/* ============================================================
   The explorer — /instructors/instructor-app and
   /students/student-app.

   Loaded after walkthrough.css (the --wt-* ink tokens),
   walkthrough-rig.css (the drawn line, and every piece of
   frame furniture these pages reuse: .wt2-tabs, the rail and
   its cards, .wt2-table, .wt2-input/.wt2-textarea, .wt2-kv,
   .wt2-topics, .wt2-modes, .wt2-note) and
   walkthrough-features.css (the kebab menus, the modal and its
   scrim, the toggle, the roster table, the spreadsheet).

   What is new here is the arrangement around all that. The
   walkthroughs are a sticky wireframe with a track of steps
   scrolling over it, and a drawn pointer that presses the
   controls for you. These two pages hold still and hand the
   reader the controls: the window sits in a plain grid beside
   a caption, every control is a link to another screen, and
   the full inventory is listed underneath so that nothing in
   the product can be missed by not thinking to click on it.

   That inverts one rule from the walkthroughs and only that
   one. There, the live controls are deliberately unmarked —
   see the note above .wt2-hot in walkthrough-rig.css, which
   still holds for those pages. Here clicking is the whole
   point, so .wtx-go carries a hand cursor, a hover state and a
   focus ring.
   ============================================================ */

/* The rig is wider than the text column it sits in. Clip rather than hide, so
   nothing inside can widen the document. walkthrough-rig.css already says this;
   repeated because these pages may one day load without it. */
.site-main { overflow-x: clip; }

/* ============================================================
   The rig
   ============================================================ */
.wtx {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: 1.6rem;
  padding: 0 clamp(1rem, 3vw, 2.6rem);
}
@media (min-width: 1280px) {
  .wtx {
    width: calc(100vw - var(--sidebar-w));
    margin-left: calc(50% - (100vw - var(--sidebar-w)) / 2);
  }
}

/* ---- Scenario chips ----
   The student page's five storylines, and the instructor page's five
   sections. Drawn boxes rather than tabs: a tab says "this pane of the thing
   you are looking at", and these say "a different thing could be happening to
   you", which is a choice about the world rather than about the view. */
.page-content .wtx-chips {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  align-items: stretch;
  gap: 0.6rem;
  margin: 0 0 1.1rem;
  padding: 0;
}
.page-content .wtx-chips li { margin: 0; display: flex; }
.page-content .wtx-chips-label {
  font-family: "Roboto Mono", monospace;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin: 0 0 0.5rem;
}
.page-content a.wtx-chip {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.15rem;
  width: 100%;
  min-height: 3.4rem;
  border: 1.5px solid var(--wt-faint);
  border-radius: 5px;
  padding: 0.5rem 0.7rem;
  font-family: "Roboto Mono", monospace;
  font-size: 0.74rem;
  line-height: 1.35;
  color: var(--wt-ink-strong);
  text-decoration: none;
  background: var(--wt-paper);
  transition: background-color 0.2s ease, color 0.2s ease, transform 0.12s ease;
}
.page-content a.wtx-chip small {
  font-size: 0.62rem;
  line-height: 1.4;
  color: var(--text-soft);
}
.page-content a.wtx-chip:hover { background: var(--wt-accent-soft); text-decoration: none; }
.page-content a.wtx-chip.is-on {
  background: var(--wt-accent);
  border-color: var(--wt-accent);
  color: var(--wt-paper);
}
.page-content a.wtx-chip.is-on small { color: var(--wt-paper); opacity: 0.86; }
.page-content a.wtx-chip.is-pressed { transform: translateY(1px); }

/* ---- The bar above the window ---- */
.wtx-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-height: 2rem;
  margin-bottom: 0.6rem;
}
.wtx-back {
  flex: none;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7rem;
  color: var(--wt-ink-strong);
  background: none;
  border: 1.5px solid var(--wt-faint);
  border-radius: 4px;
  padding: 0.25em 0.7em;
  cursor: pointer;
  transition: background-color 0.2s ease, opacity 0.2s ease;
}
.wtx-back:hover:not(:disabled) { background: var(--wt-accent-soft); }
.wtx-back:disabled { opacity: 0.35; cursor: default; }
.page-content ol.wtx-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 0;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7rem;
  color: var(--text-soft);
}
.page-content ol.wtx-crumbs li { margin: 0; }
.page-content ol.wtx-crumbs li + li::before {
  content: "\203A";
  margin-right: 0.35rem;
  color: var(--wt-faint);
}
.page-content ol.wtx-crumbs li.is-here { color: var(--wt-ink-strong); font-weight: 700; }

/* ============================================================
   Fullscreen

   The window shares its row with a caption, so on an ordinary laptop the
   drawing gets a little over half the page — and a drawn interface at half
   scale is a drawn interface you have to lean into. This gives the reader the
   whole viewport for it. The caption stays, because it is what tells them what
   they are looking at, but it narrows and the wireframe takes everything else.

   A fixed overlay rather than the Fullscreen API: no permission, no failure
   mode, works inside an iframe, and Escape still gets you out. The window's
   own type is sized from vw, so it grows with the space rather than merely
   being stretched.
   ============================================================ */
.wtx-expand {
  flex: none;
  margin-left: auto;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7rem;
  color: var(--wt-ink-strong);
  background: none;
  border: 1.5px solid var(--wt-faint);
  border-radius: 4px;
  padding: 0.25em 0.7em;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s ease;
}
.wtx-expand:hover { background: var(--wt-accent-soft); }
.wtx-expand:focus-visible { outline: 2px solid var(--wt-accent); outline-offset: 2px; }

html.wtx-full-open, html.wtx-full-open body { overflow: hidden; }
.wtx.is-full {
  position: fixed;
  inset: 0;
  z-index: 2000;
  width: 100%;
  margin: 0;
  padding: 0.7rem clamp(0.7rem, 1.6vw, 1.4rem) 0.9rem;
  background: var(--page-bg);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  overflow: hidden;
}
/* In fullscreen the chips and the index are navigation for a page the reader
   has stepped out of; the head bar stays, because Back and the breadcrumb are
   how you move. */
.wtx.is-full > .wtx-chips,
.wtx.is-full > .wtx-chips-label,
.wtx.is-full > .wtx-index { display: none; }
.wtx.is-full > .wtx-head { margin: 0; }
.wtx.is-full > .wtx-stage {
  flex: 1;
  min-height: 0;
  grid-template-columns: minmax(0, 1fr) clamp(15rem, 21vw, 20rem);
  /* An explicit row, or the grid sizes itself to its content and the canvas's
     `height: 100%` resolves against nothing — which let the window grow past
     the bottom of the viewport and lose its own lower edge. */
  grid-template-rows: minmax(0, 1fr);
  gap: 1rem;
}
.wtx.is-full .wtx-canvas { height: 100%; min-height: 0; }
.wtx.is-full .wtx-cards { overflow-y: auto; }
.wtx.is-full .wtx-card { position: static; }
/* Bigger type, because there is finally room for it. The whole wireframe is
   laid out in em, so this one number is what actually makes the drawing
   larger — widening the box alone just spreads the same small interface out.
   Roughly 20px on a 1440 laptop against 15.6px inline. */
.wtx.is-full .wtx-window { font-size: clamp(14px, 2px + 1.25vw, 24px); }
@media (max-width: 1099px) {
  .wtx.is-full > .wtx-stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
  }
  .wtx.is-full .wtx-cards { max-height: 34%; }
}

/* ---- Window and caption, side by side ---- */
.wtx-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 21.5rem;
  gap: 1.5rem;
  align-items: stretch;
  scroll-margin-top: calc(var(--banner-h) + 0.8rem);
}
@media (max-width: 1099px) {
  .wtx-stage { grid-template-columns: minmax(0, 1fr); }
}

.wtx-canvas {
  position: relative;
  min-width: 0;
  height: clamp(460px, 70vh, 760px);
}
@media (max-width: 1099px) { .wtx-canvas { height: clamp(420px, 64vh, 620px); } }
@media (max-width: 620px) { .wtx-canvas { height: clamp(380px, 68vh, 560px); } }

.wtx-window {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  border: 2px solid var(--wt-ink);
  border-radius: 8px;
  background: var(--wt-paper);
  box-shadow: 6px 6px 0 var(--wt-cast);
  overflow: hidden;
  /* Sized in px on purpose: the wireframe is a diagram, like the site chrome,
     and should not ride the fluid text root. */
  font-family: "Roboto Mono", monospace;
  font-size: clamp(11.5px, 7px + 0.6vw, 16px);
  color: var(--wt-ink);
}
.wtx-chrome {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.55em 0.85em;
  border-bottom: 2px solid var(--wt-ink);
  background: var(--wt-hatch);
}
.wtx-dot {
  width: 0.62em;
  height: 0.62em;
  border: 1.5px solid var(--wt-ink);
  border-radius: 50%;
}
.wtx-url {
  flex: 1;
  min-width: 0;
  margin-left: 0.6em;
  border: 1.5px dashed var(--wt-faint);
  border-radius: 3px;
  padding: 0.2em 0.7em;
  font-size: 0.72em;
  color: var(--text-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Shells ----
   One arrangement of the product. The instructor's manage page is a top bar,
   a rail and a pane; the student's chat is a top bar, a sidebar and a thread;
   a survey is a bare page. Only the shell holding the
   screen on show is displayed, which is what lets one window stand for the
   whole application rather than for one screen of it. */
/* position:relative so a modal's scrim, which is a child of the shell, dims
   the whole application area — rail included — rather than one pane of it. */
.wtx-shell { position: relative; display: none; flex: 1; min-height: 0; flex-direction: column; }
.wtx-shell.is-on { display: flex; }

.wtx-topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.55em 0.9em;
  border-bottom: 1.5px solid var(--wt-ink);
  background: var(--wt-hatch);
}
.wtx-brand { display: flex; align-items: center; gap: 0.45em; }
.wtx-mark {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  color: var(--wt-accent);
}
.wtx-mark svg { display: block; width: 100%; height: 100%; }
.page-content .wtx-brand b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.8em;
  font-weight: 700;
  color: var(--wt-ink-strong);
}
.wtx-topnav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.9em;
  font-size: 0.72em;
  color: var(--text-soft);
}
.wtx-avatar {
  width: 1.7em;
  height: 1.7em;
  border-radius: 50%;
  border: 1.5px solid var(--wt-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.72em;
  font-weight: 700;
  color: var(--wt-ink-strong);
  background: var(--wt-accent-soft);
}
/* The badge beside the student avatar. In the product it is the assignment
   indicator; a small filled mark is enough to say "something is there". */
.wtx-badgemark {
  width: 1.2em;
  height: 1.2em;
  border-radius: 50%;
  background: var(--wt-accent);
  color: var(--wt-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.62em;
  font-weight: 700;
}

.wtx-body { flex: 1; display: flex; align-items: stretch; min-height: 0; }
/* The product gives the rail a third of the page, and it needs about that:
   a row in it carries a name and three dated deadline lines beside a status
   pill and a menu. At the walkthroughs' fixed 12.5em every one of those wrapped
   to two lines and the card read as a pile of fragments. Proportional, with a
   floor so it survives a narrow window and a ceiling so it does not eat the
   pane in fullscreen. */
.wtx-rail {
  position: relative;
  flex: 0 0 clamp(11em, 31%, 19em);
  min-width: 0;
  padding: 1em 0.85em;
  border-right: 2px solid var(--wt-ink);
  background: var(--wt-hatch);
  overflow-y: auto;
}
@media (max-width: 900px) { .wtx-rail { flex: 0 0 clamp(9.5em, 34%, 14em); padding: 0.8em 0.6em; } }
@media (max-width: 620px) { .wtx-rail { display: none; } }

/* ---- A screen that is itself two columns ----
   The instructor's rail is the same on every screen, so it is shell furniture
   and the screens sit beside it. The student's left-hand column is not: it
   holds a list of topics on one screen, a list of chats on another, and
   nothing at all on a third. So on those pages the split belongs to the
   screen, and the screen is the whole body of the app. */
.wtx-screen.wtx-split { flex-direction: row; padding: 0; min-height: 0; overflow: hidden; }
.wtx-aside {
  flex: 0 0 13.5em;
  min-width: 0;
  padding: 0.9em 0.75em;
  border-right: 2px solid var(--wt-ink);
  background: var(--wt-hatch);
  overflow-y: auto;
}
.wtx-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 1.3em 1.5em 1.2em;
}
.wtx-main.is-flush { padding: 0; overflow: hidden; }
@media (max-width: 900px) { .wtx-aside { flex: 0 0 10.5em; padding: 0.7em 0.55em; } }
/* On a phone the two columns stack rather than one of them disappearing. The
   product collapses this panel behind a toggle at this width, so hiding it
   would not be wrong — but the panel is where the progress meter lives, and
   the progress meter is the one thing on the chat screen that answers back
   when you type into it. Keeping it above the thread is worth the height. */
@media (max-width: 620px) {
  .wtx-screen.wtx-split { flex-direction: column; }
  .wtx-aside {
    flex: 0 0 auto;
    max-height: 42%;
    border-right: 0;
    border-bottom: 2px solid var(--wt-ink);
  }
  .wtx-main { padding: 0.9em 0.95em 1em; }
}

/* ---- Screens ----
   Stacked in one grid cell, exactly one shown. A screen taller than the
   window scrolls inside it, which is also true of the product. */
.wtx-screens {
  flex: 1;
  min-width: 0;
  display: grid;
  overflow: hidden;
}
.wtx-screen {
  grid-area: 1 / 1;
  display: none;
  flex-direction: column;
  min-width: 0;
  padding: 1.6em 1.9em 1.5em;
  overflow-y: auto;
}
.wtx-screen.is-on { display: flex; }
@media (max-width: 620px) { .wtx-screen { padding: 1em 1em 1.1em; } }

/* Elements rise in as a screen arrives, the same short stagger the
   walkthroughs use. A split screen staggers the contents of its main column
   instead: its two children are the columns themselves, and animating those
   reads as the app rebuilding rather than as a screen arriving. */
.wtx-screen.is-on > *,
.wtx-screen.wtx-split.is-on > .wtx-main > * {
  animation: wtx-rise 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.wtx-screen.wtx-split.is-on > * { animation: none; }
.wtx-screen.is-on > :nth-child(1),
.wtx-screen.wtx-split.is-on > .wtx-main > :nth-child(1) { animation-delay: 0.02s; }
.wtx-screen.is-on > :nth-child(2),
.wtx-screen.wtx-split.is-on > .wtx-main > :nth-child(2) { animation-delay: 0.07s; }
.wtx-screen.is-on > :nth-child(3),
.wtx-screen.wtx-split.is-on > .wtx-main > :nth-child(3) { animation-delay: 0.12s; }
.wtx-screen.is-on > :nth-child(4),
.wtx-screen.wtx-split.is-on > .wtx-main > :nth-child(4) { animation-delay: 0.17s; }
.wtx-screen.is-on > :nth-child(5) { animation-delay: 0.22s; }
.wtx-screen.is-on > :nth-child(6) { animation-delay: 0.27s; }
@keyframes wtx-rise {
  from { opacity: 0; transform: translateY(0.6em); }
  to { opacity: 1; transform: none; }
}

/* ============================================================
   Controls the reader presses

   The opposite of the walkthroughs' rule, and deliberately so: there the
   live controls are an unannounced easter egg, here they are the document.
   Everything drawn that leads somewhere says so.
   ============================================================ */
/* A link inside the drawing is a drawn control, not a link: it takes the ink
   colour of whatever it is drawn as, and never the site's link blue or an
   underline.
   The :not()s matter. Without them this rule out-specifies .wtx-btn.is-primary
   — two classes and a type against two classes — and every filled button in
   the wireframe rendered its label in the surrounding ink colour instead of
   paper, which on the accent fill is dark text on a dark plate. Anything that
   sets its own colour has to be exempt from the reset rather than fight it. */
.wtx-window a.wtx-go:not(.wtx-btn):not(.wt2-modal-btn),
.wtx-window a.wtx-go:not(.wtx-btn):not(.wt2-modal-btn):hover {
  color: inherit;
}
.wtx-window a.wtx-go,
.wtx-window a.wtx-go:hover { text-decoration: none; }
a.wtx-go {
  cursor: pointer;
  border-radius: 3px;
  transition: background-color 0.16s ease, transform 0.1s ease;
}
a.wtx-go:hover { background: var(--wt-accent-soft); }
a.wtx-go:focus-visible {
  outline: 2px solid var(--wt-accent);
  outline-offset: 2px;
}
a.wtx-go.is-pressed { background: var(--wt-accent); color: var(--wt-paper); }
/* A pressed control that is a filled box already reads as pressed by sinking
   into its own shadow instead. */
a.wtx-go.wtx-btn.is-pressed,
a.wtx-go.wt2-modal-btn.is-pressed {
  transform: translate(2px, 2px);
  box-shadow: none;
}
/* A row, a card or a table cell that is a way somewhere lights the whole of
   itself rather than just its text. */
a.wtx-go.wtx-block { display: block; }

/* ---- Controls that change in place ----
   A radio, a checkbox, a rating, a toggle. They do not navigate, so they are
   not links — but they are just as pressable as the links beside them and
   have to look it. js/app-explorer.js drives them by family; see PICK there.
   Kept in one list so a control cannot end up live to the script and dead to
   the eye, or the reverse. */
.wtx-radio, .wtx-x, .wtx-box, .wtx-choice, .wt2-toggle,
.wtx-answers li, .wtx-window .wt2-mode, [data-says] {
  cursor: pointer;
  transition: background-color 0.16s ease, border-color 0.16s ease, transform 0.1s ease;
}
.wtx-radio:hover, .wtx-x:hover, .wtx-box:hover { border-color: var(--wt-accent); }
.wtx-answers li:hover, .wtx-window .wt2-mode:hover { background: var(--wt-accent-soft); }
.wtx-choice:hover { border-color: var(--wt-accent); background: var(--wt-accent-soft); }
.wtx-radio:focus-visible, .wtx-x:focus-visible, .wtx-box:focus-visible,
.wtx-choice:focus-visible, .wt2-toggle:focus-visible,
.wtx-answers li:focus-visible, .wtx-window .wt2-mode:focus-visible,
[data-says]:focus-visible {
  outline: 2px solid var(--wt-accent);
  outline-offset: 2px;
}
.wtx-radio.is-pressed, .wtx-x.is-pressed, .wtx-box.is-pressed { transform: scale(1.25); }
.wtx-choice.is-pressed, .wtx-answers li.is-pressed,
.wtx-window .wt2-mode.is-pressed { background: var(--wt-accent-soft); }
.wtx-btn.is-pressed, [data-says].is-pressed { transform: translate(2px, 2px); box-shadow: none; }
/* The QuickMatch toggle flips when pressed, as well as when its screen says so. */
.wt2-toggle.is-on { background: var(--wt-accent); border-color: var(--wt-accent); }
.wt2-toggle.is-on .wt2-toggle-thumb {
  left: calc(100% - 0.75em - 0.13em);
  background: var(--wt-paper);
}

/* What a button that submits nothing says for itself. */
.page-content .wtx-said {
  flex: 1 1 100%;
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  line-height: 1.5;
  color: var(--wt-accent);
  text-align: right;
  margin: 0.4em 0 0;
  opacity: 0;
  transform: translateY(-0.2em);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.page-content .wtx-said.is-on { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .page-content .wtx-said { transition: none; }
  .wtx-radio.is-pressed, .wtx-x.is-pressed, .wtx-box.is-pressed,
  .wtx-btn.is-pressed, [data-says].is-pressed { transform: none; }
}

/* ---- Buttons ---- */
.wtx-btn {
  display: inline-block;
  border: 1.5px solid var(--wt-ink-strong);
  border-radius: 4px;
  padding: 0.4em 1.2em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.74em;
  font-weight: 700;
  color: var(--wt-ink-strong);
  background: var(--wt-paper);
  box-shadow: 2px 2px 0 var(--wt-cast);
  white-space: nowrap;
}
.wtx-btn.is-primary {
  background: var(--wt-accent);
  border-color: var(--wt-accent);
  color: var(--wt-paper);
}
.wtx-btn.is-ghost {
  border-color: var(--wt-faint);
  color: var(--text-soft);
  box-shadow: none;
}
.wtx-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.7em;
  margin-top: auto;
  padding-top: 1.1em;
}
.wtx-actions.is-split { justify-content: space-between; }
.page-content .wtx-actions .wtx-note {
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0;
}

/* ============================================================
   Product furniture new to these pages
   ============================================================ */

/* ---- A row in the rail ----
   One assignment, or one QuickMatch. The product lays this out as a two-column
   row: the name and its dated hint lines on the left, the state and the menu
   held together at the right. Inheriting the walkthroughs' .wt2-railcard here
   was wrong — that one is built for a single card in a rail that only ever
   holds one, so it stacks everything, and with a status pill and a kebab added
   the result was a pile: the date under a bare label, the badge on its own
   line, the menu adrift under that. */
.wtx-railbox {
  border: 1.5px solid var(--wt-ink);
  border-radius: 3px;
  margin-bottom: 0.9em;
}
.wtx-railhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5em;
  padding: 0.5em 0.55em;
  border-bottom: 1.5px solid var(--wt-ink);
  font-size: 0.68em;
  font-weight: 700;
  line-height: 1.3;
  color: var(--wt-ink-strong);
}
.page-content .wtx-railempty {
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0;
  padding: 0.7em 0.6em;
}
.wtx-rowitem {
  display: flex;
  align-items: flex-start;
  gap: 0.4em;
  padding: 0.55em 0.5em 0.6em;
  border-bottom: 1.5px dashed var(--wt-faint);
}
.wtx-railbox .wtx-rowitem:last-child { border-bottom: 0; }
.wtx-rowitem.is-on {
  background: var(--wt-accent-soft);
  border-left: 3px solid var(--wt-accent);
  padding-left: calc(0.5em - 3px);
}
.wtx-rowitem-main { flex: 1; min-width: 0; }
.page-content .wtx-rowitem-main > b {
  display: block;
  font-size: 0.66em;
  line-height: 1.35;
  color: var(--wt-ink-strong);
  margin-bottom: 0.15em;
}
.page-content .wtx-rowitem-main > span {
  display: block;
  font-size: 0.56em;
  line-height: 1.45;
  color: var(--text-soft);
}
.page-content .wtx-rowitem-main > span > b { color: var(--wt-ink); font-weight: 700; }
/* The state and the menu travel together at the right edge, as one control
   cluster rather than two things that happen to be near each other. */
.wtx-rowitem-side {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.15em;
  margin-top: 0.05em;
}
.wtx-state {
  display: inline-block;
  border: 1.5px solid var(--wt-accent);
  border-radius: 3px;
  padding: 0.15em 0.4em;
  font-size: 0.54em;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--wt-paper);
  background: var(--wt-accent);
}
.wtx-state.is-quiet {
  background: none;
  border-color: var(--wt-faint);
  color: var(--text-soft);
  font-weight: 400;
}
.wtx-rowitem-side .wtx-kebab { font-size: 1.1em; padding: 0 0.1em; }
.wtx-rowitem-side .wt2-toggle { flex: none; }

/* ---- The white page a survey or an onboarding step is drawn on ---- */
.wtx-panel {
  border: 1.5px solid var(--wt-ink);
  border-radius: 5px;
  background: var(--wt-paper);
  padding: 1.2em 1.3em 1.3em;
}
.page-content .wtx-h {
  font-family: "Roboto Mono", monospace;
  font-size: 0.95em;
  font-weight: 700;
  line-height: 1.35;
  color: var(--wt-ink-strong);
  margin: 0 0 0.5em;
}
.page-content .wtx-p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.65;
  color: var(--wt-ink);
  margin: 0 0 0.7em;
}
.page-content .wtx-p.is-soft { color: var(--text-soft); }
.page-content .wtx-p b { color: var(--wt-ink-strong); font-weight: 700; }
.page-content ul.wtx-list {
  list-style: none;
  margin: 0 0 0.9em;
  padding: 0;
}
.page-content ul.wtx-list li {
  position: relative;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7em;
  line-height: 1.6;
  color: var(--wt-ink);
  margin: 0 0 0.3em;
  padding-left: 1em;
}
.page-content ul.wtx-list li::before {
  content: "\2022";
  position: absolute;
  left: 0.15em;
  color: var(--wt-accent);
}

/* ---- Checkbox rows (the consent screen) ---- */
.page-content ul.wtx-checks { list-style: none; margin: 0.5em 0 0; padding: 0; }
.page-content ul.wtx-checks li {
  display: flex;
  align-items: flex-start;
  gap: 0.6em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7em;
  line-height: 1.55;
  color: var(--wt-ink-strong);
  margin: 0 0 0.55em;
}
.wtx-box {
  flex: none;
  width: 1em;
  height: 1em;
  margin-top: 0.2em;
  border: 1.5px solid var(--wt-ink);
  border-radius: 2px;
  background: var(--wt-paper);
}
.wtx-box.is-on { background: var(--wt-accent); border-color: var(--wt-accent); }
.wtx-box.is-on::after {
  content: "\2713";
  display: block;
  margin-top: -0.15em;
  text-align: center;
  font-size: 0.85em;
  font-weight: 700;
  color: var(--wt-paper);
}

/* ---- Fields ---- */
.wtx-input, .wtx-textarea {
  display: block;
  border: 1.5px solid var(--wt-ink);
  border-radius: 4px;
  padding: 0.5em 0.7em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.74em;
  line-height: 1.6;
  color: var(--wt-ink-strong);
  background: var(--wt-paper);
}
.wtx-input.is-empty, .wtx-textarea.is-empty { color: var(--wt-faint); }
.wtx-textarea { min-height: 3.6em; }
.page-content .wtx-label {
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin: 0 0 0.35em;
}
.wtx-field + .wtx-field { margin-top: 0.9em; }
.wtx-fieldrow { display: grid; grid-template-columns: 1fr 1fr; gap: 1em; }
@media (max-width: 620px) { .wtx-fieldrow { grid-template-columns: 1fr; } }

/* A select with a chevron, drawn open on the screens that are about the
   choice it holds. */
.wtx-select {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5em;
  border: 1.5px solid var(--wt-ink);
  border-radius: 4px;
  padding: 0.42em 0.65em;
  font-size: 0.74em;
  color: var(--wt-ink-strong);
  background: var(--wt-paper);
}
.wtx-selectwrap { position: relative; }
.page-content ul.wtx-menu {
  display: none;
  position: absolute;
  z-index: 6;
  top: calc(100% + 0.3em);
  left: 0;
  min-width: 100%;
  list-style: none;
  margin: 0;
  padding: 0.3em;
  border: 1.5px solid var(--wt-ink);
  border-radius: 4px;
  background: var(--wt-paper);
  box-shadow: 3px 3px 0 var(--wt-cast);
  text-align: left;
}
.page-content ul.wtx-menu.is-right { left: auto; right: 0; }
.page-content ul.wtx-menu li {
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.9;
  color: var(--wt-ink);
  padding: 0 0.55em;
  margin: 0;
  border-radius: 2px;
  white-space: nowrap;
}
.page-content ul.wtx-menu li.is-on {
  background: var(--wt-accent);
  color: var(--wt-paper);
  font-weight: 700;
}
.page-content ul.wtx-menu li.is-danger { font-weight: 700; color: var(--wt-ink-strong); }
/* A menu is open because the screen on show says it is: each menu is named
   with data-menu, each screen lists the names it wants open in data-open, and
   js/app-explorer.js marks the matches. So every open menu is a state the
   reader can be sent straight to, and adding one is not also an edit here.

   The selector has to carry the same `.page-content ul` weight the base rule
   above does. Written as a bare `.wtx-menu.is-open` it lost to it on
   specificity — 0,2,0 against 0,2,1 — and every menu in the drawing stayed
   display:none however open the script believed it was. */
.page-content ul.wtx-menu.is-open,
ul.wtx-menu.is-open { display: block; }
.wtx-menu-anchor { position: relative; display: inline-block; }
/* A menu hangs below the row it belongs to, and two ancestors would clip it:
   site.css gives every table overflow:hidden for its rounded corners, and
   .wt2-tablewrap sets overflow-x for wide ones, which makes the other axis
   compute to auto and clip too. walkthrough-features.css already says this for
   its own anchors; these are a different class, so it has to be said again. */
.wt2-tablewrap:has(.wtx-menu-anchor),
.page-content table.wt2-table:has(.wtx-menu-anchor) { overflow: visible; }
/* A menu drawn at its ordinary size, beside a caption explaining it in depth,
   reads as an afterthought rather than as the subject. On the screens whose
   whole business is a menu it grows, the way the walkthroughs' does. */
/* The menu arrives rather than appearing. It settles at its natural size:
   the walkthroughs end this same animation at scale(1.12), because there the
   menu is the whole lesson and has to outweigh a wireframe with nothing else
   happening on it. Here the caption card beside the window carries that
   weight, and the scale-up did real damage — a menu wider than its anchor
   grew outwards past the edge of the drawn window, which is how the class
   selector's menu ended up hanging off the side of the browser frame. */
.page-content ul.wtx-menu.is-open,
ul.wtx-menu.is-open {
  transform-origin: top center;
  animation: wtx-menu-pop 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
  box-shadow: 5px 5px 0 var(--wt-cast);
}
@keyframes wtx-menu-pop {
  from { opacity: 0; transform: translateY(-0.3em); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .page-content ul.wtx-menu.is-open,
  ul.wtx-menu.is-open { animation: none; }
}
/* A menu is only as wide as it needs to be, and never wider than the pane it
   drops into — the class selector's items are long enough to matter. */
.page-content ul.wtx-menu { max-width: min(20em, 88vw); }

/* ---- letting an open menu out of its box ----
   A menu is absolutely positioned with a z-index, which ought to be enough to
   put it over the screen behind it. It was not, for two reasons, and both had
   to be answered or the menus rendered *underneath* the page — the drawn box
   visible, the text of the paragraph below it printing straight through.

   1. Stacking. The entrance animation on a screen's children animates
      `transform` with fill-mode `both`, and an element with a filled
      transform animation is a stacking context. So every direct child of a
      screen became one, the menu's z-index was scoped inside whichever child
      held it, and any later sibling — the paragraph under the roster — simply
      painted over the lot. The child holding an open menu therefore has to
      out-rank its siblings itself.

   2. Clipping. The rail scrolls, and a scroll container clips its children on
      both axes; the class selector's menu is wider than the rail, so it was
      cut off mid-word. While a menu is open the rail does not clip.

   Both are written with :has(), so nothing has to be marked up for it and a
   menu added later is covered on the day it is added. */
.wtx-screen.is-on > *:has(.wtx-menu.is-open),
.wtx-screen.is-on > .wtx-main > *:has(.wtx-menu.is-open),
.wtx-screen.is-on > .wtx-aside:has(.wtx-menu.is-open) {
  position: relative;
  z-index: 20;
}
.wtx-body:has(.wtx-menu.is-open) > .wtx-rail,
.wtx-screen.is-on > .wtx-aside:has(.wtx-menu.is-open) {
  overflow: visible;
  z-index: 20;
}
/* The rail is a flex item, so it needs a position for the z-index to count. */
.wtx-body:has(.wtx-menu.is-open) > .wtx-rail { position: relative; }
/* ...and the screens beside it must not out-rank it. */
.wtx-body:has(.wtx-rail .wtx-menu.is-open) > .wtx-screens { z-index: 0; }

/* ---- Kebab ---- */
.page-content span.wtx-kebab,
.page-content a.wtx-kebab {
  display: inline-block;
  font-family: "Roboto Mono", monospace;
  font-size: 1.5em;
  font-weight: 700;
  line-height: 0.85;
  letter-spacing: -1px;
  color: var(--wt-ink-strong);
  padding: 0.05em 0.22em;
  border-radius: 3px;
}

/* ---- Tabs ---- */
.wtx-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2em;
  border-bottom: 1.5px solid var(--wt-faint);
  margin-bottom: 1.1em;
  font-size: 0.72em;
  flex: none;
}
.wtx-tabs a, .wtx-tabs span {
  padding-bottom: 0.5em;
  color: var(--text-soft);
  white-space: nowrap;
}
.wtx-tabs .is-on {
  color: var(--wt-ink-strong);
  font-weight: 700;
  box-shadow: inset 0 -2px 0 var(--wt-accent);
}

/* ---- Pills and small marks ---- */
.wtx-pill {
  display: inline-block;
  border: 1.5px solid var(--wt-accent);
  border-radius: 2px;
  padding: 0.1em 0.45em;
  font-size: 0.58em;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--wt-paper);
  background: var(--wt-accent);
  white-space: nowrap;
}
.wtx-pill.is-quiet {
  background: none;
  border-color: var(--wt-faint);
  color: var(--text-soft);
  font-weight: 400;
}
.page-content .wtx-ghost {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.5;
  color: var(--text-soft);
  border: 1.5px dashed var(--wt-faint);
  border-radius: 4px;
  padding: 0.45em 0.65em;
  margin: 0.3em 0 0;
}

/* ---- A notice inside the product ----
   Suspension, a Chat with Guide offer, a deadline warning. The product puts
   these across the top of the pane; here they are a bordered band with the
   accent down one side, which is how this wireframe already marks the thing
   that matters on a screen. */
.wtx-banner {
  border: 1.5px solid var(--wt-ink);
  border-left: 3px solid var(--wt-accent);
  border-radius: 4px;
  background: var(--wt-accent-soft);
  padding: 0.7em 0.85em;
  margin-bottom: 1.1em;
  flex: none;
}
.page-content .wtx-banner b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.76em;
  font-weight: 700;
  color: var(--wt-ink-strong);
  margin-bottom: 0.25em;
}
.page-content .wtx-banner p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.6;
  color: var(--wt-ink);
  margin: 0;
}
.wtx-banner .wtx-actions { margin-top: 0.6em; padding-top: 0; justify-content: flex-start; }

/* ---- Empty state ----
   Waiting for a match, an empty chat list, a class with nothing in it. */
.wtx-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  text-align: center;
  border: 1.5px dashed var(--wt-faint);
  border-radius: 5px;
  padding: 1.6em 1.2em;
  min-height: 8em;
}
.page-content .wtx-empty b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.82em;
  color: var(--wt-ink-strong);
}
.page-content .wtx-empty p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.6;
  color: var(--text-soft);
  max-width: 26em;
  margin: 0;
}
/* The waiting state gets the one piece of motion on either page that is not
   a line being drawn: three dots, because that is what waiting looks like. */
.wtx-wait {
  display: flex;
  gap: 0.4em;
}
.wtx-wait i {
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: var(--wt-accent);
  animation: wtx-wait 1.4s ease-in-out infinite;
}
.wtx-wait i:nth-child(2) { animation-delay: 0.18s; }
.wtx-wait i:nth-child(3) { animation-delay: 0.36s; }
@keyframes wtx-wait {
  0%, 60%, 100% { opacity: 0.25; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-0.22em); }
}

/* ---- The topic list in the student's sidebar ----
   The dot beside a topic is the whole of Sway's "is anyone available to
   disagree with you" interface, so it has to read clearly at this size:
   filled for a match, hollow for still looking. The product uses green and
   orange; this wireframe has one accent and no colour vocabulary of its own,
   so filled-versus-hollow carries it, and the words underneath say which. */
.page-content ul.wtx-topics { list-style: none; margin: 0; padding: 0; }
.page-content ul.wtx-topics li { margin: 0 0 0.15em; }
.wtx-topic {
  display: block;
  padding: 0.5em 0.5em;
  border-radius: 4px;
}
.wtx-topic-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5em; }
.page-content .wtx-topic b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  line-height: 1.4;
  color: var(--wt-ink-strong);
}
.page-content .wtx-topic p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.58em;
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0.15em 0 0;
}
/* The status dot is the one place this wireframe uses colour from the product
   rather than its own ink-and-one-accent palette, and it earns the exception:
   green against orange is the entire interface for "is there anybody to
   disagree with you yet". Drawn hollow-against-filled instead, the screen
   stopped saying the thing it exists to say. The two values are the product's
   own (static/css/base.css). */
:root {
  --wtx-available: #28a745;
  --wtx-unavailable: #ff8c00;
}
.wtx-dot-status {
  flex: none;
  width: 0.8em;
  height: 0.8em;
  border-radius: 50%;
  background: var(--wtx-unavailable);
  /* A ring in the paper colour keeps both dots legible on the tinted row of a
     matched topic, and in dark mode, without touching the hues themselves. */
  box-shadow: 0 0 0 1.5px var(--wt-paper);
}
.wtx-dot-status.is-ready { background: var(--wtx-available); }
.wtx-topic.is-ready { background: var(--wt-accent-soft); }
.wtx-legend {
  border: 1.5px dashed var(--wt-faint);
  border-radius: 4px;
  padding: 0.5em 0.55em;
  margin-bottom: 0.7em;
}
.page-content .wtx-legend p {
  display: flex;
  align-items: center;
  gap: 0.45em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.56em;
  line-height: 1.45;
  color: var(--text-soft);
  margin: 0 0 0.3em;
}
.page-content .wtx-legend p:last-child { margin: 0; }

/* ============================================================
   The opinion survey matrix
   ============================================================ */
.wtx-matrixwrap { overflow-x: auto; }
.page-content table.wtx-matrix {
  width: 100%;
  border-collapse: collapse;
  border: 1.5px solid var(--wt-ink);
  background: var(--wt-paper);
  box-shadow: none;
  border-radius: 0;
  margin: 0;
  font-family: "Roboto Mono", monospace;
}
.page-content table.wtx-matrix th,
.page-content table.wtx-matrix td {
  border: 1.5px solid var(--wt-faint);
  padding: 0.5em 0.35em;
  text-align: center;
  font-size: 0.6em;
  line-height: 1.35;
  vertical-align: middle;
}
.page-content table.wtx-matrix th {
  background: var(--wt-hatch);
  color: var(--wt-ink-strong);
  font-weight: 700;
}
.page-content table.wtx-matrix td:first-child,
.page-content table.wtx-matrix th:first-child {
  text-align: left;
  font-size: 0.62em;
  font-weight: 400;
  color: var(--wt-ink);
  min-width: 11em;
}
.wtx-radio {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  border-radius: 50%;
  border: 1.5px solid var(--wt-ink);
}
.wtx-radio.is-on {
  border-color: var(--wt-accent);
  background: var(--wt-accent);
  box-shadow: inset 0 0 0 2px var(--wt-paper);
}
.wtx-x {
  display: inline-block;
  width: 1em;
  height: 1em;
  line-height: 0.9em;
  border: 1.5px solid var(--wt-faint);
  border-radius: 2px;
  color: var(--text-soft);
  font-size: 0.85em;
}
.wtx-x.is-on { border-color: var(--wt-accent); background: var(--wt-accent); color: var(--wt-paper); }

/* ---- Big choice boxes (the feedback survey's five ratings) ---- */
.page-content ul.wtx-choices {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55em;
  margin: 0.5em 0 1em;
  padding: 0;
}
.page-content ul.wtx-choices li { margin: 0; flex: 1 1 6em; }
.wtx-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2em;
  border: 1.5px solid var(--wt-faint);
  border-radius: 4px;
  padding: 0.6em 0.4em;
  font-size: 0.7em;
  color: var(--wt-ink-strong);
  text-align: center;
  background: var(--wt-paper);
}
.wtx-choice.is-on { border-color: var(--wt-accent); background: var(--wt-accent-soft); font-weight: 700; }
.wtx-choice span { font-size: 1.1em; }

/* ---- The understanding quiz ---- */
.wtx-quiz { border: 1.5px solid var(--wt-ink); border-radius: 5px; padding: 0.9em 1em; margin-bottom: 0.8em; }
.page-content .wtx-quiz > b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.55;
  color: var(--wt-ink-strong);
  margin-bottom: 0.55em;
}
.page-content ul.wtx-answers { list-style: none; margin: 0; padding: 0; }
.page-content ul.wtx-answers li {
  display: flex;
  align-items: flex-start;
  gap: 0.55em;
  border-radius: 4px;
  background: var(--wt-hatch);
  padding: 0.45em 0.6em;
  margin: 0 0 0.3em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  line-height: 1.5;
  color: var(--wt-ink);
}
.page-content ul.wtx-answers li.is-on { background: var(--wt-accent-soft); color: var(--wt-ink-strong); }
.wtx-answers .wtx-radio { margin-top: 0.15em; }

/* ---- Spinner, for the screens that are genuinely a wait ---- */
.wtx-spin {
  width: 1.4em;
  height: 1.4em;
  border: 2px solid var(--wt-faint);
  border-top-color: var(--wt-accent);
  border-radius: 50%;
  animation: wtx-spin 0.9s linear infinite;
}
@keyframes wtx-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .wtx-spin { animation: none; } }

/* ============================================================
   The chat
   ============================================================ */
.wtx-chat {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 0;
}
.wtx-thread {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 1.2em 1.4em 0.8em;
  display: flex;
  flex-direction: column;
  gap: 0.55em;
  /* The strokes overshoot their boxes by seven pixels, so a bubble against
     the edge would have its ink clipped by the scroller. */
  scroll-padding: 0.5em;
}
@media (max-width: 620px) { .wtx-thread { padding: 0.9em 0.9em 0.6em; } }
.wtx-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 84%;
}
.wtx-row.is-mine { align-self: flex-end; align-items: flex-end; }
.wtx-row.is-guide { max-width: 92%; }
.wtx-row.is-cta { align-self: center; max-width: none; margin-top: 0.5em; }
.page-content .wtx-who {
  font-family: "Roboto Mono", monospace;
  font-size: 0.6em;
  letter-spacing: 0.06em;
  color: var(--text-soft);
  margin: 0 0 0.2em 0.3em;
}
.wtx-bubble {
  position: relative;
  border: 1.5px solid var(--wt-faint);
  border-radius: 6px;
  padding: 0.5em 0.7em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.6;
  color: var(--wt-ink);
  background: var(--wt-paper);
  overflow-wrap: anywhere;
}
.wtx-row.is-mine .wtx-bubble {
  background: var(--wt-accent-soft);
  color: var(--wt-ink-strong);
}
.wtx-row.is-guide .wtx-bubble { background: var(--wt-hatch); }
.page-content .wtx-bubble p { font-family: inherit; font-size: 1em; line-height: 1.6; margin: 0 0 0.5em; }
.page-content .wtx-bubble p:last-child { margin: 0; }
.page-content .wtx-bubble i { font-style: italic; color: var(--wt-ink-strong); }
.page-content .wtx-bubble ul { margin: 0.4em 0; padding-left: 1.1em; }
.page-content .wtx-bubble li { font-family: inherit; font-size: 1em; line-height: 1.55; margin: 0 0 0.2em; }
.page-content .wtx-stamp {
  font-family: "Roboto Mono", monospace;
  font-size: 0.55em;
  color: var(--text-soft);
  margin: 0.15em 0.3em 0;
}

/* The typing indicator. The one thing on these pages that has to move to
   mean anything at all. */
.wtx-dots { display: flex; align-items: center; gap: 0.28em; padding: 0.7em 0.8em; }
.wtx-dots i {
  width: 0.35em;
  height: 0.35em;
  border-radius: 50%;
  background: var(--wt-ink);
  animation: wtx-type 1.1s ease-in-out infinite;
}
.wtx-dots i:nth-child(2) { animation-delay: 0.14s; }
.wtx-dots i:nth-child(3) { animation-delay: 0.28s; }
@keyframes wtx-type {
  0%, 65%, 100% { opacity: 0.28; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-0.18em); }
}

.wtx-composer {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin: 0.4em 1.4em 1.1em;
  border: 1.5px dashed var(--wt-faint);
  border-radius: 20px;
  padding: 0.35em 0.5em 0.35em 0.8em;
  background: var(--wt-paper);
}
@media (max-width: 620px) { .wtx-composer { margin: 0.4em 0.9em 0.9em; } }
.wtx-composer .wtx-icon { flex: none; font-size: 0.85em; color: var(--text-soft); }
.wtx-say {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  font-family: "Roboto Mono", monospace;
  font-size: 0.7em;
  line-height: 1.6;
  color: var(--wt-ink-strong);
  padding: 0.3em 0;
}
.wtx-say::placeholder { color: var(--text-soft); }
.wtx-say:focus { outline: none; }
.wtx-composer:focus-within { border-style: solid; border-color: var(--wt-accent); }
.wtx-send {
  flex: none;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 0.95em;
  line-height: 1;
  color: var(--wt-accent);
  padding: 0.2em 0.35em;
  border-radius: 4px;
}
.wtx-send:hover { background: var(--wt-accent-soft); }
.wtx-send:focus-visible { outline: 2px solid var(--wt-accent); outline-offset: 1px; }

/* ---- The chat sidebar ---- */
.wtx-side-card {
  border-radius: 4px;
  background: var(--wt-accent-soft);
  border-left: 3px solid var(--wt-accent);
  padding: 0.7em 0.65em;
  margin-bottom: 0.8em;
}
.page-content .wtx-side-card b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.4;
  color: var(--wt-ink-strong);
  margin-bottom: 0.35em;
}
.page-content .wtx-side-card p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.6em;
  line-height: 1.55;
  color: var(--text-soft);
  margin: 0;
}
.wtx-progress { margin: 0.5em 0 0.2em; }
.wtx-progress-track {
  height: 4px;
  border-radius: 2px;
  background: var(--wt-faint);
  overflow: hidden;
}
.wtx-progress-fill {
  display: block;
  height: 100%;
  width: 40%;
  background: var(--wt-accent);
  transition: width 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.page-content .wtx-progress-label {
  display: flex;
  justify-content: space-between;
  font-family: "Roboto Mono", monospace;
  font-size: 0.58em;
  color: var(--text-soft);
  margin: 0 0 0.3em;
}
.wtx-progress-num { font-weight: 700; color: var(--wt-ink-strong); }

.wtx-chatrow {
  display: flex;
  align-items: flex-start;
  gap: 0.5em;
  padding: 0.5em 0.5em;
  border-radius: 4px;
}
.wtx-chatrow.is-on { background: var(--wt-accent-soft); }
.wtx-chatrow .wtx-avatar { flex: none; }
.wtx-chatrow > div { min-width: 0; }
.page-content .wtx-chatrow b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  line-height: 1.4;
  color: var(--wt-ink-strong);
}
.page-content .wtx-chatrow span {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.58em;
  line-height: 1.5;
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wtx-unread {
  flex: none;
  width: 0.5em;
  height: 0.5em;
  border-radius: 50%;
  background: var(--wt-accent);
  margin-top: 0.4em;
}

/* ============================================================
   Modals
   ============================================================ */
.wtx-scrim {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 7;
  background: rgba(20, 16, 30, 0.32);
  align-items: center;
  justify-content: center;
  padding: 1.2em;
}
html.dark-mode .wtx-scrim { background: rgba(0, 0, 0, 0.55); }
.wtx-window[data-modal] .wtx-scrim { display: flex; }
/* Which modal, like which menu, is marked by the script from the screen's own
   data-modal rather than enumerated here. */
.wtx-modal { display: none; }
.wtx-modal.is-on { display: block; }
.wtx-modal {
  width: min(24em, 100%);
  max-height: 100%;
  overflow-y: auto;
  border: 1.5px solid var(--wt-ink);
  border-radius: 6px;
  background: var(--wt-paper);
  box-shadow: 5px 5px 0 var(--wt-cast);
  animation: wtx-modal-in 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes wtx-modal-in {
  from { opacity: 0; transform: scale(0.94) translateY(0.4em); }
  to { opacity: 1; transform: none; }
}
.wtx-modal-head {
  padding: 0.6em 0.8em;
  border-bottom: 1.5px solid var(--wt-ink);
  background: var(--wt-hatch);
  font-size: 0.8em;
  font-weight: 700;
  color: var(--wt-ink-strong);
}
.wtx-modal-body { padding: 0.85em 0.9em 0.3em; }
.page-content .wtx-modal-body p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.7;
  color: var(--text-soft);
  margin: 0 0 0.7em;
}
.page-content .wtx-modal-body p b { color: var(--wt-ink-strong); }
.wtx-modal-warn {
  border-left: 2px solid var(--wt-ink-strong);
  padding: 0.1em 0 0.1em 0.6em;
  margin: 0.7em 0;
}
.page-content .wtx-modal-warn p { color: var(--wt-ink-strong); margin: 0; }
.wtx-modal-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0.6em;
  padding: 0.5em 0.8em 0.85em;
}

/* ---- how fast the lines draw ----
   The reveal itself is walkthrough-rig.css's, and so is the stagger that
   spreads it: `--b` is a box's place in its screen, `--i` an edge's place in
   the box, and the delay is 0.055s per box plus 0.035s per edge. That is
   judged for a guided tour, where a screen arrives every few seconds and has
   the reader's whole attention while it draws.

   Here the reader is clicking, and a screen has to be finished by the time
   they have looked at it. A screen with sixty boxes on it — the roster, the
   survey matrix, the spreadsheet — took three and a half seconds to finish
   under the tour's timing, which does not read as drawing. It reads as a
   wireframe with no lines.

   So the step is shorter and, more importantly, clamped: past the thirtieth
   box the delay stops growing, so a big screen and a small one both settle in
   about six tenths of a second. Scoped to #wtx, which is these two pages only. */
html.wt2-ink #wtx .hi-on > .hi-ink:not(.hi-dash) path,
html.wt2-ink #wtx .hi-on > .hi-dash path {
  animation-delay: calc(min(var(--b, 0), 30) * 0.014s + min(var(--i, 0), 8) * 0.022s);
}

/* ============================================================
   Borrowed from the walkthroughs

   These pages reuse the walkthroughs' furniture wholesale — it is the same
   product drawn in the same hand, and a second copy of it would drift. A few
   of those components carry state rules keyed to `.wt2-window`, which is the
   walkthroughs' window and not this one, so their state has to be restated
   here against `.wtx-window`. Everything in this block is that and only that.
   ============================================================ */

/* The rail card is display:none until the walkthrough's rig says an assignment
   exists. Here one always does. */
.wtx-window .wt2-railcard { display: block; }
/* A row in the rail that is not the one selected: present, quiet, and not a
   way anywhere. Completed assignments sit in the list like this. */
.page-content .wtx-rail-quiet {
  font-family: "Roboto Mono", monospace;
  font-size: 0.62em;
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0;
  padding: 0.55em 0.6em;
  border-top: 1.5px dashed var(--wt-faint);
}
/* Which row in the rail is selected follows the screen, so it is the window's
   data-rail that says — the same attribute the walkthroughs use for the same
   purpose. */
.wtx-window[data-rail="quickmatch"] .wt2-railcard {
  background: none;
  border-left-color: var(--wt-faint);
}
.wtx-window:not([data-rail="quickmatch"]) .wt2-qmrow {
  background: none;
  border-left-color: var(--wt-faint);
}
/* The QuickMatch toggle is on while its own screens are showing. */
.wtx-window[data-open~="qm-on"] .wt2-toggle {
  background: var(--wt-accent);
  border-color: var(--wt-accent);
}
.wtx-window[data-open~="qm-on"] .wt2-toggle .wt2-toggle-thumb {
  left: calc(100% - 0.75em - 0.13em);
  background: var(--wt-paper);
}
/* A roster row for a student who has not shared their identity. */
.page-content table.wt2-roster td.is-soft { color: var(--text-soft); }
/* The Matches table is seven columns, and its wrapper cannot scroll: each
   column heading carries its own explanation as an absolutely-positioned
   popover, which needs overflow:visible to escape the cell
   (walkthrough-rig.css). On the walkthroughs the window is full-bleed and it
   fits comfortably. Here the window shares its row with the caption, and just
   above the sidebar breakpoint — where the site's own 250px sidebar appears
   but the viewport has not yet grown to pay for it — the table was about
   thirteen pixels too wide and pushed its screen into a sideways scroll.
   Cell padding is the cheapest width to give back, and a real table's cells
   are tight anyway. */
.wtx-window .page-content table.wt2-table th,
.wtx-window .page-content table.wt2-table td,
.page-content .wtx-window table.wt2-table th,
.page-content .wtx-window table.wt2-table td { padding: 0.55em 0.3em; }
/* The spreadsheet pane is a whole screen here rather than a replacement for
   the window's body, so it needs the height management the walkthroughs put
   on their own .wt2-xlsx-view. */
.wtx-screen > .wt2-xlsx { max-height: none; }

/* ============================================================
   The caption beside the window
   ============================================================ */
.wtx-cards {
  position: relative;
  min-width: 0;
  display: grid;
}
.wtx-card {
  grid-area: 1 / 1;
  align-self: start;
  border: 1px solid var(--border-subtle);
  border-radius: 14px;
  background: var(--wt2-card-bg, var(--page-bg));
  box-shadow: var(--shadow-lg);
  padding: 1.25rem 1.35rem 1.35rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.6rem);
  transition: opacity 0.3s ease, transform 0.36s cubic-bezier(0.22, 1, 0.36, 1), visibility 0.3s;
}
.wtx-card.is-on { opacity: 1; visibility: visible; transform: none; }
.page-content h2.wtx-title {
  font-family: "Roboto Mono", monospace;
  font-weight: 700;
  font-size: clamp(1rem, 1.4vw, 1.2rem);
  line-height: 1.32;
  color: var(--text-strong);
  margin: 0 0 0.6rem;
}
.page-content h2.wtx-title b { color: var(--wt-accent); font-weight: 700; margin-right: 0.5em; }
.page-content .wtx-card p {
  font-size: 0.83rem;
  line-height: 1.66;
  margin: 0 0 0.65rem;
}
.page-content .wtx-card p:last-child { margin-bottom: 0; }
.page-content .wtx-card ul { margin: 0.55rem 0 0.65rem; padding-left: 1.05rem; }
.page-content .wtx-card li { font-size: 0.8rem; line-height: 1.58; margin: 0 0 0.4rem; }
.page-content .wtx-card b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.94em;
  font-weight: 700;
  color: var(--text-strong);
}
.page-content .wtx-card a { text-decoration: underline; text-underline-offset: 0.16em; }
/* A line naming what to press next, set apart from the explanation above it.
   These pages are driven by the reader, so the caption's last job is to say
   where they can go from here. */
.page-content .wtx-try {
  margin-top: 0.9rem;
  padding-top: 0.7rem;
  border-top: 1px dashed var(--wt-faint);
  font-family: "Roboto Mono", monospace;
  font-size: 0.72rem;
  line-height: 1.6;
  color: var(--text-soft);
}
.page-content .wtx-try b { color: var(--wt-accent); }

/* ============================================================
   Every screen
   ============================================================ */
.wtx-index {
  margin-top: 1.6rem;
  border-top: 1.5px dashed var(--wt-faint);
  padding-top: 1rem;
}
.page-content .wtx-index > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-family: "Roboto Mono", monospace;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--wt-accent);
}
.page-content .wtx-index > summary::-webkit-details-marker { display: none; }
.page-content .wtx-index > summary::after { content: " +"; font-weight: 700; }
.page-content .wtx-index[open] > summary::after { content: " \2212"; }
.page-content .wtx-index-count {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-soft);
}
.wtx-index-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.2rem 1.8rem;
  margin-top: 1rem;
}
.page-content .wtx-idx-group h3 {
  font-family: "Roboto Mono", monospace;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin: 0 0 0.5rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px dashed var(--wt-faint);
}
.page-content .wtx-idx-group ol {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: wtxi;
}
.page-content .wtx-idx-group li {
  counter-increment: wtxi;
  margin: 0 0 0.12rem;
  font-size: 0.78rem;
  line-height: 1.5;
}
.page-content .wtx-idx-group a {
  display: block;
  padding: 0.18rem 0.4rem 0.18rem 1.6rem;
  position: relative;
  border-radius: 4px;
  color: var(--text);
  text-decoration: none;
}
.page-content .wtx-idx-group a::before {
  content: counter(wtxi, decimal-leading-zero);
  position: absolute;
  left: 0.35rem;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  color: var(--wt-faint);
}
.page-content .wtx-idx-group a:hover { background: var(--wt-accent-soft); text-decoration: none; }
.page-content .wtx-idx-group a.is-here {
  background: var(--wt-accent);
  color: var(--wt-paper);
  font-weight: 600;
}
.page-content .wtx-idx-group a.is-here::before { color: var(--wt-paper); opacity: 0.7; }

/* ============================================================
   Narrow screens
   ============================================================ */
@media (max-width: 1099px) {
  .wtx-cards { margin-top: 1.1rem; }
  .wtx-card { position: static; }
}
@media (max-width: 620px) {
  .page-content a.wtx-chip { width: 100%; min-height: 0; }
  .wtx-head { flex-wrap: wrap; gap: 0.5rem; }
  /* The section half of the breadcrumb wraps onto its own line here, which
     left the "›" separator stranded at the start of the second one, reading
     as a stray character rather than as punctuation. On a phone the current
     screen's own name is enough. */
  .page-content ol.wtx-crumbs li:not(.is-here) { display: none; }
  .page-content ol.wtx-crumbs li + li::before { content: none; }
}

/* ============================================================
   Reduced motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  /* Both selectors, and at the weight of the ones they are turning off: the
     split-screen rule below is more specific than a bare `.wtx-screen.is-on > *`,
     so a single blanket line left the main column still animating for exactly
     the readers who asked it not to. */
  .wtx-screen.is-on > *,
  .wtx-screen.wtx-split.is-on > .wtx-main > * { animation: none; }
  .wtx-card { transition: opacity 0.15s ease, visibility 0.15s; transform: none; }
  .wtx-modal { animation: none; }
  .wtx-wait i, .wtx-dots i { animation: none; opacity: 0.7; }
  .wtx-progress-fill { transition: none; }
}

/* ============================================================
   No JS: unstack into every screen in order

   Without the script there is nothing to click, so the page becomes what it
   is a model of: every screen in turn, drawn, inside one long window, and
   then the captions under it in the same order — each headed by the name of
   the screen it belongs to. The index still works, because every way into a
   screen on this page is an ordinary anchor.
   ============================================================ */
html:not(.wtx-js) .wtx-stage { display: block; }
html:not(.wtx-js) .wtx-canvas { height: auto; }
html:not(.wtx-js) .wtx-window { height: auto; }
html:not(.wtx-js) .wtx-shell { display: flex; }
html:not(.wtx-js) .wtx-screens { display: block; overflow: visible; }
html:not(.wtx-js) .wtx-screen {
  display: flex;
  overflow: visible;
  border-top: 1.5px dashed var(--wt-faint);
  scroll-margin-top: calc(var(--banner-h) + 1rem);
}
html:not(.wtx-js) .wtx-screens > .wtx-screen:first-child { border-top: 0; }
/* A state carries no markup of its own — it is a menu or a modal over a view
   that is already drawn further up the page — so without the script there is
   nothing for it to show, and an empty section would only draw a stray rule.
   Its caption still appears with the others. */
html:not(.wtx-js) .wtx-screen[data-view] { display: none; }
html:not(.wtx-js) .wtx-menu { display: block; position: static; box-shadow: none; margin-top: 0.4em; }
html:not(.wtx-js) .wtx-scrim { display: block; position: static; background: none; padding: 1em 0 0; }
html:not(.wtx-js) .wtx-modal { display: block; margin: 0 0 0.8em; }
html:not(.wtx-js) .wtx-cards { display: block; margin-top: 1.2rem; }
html:not(.wtx-js) .wtx-card {
  opacity: 1;
  visibility: visible;
  transform: none;
  margin-bottom: 1rem;
}
html:not(.wtx-js) .wtx-head,
html:not(.wtx-js) .wtx-composer { display: none; }
html:not(.wtx-js) .wtx-thread { overflow: visible; }
html:not(.wtx-js) .wtx-index[open],
html:not(.wtx-js) .wtx-index { display: block; }
