/* ============================================================
   Student-side wireframe components for the scroll rig.

   Loaded alongside walkthrough.css (the --wt-* ink tokens),
   walkthrough-rig.css (the whole rig: grid, sticky stage, step
   track, card, dot rail, pointer, hand-ink) and
   walkthrough-features.css (modals, the scrim, dropdown menus,
   the exported spreadsheet, .wt2-modes radio rows).

   Everything here is new: the student's app bar, the survey
   host's purple band, the white page a survey step is drawn on,
   the topic list, the chat and its composer, the opinion matrix,
   and the email screens two of these pages open on.

   Nothing in this file is read by the three instructor
   walkthroughs, which never load it.
   ============================================================ */

/* ---- Screens that fill their window ----
   .wt2-frames is a one-cell grid whose row is `auto`, so it takes the height
   of the tallest screen's content. On the instructor walkthroughs nothing is
   taller than the window, so that never showed; a message thread is, and the
   window simply grew and clipped the bottom of it. Clamping the row is what
   gives every screen a real height to fill — and what makes the thread
   inside one scroll rather than run off the end. */
.wt2-student .wt2-frames {
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  min-height: 0;
}

/* ---- Two-column screen ----
   Every screen of the student app is a narrow sidebar and a wide pane.
   .wt2-frame is already a flex column with the card's gutter reserved on
   the right, so this is one flex row inside it that fills what is left. */
.wt2-split {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: stretch;
  gap: 1.2em;
}
/* The sidebar is divided from the message column by a rule, as it is in the
   product — the same mark the manage screen uses down the side of its rail.
   The line itself is drawn (INK_SPEC); this reserves the room for it. */
.wt2-side {
  flex: 0 0 11.5em;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding-right: 0.9em;
  border-right: 1.5px solid var(--wt-faint);
}
.wt2-main {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* A chat needs the width more than its card does: the card beside these
   screens carries two short paragraphs, and the pane carries a conversation
   that wraps to nothing if it is squeezed. The two figures are set from each
   other and have to stay in step, or the thread either runs under the card
   or stops short of where it could have reached. */
@media (min-width: 901px) {
  .wt2-step.is-wide .wt2-card { width: min(20rem, 38%); }
  .wt2-frame.is-wide { padding-right: calc(20rem + 1.4rem); }
  .wt2-student .wt2-window:has(.wt2-frame.is-on.is-wide) .wt2-modal-slot {
    right: calc(20rem + 1.4rem);
  }
}
/* The chat runs to the edges of its pane rather than sitting in the frame's
   own padding: a message thread with a gutter round it reads as a document,
   not as a window. */
.wt2-main.is-flush { margin: -0.6em -0.9em -0.6em 0; }
@media (max-width: 760px) {
  .wt2-split { gap: 0.9em; }
  .wt2-side { flex-basis: 9.5em; }
}
@media (max-width: 620px) {
  /* Below this the frame's own padding has already collapsed and there is
     not room for both columns; the pane is what the screen is about. */
  .wt2-side { display: none; }
  .wt2-main.is-flush { margin: 0; }
}

/* ---- The two bars a screen can wear ----
   chat.swaybeta.ai has no left rail; the mark sits top left and the account
   avatar top right, and that is the whole of its chrome. The opinion survey,
   the understanding quiz and the post-chat survey are not on that host at
   all — they are a different website, with a deep purple band across the
   top. Students notice the change, and an instructor reading this needs to
   know it is not a fault, so the wireframe keeps it.

   Both live outside the frame swap, as siblings of .wt2-body, for the reason
   the instructor pages' rail does: chrome that redrew itself on every screen
   would read as the page reloading. Which one is up is data-host, set from
   the screen by walkthrough-rig.js. */
.wt2-appbar { display: none; }
.wt2-window[data-host="app"] .wt2-appbar,
.wt2-window[data-host="auth"] .wt2-appbar { display: flex; }
/* One bar, two right-hand sides: before a student has signed in it offers a
   way in, and after it carries their account. Two separate bars would each
   want their own drawn rule under them, and only the first would get one. */
.wt2-window:not([data-host="auth"]) .wt2-signedout,
.wt2-window[data-host="auth"] .wt2-avatar { display: none; }
.wt2-appbar {
  flex: none;
  align-items: center;
  gap: 0.7em;
  padding: 0.55em 0.9em;
  border-bottom: 1.5px solid var(--wt-faint);
  background: var(--wt-hatch);
}
.wt2-brand { display: flex; align-items: center; gap: 0.45em; }
.wt2-mark { width: 1.25em; height: 1.25em; flex: none; color: var(--wt-accent); }
.wt2-mark svg { display: block; width: 100%; height: 100%; }
.page-content .wt2-brand b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.8em;
  font-weight: 700;
  color: var(--wt-ink-strong);
}
.wt2-topnav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.9em;
  font-size: 0.72em;
  color: var(--text-soft);
}
/* The theme control in the product's top bar is Material's brightness_auto —
   a capital A inside a rounded square — not a moon. */
.wt2-abadge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.55em;
  height: 1.55em;
  border: 1.5px solid var(--wt-faint);
  border-radius: 4px;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  font-weight: 700;
  line-height: 1;
  color: var(--wt-ink-strong);
}
.wt2-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 white page a survey step is drawn on ---- */
.wt2-panel {
  border: 1.5px solid var(--wt-ink);
  border-radius: 5px;
  background: var(--wt-paper);
  padding: 1.1em 1.2em 1.2em;
}
/* A form is a narrow card in the middle of the page; a survey page is the
   page. Only the first is centred. */
.wt2-panel.is-form { width: min(24em, 100%); margin: 0 auto; }
.wt2-frame.is-mid { justify-content: center; }
/* The pronouns select carries the longest label the product uses, and the
   rig's own 9em column wraps it onto two lines. */
.wt2-student .wt2-selectwrap { flex-basis: 11.5em; min-height: 11em; }
.page-content .wt2-h {
  font-family: "Roboto Mono", monospace;
  font-size: 0.92em;
  font-weight: 700;
  line-height: 1.35;
  color: var(--wt-ink-strong);
  margin: 0 0 0.5em;
}
.page-content .wt2-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 .wt2-p:last-child { margin-bottom: 0; }
.page-content .wt2-p.is-soft { color: var(--text-soft); }
.page-content .wt2-p b { color: var(--wt-ink-strong); font-weight: 700; }
.page-content .wt2-p i { font-style: italic; }
.page-content ul.wt2-list { list-style: none; margin: 0 0 0.9em; padding: 0; }
.page-content ul.wt2-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.wt2-list li::before {
  content: "\2022";
  position: absolute;
  left: 0.15em;
  color: var(--wt-accent);
}

/* ---- Fields ---- */
.wt2-field { margin-bottom: 0.7em; }
.page-content .wt2-label {
  font-family: "Roboto Mono", monospace;
  font-size: 0.62em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin: 0 0 0.25em;
}
/* .wt2-input and .wt2-textarea come from walkthrough-rig.css; only the
   placeholder state is new. */
.wt2-input.is-empty, .wt2-textarea.is-empty { color: var(--text-soft); }
.wt2-input, .wt2-textarea { display: block; }

/* ---- Checkbox rows ---- */
.page-content ul.wt2-checks { list-style: none; margin: 0.5em 0 0; padding: 0; }
.page-content ul.wt2-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.5em;
}
.wt2-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);
}
.wt2-box.is-on { background: var(--wt-accent); border-color: var(--wt-accent); }
.wt2-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);
}
.wt2-box.is-pressed { transform: scale(1.2); }

/* ---- Pills ---- */
.wt2-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;
}

/* ---- A notice inside the product ----
   A Chat with Guide offer, a suspension, a deadline warning. The product
   puts these across the top of the pane. */
.wt2-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: 1em;
  flex: none;
}
.page-content .wt2-banner b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.74em;
  font-weight: 700;
  color: var(--wt-ink-strong);
  margin-bottom: 0.3em;
}
.page-content .wt2-banner p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.6;
  color: var(--wt-ink);
  margin: 0 0 0.5em;
}
.page-content .wt2-banner p:last-child { margin-bottom: 0; }
.wt2-banner .wt2-actions { margin-top: 0.6em; justify-content: flex-start; }

/* ---- Empty state ---- */
.wt2-blank {
  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: 7em;
}
.page-content .wt2-blank b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.8em;
  color: var(--wt-ink-strong);
}
.page-content .wt2-blank p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.68em;
  line-height: 1.6;
  color: var(--text-soft);
  max-width: 26em;
  margin: 0;
}
/* Three dots, because that is what waiting looks like. */
.wt2-wait { display: flex; gap: 0.4em; }
.wt2-wait i {
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: var(--wt-accent);
  animation: wt2-waitdot 1.4s ease-in-out infinite;
}
.wt2-wait i:nth-child(2) { animation-delay: 0.18s; }
.wt2-wait i:nth-child(3) { animation-delay: 0.36s; }
@keyframes wt2-waitdot {
  0%, 60%, 100% { opacity: 0.25; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-0.22em); }
}
.wt2-spin {
  width: 1.4em;
  height: 1.4em;
  border: 2px solid var(--wt-faint);
  border-top-color: var(--wt-accent);
  border-radius: 50%;
  animation: wt2-spin 0.9s linear infinite;
}
@keyframes wt2-spin { to { transform: rotate(360deg); } }

/* ---- The topic list ----
   One row per statement, with a dot saying whether a classmate who disagrees
   is available right now. Green against orange is the whole of that
   interface, so the two values are taken from the product itself
   (static/css/base.css) rather than from this wireframe's ink palette —
   drawn hollow-against-filled the row stopped saying the thing it exists to
   say. Both are ringed in the paper colour so they stay legible on the
   tinted row of a matched topic and in dark mode. */
:root {
  --wt2-available: #28a745;
  --wt2-unavailable: #ff8c00;
}
.page-content ul.wt2-tlist { list-style: none; margin: 0; padding: 0; }
.page-content ul.wt2-tlist li { margin: 0 0 0.15em; }
.wt2-tcard {
  display: block;
  padding: 0.5em;
  border-radius: 4px;
}
.wt2-tcard.is-ready { background: var(--wt-accent-soft); }
.wt2-tcard.is-pressed { background: var(--wt-hatch); }
.wt2-thead { display: flex; align-items: center; justify-content: space-between; gap: 0.5em; }
.page-content .wt2-tcard b {
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  line-height: 1.4;
  color: var(--wt-ink-strong);
}
.page-content .wt2-tcard p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.58em;
  line-height: 1.5;
  color: var(--text-soft);
  margin: 0.15em 0 0;
}
.wt2-tdot {
  flex: none;
  width: 0.8em;
  height: 0.8em;
  border-radius: 50%;
  background: var(--wt2-unavailable);
  box-shadow: 0 0 0 1.5px var(--wt-paper);
}
.wt2-tdot.is-ready { background: var(--wt2-available); }
.wt2-legend {
  border: 1.5px dashed var(--wt-faint);
  border-radius: 4px;
  padding: 0.5em 0.55em;
  margin-bottom: 0.7em;
}
.page-content .wt2-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 .wt2-legend p:last-child { margin: 0; }

/* ---- The assignment card in the sidebar, and its progress meter ---- */
.wt2-sidecard {
  border-radius: 4px;
  background: var(--wt-accent-soft);
  border-left: 3px solid var(--wt-accent);
  padding: 0.7em 0.65em;
  margin-bottom: 0.8em;
  flex: none;
}
.page-content .wt2-sidecard > 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 .wt2-sidecard p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.6em;
  line-height: 1.55;
  color: var(--text-soft);
  margin: 0;
}
.wt2-prog { margin: 0.5em 0 0.2em; }
.wt2-prog-track {
  display: block;
  height: 4px;
  border-radius: 2px;
  background: var(--wt-faint);
  overflow: hidden;
}
/* The width is set from --pct rather than inline, so the same element can be
   animated from where the last screen left it to where this one wants it —
   see the meter's arm/run pair in walkthrough-rig.js. */
.wt2-prog-fill {
  display: block;
  height: 100%;
  width: var(--pct, 0%);
  background: var(--wt-accent);
  transition: width 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}
.page-content .wt2-prog-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;
}
.wt2-prog-num { font-weight: 700; color: var(--wt-ink-strong); }

.wt2-chatrow {
  display: flex;
  align-items: flex-start;
  gap: 0.5em;
  padding: 0.5em;
  border-radius: 4px;
}
.wt2-chatrow.is-on { background: var(--wt-accent-soft); }
.wt2-chatrow > div { min-width: 0; }
.page-content .wt2-chatrow b {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.64em;
  line-height: 1.4;
  color: var(--wt-ink-strong);
}
.page-content .wt2-chatrow span.wt2-preview {
  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;
}
/* The sender's name runs into the preview, as it does in a message list;
   the rule above makes every b in this row a block of its own. */
.page-content .wt2-chatrow span.wt2-preview b { display: inline; }

/* ============================================================
   The chat
   ============================================================ */
.wt2-chat {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.wt2-thread {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.9em 1em 0.6em;
  display: flex;
  flex-direction: column;
  gap: 0.55em;
  /* The strokes overshoot their boxes by seven pixels, so a bubble hard
     against the edge would have its ink clipped by the scroller. */
  scroll-padding: 0.5em;
}
.wt2-msg {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 84%;
}
.wt2-msg.is-mine { align-self: flex-end; align-items: flex-end; }
.wt2-msg.is-guide { max-width: 92%; }
.page-content .wt2-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;
}
.wt2-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;
}
.wt2-msg.is-mine .wt2-bubble { background: var(--wt-accent-soft); color: var(--wt-ink-strong); }
.wt2-msg.is-guide .wt2-bubble { background: var(--wt-hatch); }
.page-content .wt2-bubble p { font-family: inherit; font-size: 1em; line-height: 1.6; margin: 0 0 0.5em; }
.page-content .wt2-bubble p:last-child { margin: 0; }
.page-content .wt2-bubble i { font-style: italic; color: var(--wt-ink-strong); }
.page-content .wt2-bubble ul { margin: 0.4em 0; padding-left: 1.1em; }
.page-content .wt2-bubble li { font-family: inherit; font-size: 1em; line-height: 1.55; margin: 0 0 0.2em; }
.page-content .wt2-stamp {
  font-family: "Roboto Mono", monospace;
  font-size: 0.55em;
  color: var(--text-soft);
  margin: 0.15em 0.3em 0;
}

/* The typing indicator, and the reply that follows it. Both start hidden and
   are revealed by data-then on the control that sends the message (see
   walkthrough-rig.js): a reply that is already sitting there when the screen
   arrives is not a reply to anything. */
.wt2-later { display: none; }
.wt2-later.is-shown { display: flex; animation: wt2-rise 0.4s cubic-bezier(0.22, 1, 0.36, 1) both; }
/* The dots are what waiting for a reply looks like, so they go the moment the
   reply lands. Expressed as "is there a later revealed message after me"
   rather than as a second timer, so the two cannot end up disagreeing. */
.wt2-typebubble.is-shown:has(~ .wt2-later.is-shown) { display: none; }
.wt2-typing { display: flex; align-items: center; gap: 0.28em; padding: 0.7em 0.8em; }
.wt2-typing i {
  width: 0.35em;
  height: 0.35em;
  border-radius: 50%;
  background: var(--wt-ink);
  animation: wt2-typedot 1.1s ease-in-out infinite;
}
.wt2-typing i:nth-child(2) { animation-delay: 0.14s; }
.wt2-typing i:nth-child(3) { animation-delay: 0.28s; }
@keyframes wt2-typedot {
  0%, 65%, 100% { opacity: 0.28; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-0.18em); }
}

/* ---- The message box ----
   Three controls in a row, as the product has them: the smiley that opens the
   emoji picker, the box a message is typed into, and Send. The box is dashed
   because it is waiting to be filled in, which is what dashed means everywhere
   else in this drawing; Send is filled because it is the one control here that
   does something. */
.wt2-composer {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.5em;
  margin: 0.5em 1em 0.9em;
}
.wt2-emoji {
  flex: none;
  font-size: 1.15em;
  line-height: 1;
  color: var(--text-soft);
  padding: 0.28em 0.36em;
  border-radius: 4px;
}
.wt2-emoji.is-pressed { background: var(--wt-accent-soft); color: var(--wt-ink-strong); }
.page-content .wt2-say {
  flex: 1;
  min-width: 0;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.6;
  color: var(--wt-ink-strong);
  margin: 0;
  padding: 0.45em 0.95em;
  border: 1.5px dashed var(--wt-faint);
  border-radius: 18px;
  background: var(--wt-paper);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* The prompt gives way to whatever has been put in the box. */
/* Placeholder text is quiet, not unreadable: at the faint ink it sat under a
   2:1 contrast ratio, which is below anything legible at this size. */
.wt2-ph { color: var(--text-soft); }
.wt2-say:has(.wt2-typedmsg:not(:empty)) .wt2-ph { display: none; }
.wt2-send {
  flex: none;
  border: 1.5px solid var(--wt-accent);
  border-radius: 4px;
  background: var(--wt-accent);
  color: var(--wt-paper);
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.62em 1.25em;
  box-shadow: 2px 2px 0 var(--wt-cast);
}
.wt2-send.is-pressed { transform: translate(1px, 1px); box-shadow: 1px 1px 0 var(--wt-cast); }

/* The picker floats above the composer, as it does in the product, and closes
   when an emoji is taken from it. Its outline is drawn (INK_SPEC), so it
   carries no border of its own. */
.wt2-picker {
  display: none;
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.55em);
  z-index: 6;
  width: 13em;
  padding: 0.55em;
  border-radius: 6px;
  background: var(--wt-paper);
  box-shadow: 3px 3px 0 var(--wt-cast);
  grid-template-columns: repeat(6, 1fr);
  gap: 0.15em;
}
.wt2-picker.is-open { display: grid; }
.wt2-pick-em {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05em;
  line-height: 1;
  padding: 0.26em;
  border-radius: 4px;
}
.wt2-pick-em.is-pressed { background: var(--wt-accent-soft); }

/* ============================================================
   The opinion survey matrix, the quiz, and the rating choices
   ============================================================ */
/* Eight columns is wider than the pane on a small laptop once the card's
   gutter is taken out of it, so the table scrolls sideways rather than
   forcing the window wider than the page.

   It is also the box the column heads size themselves against — see the note
   on .wt2-matrix.is-scale th — which is what container-type is here for. */
.wt2-matrixwrap { overflow-x: auto; container-type: inline-size; }
.page-content table.wt2-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.wt2-matrix th,
.page-content table.wt2-matrix td {
  border: 1.5px solid var(--wt-faint);
  padding: 0.45em 0.3em;
  text-align: center;
  font-size: 0.58em;
  line-height: 1.35;
  vertical-align: middle;
  font-weight: 400;
}
.page-content table.wt2-matrix th {
  background: var(--wt-hatch);
  color: var(--wt-ink-strong);
  font-weight: 700;
}
.page-content table.wt2-matrix td:first-child,
.page-content table.wt2-matrix th:first-child {
  text-align: left;
  font-size: 0.62em;
  color: var(--wt-ink);
  min-width: 10em;
}
.wt2-radio {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  border-radius: 50%;
  border: 1.5px solid var(--wt-ink);
}
.wt2-radio.is-on {
  border-color: var(--wt-accent);
  background: var(--wt-accent);
  box-shadow: inset 0 0 0 2px var(--wt-paper);
}
.wt2-radio.is-pressed { transform: scale(1.25); }
.wt2-nomatch {
  display: inline-block;
  width: 1.25em;
  height: 1.25em;
  line-height: 1.1em;
  border: 1.5px solid var(--wt-faint);
  border-radius: 2px;
  color: var(--wt-ink);
  font-size: 1em;
  font-weight: 700;
}
.wt2-nomatch.is-on { border-color: var(--wt-accent); background: var(--wt-accent); color: var(--wt-paper); }

.wt2-quiz {
  border: 1.5px solid var(--wt-ink);
  border-radius: 5px;
  padding: 0.85em 0.95em;
  margin-bottom: 0.7em;
}
.page-content .wt2-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.5em;
}
.page-content ul.wt2-answers { list-style: none; margin: 0; padding: 0; }
.page-content ul.wt2-answers li {
  display: flex;
  align-items: flex-start;
  gap: 0.55em;
  border-radius: 4px;
  background: var(--wt-hatch);
  padding: 0.42em 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.wt2-answers li.is-on { background: var(--wt-accent-soft); color: var(--wt-ink-strong); }
.page-content ul.wt2-answers li.is-pressed { background: var(--wt-accent-soft); }
.wt2-answers .wt2-radio { margin-top: 0.15em; }
/* The whole row is the control here, so the radio inside it follows the row
   rather than being picked separately. */
.wt2-answers li.is-on .wt2-radio {
  border-color: var(--wt-accent);
  background: var(--wt-accent);
  box-shadow: inset 0 0 0 2px var(--wt-paper);
}

.page-content ul.wt2-choices {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
  margin: 0.5em 0 0.9em;
  padding: 0;
}
.page-content ul.wt2-choices li { margin: 0; flex: 1 1 5.5em; }
.wt2-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2em;
  border: 1.5px solid var(--wt-faint);
  border-radius: 4px;
  padding: 0.55em 0.35em;
  font-size: 0.68em;
  color: var(--wt-ink-strong);
  text-align: center;
  background: var(--wt-paper);
}
.wt2-choice.is-on { border-color: var(--wt-accent); background: var(--wt-accent-soft); font-weight: 700; }
.wt2-choice.is-pressed { transform: translateY(1px); }
.wt2-choice span { font-size: 1.1em; }

/* ============================================================
   Modals

   The scrim, the modal box and its buttons all come from
   walkthrough-features.css. Two things are different here.

   First, the slot the modal is centred in: that file insets it by the width
   of the instructor pages' rail, and these pages have no rail.

   Second, which modal belongs to which screen. That file names the
   instructor pages' three; these are the student pages' own, listed the same
   way, because a modal is shared shell content — its scrim has to dim the
   app bar too — and shared content cannot say in its own markup which screen
   it is for.
   ============================================================ */
@media (min-width: 901px) {
  /* These pages have no rail, so a modal is centred over the whole window —
     except on the screens that do wear one, where it sits beside it, exactly
     as it does on the instructor walkthroughs. */
  .wt2-student .wt2-modal-slot { left: 0; }
  .wt2-student .wt2-window[data-chrome~="rail"] .wt2-modal-slot { left: 14.5em; }
}
.wt2-student .wt2-window[data-active="complete"] .wt2-scrim,
.wt2-student .wt2-window[data-active="complete"] .wt2-modal[data-modal="complete"],
.wt2-student .wt2-window[data-active="guide-offered"] .wt2-scrim,
.wt2-student .wt2-window[data-active="guide-offered"] .wt2-modal[data-modal="guide-offered"],
.wt2-student .wt2-window[data-active="cut-off"] .wt2-scrim,
.wt2-student .wt2-window[data-active="cut-off"] .wt2-modal[data-modal="cut-off"] { display: block; }

/* ---- A second button that is not the way on ----
   The opinion survey ends with two identical primary buttons, which is what
   the product does: it does not steer a student towards taking part. Only
   one of them is the screen's way on, so the other cannot be .wt2-next —
   that class is what the rig reads to decide which controls are live. */
.wt2-alt {
  border: 1.5px solid var(--wt-ink-strong);
  border-radius: 4px;
  padding: 0.4em 1.4em;
  font-size: 0.74em;
  font-weight: 700;
  color: var(--wt-ink-strong);
  box-shadow: 2px 2px 0 var(--wt-cast);
}
.wt2-actions.is-pair { justify-content: flex-start; gap: 0.7em; }

/* ============================================================
   Email

   Two of these walkthroughs open on a message rather than on a screen — a
   student writing to their instructor, and Sway's own reminder. Mail is not
   part of the app, so its screen wears no chrome (data-host="mail"), and
   the message sits on the desk colour rather than on the app's paper.
   ============================================================ */
.wt2-window[data-host="mail"] .wt2-frames { background: var(--wt-hatch); }
.wt2-mail {
  width: min(34em, 100%);
  /* 34em is the message's measure and it does not grow — a wider column of
     mail is a worse one to read. What changed is the room around it: the
     window fills the stage now, so left-aligning the message left a third of
     the desk empty on one side and none on the other. Centred in what the
     frame leaves (the card's gutter is already out of that box), it reads as
     an open message on a desk rather than one that failed to fill it. The
     frame is a column, so this is the cross axis; .wt2-frame.is-mid does the
     other one. */
  align-self: center;
  border: 1.5px solid var(--wt-ink);
  border-radius: 5px;
  background: var(--wt-paper);
  box-shadow: 4px 4px 0 var(--wt-cast);
  padding: 1em 1.1em 1.1em;
}
.page-content .wt2-mailrow {
  display: flex;
  gap: 0.6em;
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  line-height: 1.7;
  color: var(--wt-ink);
  margin: 0;
}
.wt2-mailrow b { min-width: 3.4em; color: var(--text-soft); font-weight: 400; }
.page-content .wt2-mailsubj {
  font-family: "Roboto Mono", monospace;
  font-size: 0.8em;
  font-weight: 700;
  line-height: 1.45;
  color: var(--wt-ink-strong);
  margin: 0.55em 0 0.7em;
  padding-bottom: 0.7em;
  border-bottom: 1.5px dashed var(--wt-faint);
}
.page-content .wt2-mail .wt2-p { font-size: 0.7em; }

/* ============================================================
   Ink

   Two adjustments to walkthrough-rig.css's reveal, both scoped to pages
   that load this file.
   ============================================================ */
/* A screen here can carry many more boxes than an instructor screen does —
   the opinion matrix alone is nine columns by four rows — and the shipped
   stagger of 0.055s a box would have the last cell of that table arriving
   two seconds after the first. The per-box beat is shorter and both counters
   are capped, so a dense screen finishes in about the same time a sparse one
   does instead of in proportion to how much is on it. */
html.wt2-ink .wt2-student .hi-on > .hi-ink:not(.hi-dash) path {
  animation-delay: calc(min(var(--b, 0), 26) * 0.019s + min(var(--i, 0), 8) * 0.028s);
}
html.wt2-ink .wt2-student .hi-on > .hi-dash path {
  animation-delay: calc(min(var(--b, 0), 26) * 0.019s + min(var(--i, 0), 8) * 0.028s);
}
/* The matrix's own cells keep hairlines rather than being drawn one by one:
   at 36 cells the drawing reads as a machine ruling a grid, which is the one
   thing the hand-drawn line is here to avoid. The table's outer box is
   drawn, and that is what says "hand". */
html.wt2-ink .page-content table.wt2-matrix th,
html.wt2-ink .page-content table.wt2-matrix td { border-color: var(--wt-faint); }

/* ============================================================
   The scale, drawn as a scale
   ============================================================ */
/* Seven points that mean equal steps have to be drawn as equal steps. Left to
   size themselves to their labels, "Moderately disagree" took half again the
   width of "No idea!", which draws a ruler with uneven marks on it. Fixed
   layout with a width on the statement column only: every column that has no
   width of its own then shares what is left, equally, which is the whole rule.
   The same goes for any table in this drawing whose columns are one kind of
   thing — see .wt2-matrix.is-scale wherever it is used. */
.page-content table.wt2-matrix.is-scale { table-layout: fixed; }
.page-content table.wt2-matrix.is-scale.is-labelled th:first-child,
.page-content table.wt2-matrix.is-scale.is-labelled td:first-child { width: 29%; }
/* Seven columns of two-word labels in the width a scale gets is the one place
   in this drawing where the type cannot be as big as the rest. The statement
   beside them — the thing a reader is actually here to read — keeps the full
   size; the column heads take what is left.

   Sized against the table rather than against the window, which is the only
   box that knows how much room a column actually has: the seven share whatever
   the statement column leaves, so one column is 10.1% of this container and
   the longest word in a head ("Moderately", ten monospace characters) needs
   about six times the type size to sit on one line inside it. 1.45cqi keeps
   under that with room for the padding, and it holds at every width — where a
   flat size could only ever be right at one, which is why the labels used to
   collide into each other on a narrow window. The 0.56em cap is what stops it
   growing past the rest of the drawing on a wide one. */
.page-content table.wt2-matrix.is-scale th {
  padding-left: 0.15em;
  padding-right: 0.15em;
  font-size: min(0.56em, 1.45cqi);
  letter-spacing: -0.01em;
}
.page-content table.wt2-matrix.is-scale.is-labelled th:first-child { font-size: 0.62em; }
/* With no statement column beside them, the seven have room to spare. */
.page-content table.wt2-matrix.is-scale:not(.is-labelled) th { font-size: 0.56em; }
.page-content table.wt2-matrix.is-scale td:first-child { font-size: 0.6em; line-height: 1.5; }

/* ============================================================
   A survey page is the page
   ============================================================ */
/* A survey page runs to the edges of the window: contents at the top, the
   button at the bottom. Drawn as a small card floating in a large window it
   made a claim about the product that isn't true, and left most of the window
   empty.

   Marked on the frame rather than read off data-host, which used to carry it:
   these screens are on the app's own host now, and it is the shape of the page
   that makes it a survey, not where it is served from. */
.wt2-frame.is-survey > .wt2-panel {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
/* A survey page can be taller than the window — the opinion matrix is the one
   screen with more on it than anywhere else — so the screen scrolls rather
   than being cut off at the bottom. walkthrough-rig.js brings a control back
   into view before the pointer reaches for it, so a press is never made
   off-screen. */
.wt2-student .wt2-frame { overflow-y: auto; overflow-x: hidden; }
.wt2-frame.is-survey > .wt2-panel > .wt2-actions { margin-top: auto; padding-top: 0.7em; }
.wt2-frame.is-survey .wt2-matrixwrap { margin: 0.2em 0; }
.wt2-frame.is-survey .wt2-panel > .wt2-p { margin-bottom: 0.55em; }
.page-content table.wt2-matrix.is-scale td { padding-top: 0.3em; padding-bottom: 0.3em; }
/* ...and it is the same page from one screen to the next. It does not slide in
   with the rest of the screen's contents, because it never went away; what
   changed is what is on it, so that is what moves. Its lines are held too —
   see data-ink-keep in walkthrough-rig.js. */
.wt2-frame.is-on > [data-ink-keep] { animation: none; }
.wt2-frame.is-on > [data-ink-keep] > *:not(.hi-ink) { animation: wt2-fade 0.4s ease-out both; }
.wt2-frame.is-on > [data-ink-keep] > :nth-child(2) { animation-delay: 0.05s; }
.wt2-frame.is-on > [data-ink-keep] > :nth-child(3) { animation-delay: 0.1s; }
.wt2-frame.is-on > [data-ink-keep] > :nth-child(4) { animation-delay: 0.15s; }
.wt2-frame.is-on > [data-ink-keep] > :nth-child(n+5) { animation-delay: 0.2s; }
@keyframes wt2-fade { from { opacity: 0; } to { opacity: 1; } }

/* ============================================================
   One conversation, three steps
   ============================================================ */
/* The chat, the notice that it is complete, and the same thread again after
   the quiz are three steps over one screen (data-uses in the markup). data-at
   says which of them a piece of the screen belongs to. Nothing here is a
   second copy of the chat: the window, the message box and every message
   already sent stay exactly where they are, and only the thread grows. */
.wt2-student .wt2-msg[data-at]:not(.is-at),
.wt2-student .wt2-sidecard[data-at]:not(.is-at) { display: none; }
/* Whatever the send revealed is simply part of the thread by the time the chat
   is complete. The typing dots are not: nobody is still typing. */
.wt2-student .wt2-window[data-active="complete"] .wt2-later:not(.wt2-typebubble),
.wt2-student .wt2-window[data-active="done"] .wt2-later:not(.wt2-typebubble) { display: flex; }

/* ============================================================
   Notices the product puts up, and the controls that earn them
   ============================================================ */
/* The two screens that refuse to go on. Keyed on data-open rather than on
   data-active, because these are caused by a press rather than by arriving. */
.wt2-student .wt2-window[data-open~="consent-required"] .wt2-scrim,
.wt2-student .wt2-window[data-open~="consent-required"] .wt2-modal[data-modal="consent-required"],
.wt2-student .wt2-window[data-open~="commit-required"] .wt2-scrim,
.wt2-student .wt2-window[data-open~="commit-required"] .wt2-modal[data-modal="commit-required"],
.wt2-student .wt2-window[data-open~="opted-out"] .wt2-scrim,
.wt2-student .wt2-window[data-open~="opted-out"] .wt2-modal[data-modal="opted-out"] { display: block; }

/* ---- the first-name coaching panel ----
   Registration does not refuse a surname; it offers to drop it. Grey panel
   with a grey left border, under the field, exactly where the product puts
   it. Hidden until a reader puts a second word in the box. */
.wt2-namefield .wt2-nm2 { display: none; }
.wt2-namefield.is-two .wt2-nm2 { display: inline; }
.wt2-coach { display: none; margin-top: 0.5em; }
.wt2-namefield.is-coached .wt2-coach { display: block; }
.wt2-coach {
  border-left: 3px solid var(--wt-faint);
  background: var(--wt-hatch);
  border-radius: 4px;
  padding: 0.6em 0.7em;
}
.page-content .wt2-coach p {
  font-family: "Roboto Mono", monospace;
  font-size: 0.66em;
  line-height: 1.55;
  color: var(--wt-ink);
  margin: 0 0 0.55em;
}
.page-content .wt2-coach p i { font-style: italic; color: var(--wt-ink-strong); }
.wt2-coach-row { display: flex; gap: 0.45em; }
.wt2-usefirst, .wt2-keepboth {
  flex: 1;
  text-align: center;
  border-radius: 4px;
  font-family: "Roboto Mono", monospace;
  font-size: 0.62em;
  font-weight: 700;
  padding: 0.5em 0.4em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wt2-usefirst { background: var(--wt-accent); color: var(--wt-paper); border: 1.5px solid var(--wt-accent); }
.wt2-keepboth { background: var(--wt-paper); color: var(--wt-ink-strong); border: 1.5px solid var(--wt-faint); }
.wt2-usefirst.is-pressed, .wt2-keepboth.is-pressed { transform: translateY(1px); }

/* ---- hover text ----
   Anything the product explains on hover explains itself here too. Drawn
   rather than left to the browser's own tooltip, which would be the one piece
   of real chrome in a page of drawn ones — and reachable from the keyboard,
   which a title attribute is not. */
.wt2-tipped { position: relative; }
.wt2-tipped::after {
  content: attr(data-tip);
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.5em);
  z-index: 12;
  width: max-content;
  max-width: 20em;
  padding: 0.5em 0.65em;
  border: 1.5px solid var(--wt-ink);
  border-radius: 4px;
  background: var(--wt-paper);
  box-shadow: 3px 3px 0 var(--wt-cast);
  font-family: "Roboto Mono", monospace;
  font-size: 0.62em;
  font-weight: 400;
  line-height: 1.5;
  color: var(--wt-ink);
  white-space: normal;
  text-align: left;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s ease, visibility 0.16s;
  pointer-events: none;
}
.wt2-tipped:hover::after,
.wt2-tipped:focus-visible::after { opacity: 1; visibility: visible; }
/* A tip on something near the right edge of its pane would hang off it. */
.wt2-tipped.is-right::after { left: auto; right: 0; }
/* Near the top of a pane there is no room above it, so the tip drops below. */
.wt2-prog.wt2-tipped::after { bottom: auto; top: calc(100% + 0.5em); }
@media (prefers-reduced-motion: reduce) {
  .wt2-tipped::after { transition: none; }
}

/* A message that is simply part of the thread by the time this step is reached
   does not arrive again — it was already there. */
.wt2-later.is-pre { animation: none; }

/* ============================================================
   A chat that is over for this student
   ============================================================ */
/* The product empties the message column, paints the reason as a centred
   system line, greys the thread in the sidebar and takes the message box away
   altogether. A wireframe that showed a completed-looking chat here would be
   wrong: nothing about this state is completion. */
.wt2-thread.is-empty { align-items: center; justify-content: center; text-align: center; }
.page-content .wt2-sysline {
  font-family: "Roboto Mono", monospace;
  font-size: 0.72em;
  line-height: 1.7;
  color: var(--text-soft);
  max-width: 30em;
  margin: 0;
}
.wt2-chatrow.is-dim { opacity: 0.5; }
.wt2-composer.is-dead { opacity: 0.45; }

/* ============================================================
   Furniture that belongs to one screen and not the next
   ============================================================ */
/* These pages move between three different interfaces — the instructor's
   manage screen, the student's app, and a mail client that is not Sway at all.
   The rail is the manage screen's, so it stands only on the screens that ask
   for it. Left up behind an inbox it says Sway has an inbox, and behind a
   student's chat it says a student sees the instructor's course list; both are
   the sort of thing a reader would take away and believe. */
.wt2-student .wt2-rail { display: none; }
/* The row wraps; a label does not. This used to be `white-space: nowrap` on
   the row, which meant nothing could give: three tab names are wider than the
   frame leaves once the card's gutter is out of it — on the roster screens at
   ordinary laptop widths, by about 50px — so the row simply ran on under the
   card and "Suspended accounts" was cut mid-word. The nowrap moves to the
   label, which is what it was always protecting (a label broken in two reads
   as two headings rather than one tab), and the row takes a second line
   instead of overflowing. Pre-existing; found while checking every screen at
   every width.

   Scoped here rather than shared with the instructor walkthroughs on purpose:
   their type is smaller and their frame narrower, and a whole-label wrap costs
   them a third line they have no room for. See the note on .wt2-tabs in
   walkthrough-rig.css. */
.wt2-student .wt2-tabs { font-size: 0.92em; flex-wrap: wrap; }
.wt2-student .wt2-tabs span { white-space: nowrap; }
.wt2-student .wt2-window[data-chrome~="rail"] .wt2-rail { display: block; }

/* ============================================================
   Narrow screens
   ============================================================ */
/* Below this the card drops beneath the wireframe and the window is cut to
   62vh, which is not enough room for a survey page at the desktop type size.
   Three things give it back: smaller type, less padding, and — for the one
   or two screens that still do not fit on a short window — a pane that
   scrolls. walkthrough-rig.js brings a control back into view before the
   pointer reaches for it, so a press is never made off-screen. */
/* The wireframe is read at arm's length on a desktop, and the window is a good
   deal wider than the drawing inside it needed. The shared rig tops out at
   17px, which put the opinion matrix's cells at under 10px — too small to
   read, which is the one thing a screenshot of a product must not be. */
/* Built the same way as the shared rig's (see the note on .wt2-window in
   css/walkthrough-rig.css), with this family's own numbers: the floor is the
   curve that shipped, so nothing shrinks, and the growth term is measured
   against the window rather than the viewport so that a folded navigation —
   which is 240px of width the viewport cannot see — counts.

   These screens are the tall ones. An opinion survey or a chat runs close to
   the bottom of the window where a setup screen has room to spare, so the
   ceiling here is 2.3% of the window's height rather than 2.94%, and the
   growth this page family gets is mostly the extra width. */
@media (min-width: 901px) {
  .wt2-student .wt2-window {
    font-size: clamp(13px, max(min(6px + 1vw, 1.9vh), min(1.4cqi, 2.3cqb)), 22px);
  }
  /* Without JS the canvas is height:auto and stops being a size container, so
     the cq units above would fall back to the viewport and set the wireframe
     at 22px. Back to the curve that needs no container. Inside this media
     query rather than beside it, so the narrow branch below — which the
     unstacked layout uses too — still wins on its own terms. */
  html:not(.wt2-js) .wt2-student .wt2-window {
    font-size: clamp(13px, min(6px + 1vw, 1.9vh), 22px);
  }
}
@media (max-width: 900px) {
  /* The second selector only exists to outrank the shared rig's own no-JS
     rule, which carries an `html` in it and so beats a two-class selector on
     specificity however late this file is loaded. */
  .wt2-student .wt2-window,
  html:not(.wt2-js) .wt2-student .wt2-window { font-size: clamp(11px, 6px + 0.72vw, 15px); }
  .wt2-student .wt2-frame { padding: 1.4em 1.5em 1.3em; overflow-y: auto; overflow-x: hidden; }
  .wt2-panel { padding: 0.9em 1em 1em; }
  .wt2-thread { padding: 0.8em 0.85em 0.5em; }
  .wt2-composer { margin: 0.4em 0.85em 0.8em; }
  .wt2-student .wt2-selectwrap { flex-basis: 10em; min-height: 9.5em; }
  .wt2-legend { padding: 0.4em 0.45em; margin-bottom: 0.5em; }
  .wt2-tcard { padding: 0.35em 0.4em; }
  .wt2-quiz { padding: 0.7em 0.8em; margin-bottom: 0.5em; }
  .wt2-sidecard { padding: 0.55em 0.5em; }
}
@media (max-width: 620px) {
  .wt2-student .wt2-frame { padding: 1.1em 1.1em 1.2em; }
}

/* ============================================================
   No JS: the screens unstack, so anything hidden until a click
   has to be visible instead — there is nothing to click.
   ============================================================ */
html:not(.wt2-js) .wt2-later { display: flex; }
/* The meter's resting value is written inline on .wt2-prog, so it is right
   here too; all that has to go is the climb. */
html:not(.wt2-js) .wt2-prog-fill { transition: none; }
html:not(.wt2-js) .wt2-thread { overflow-y: visible; }
/* Both bars are on show at once here, above the screens they belong to,
   because there is no data-host to choose between them. */
html:not(.wt2-js) .wt2-appbar { display: flex; }
html:not(.wt2-js) .wt2-split { display: block; }
html:not(.wt2-js) .wt2-side { display: block; margin-bottom: 1em; }

@media (prefers-reduced-motion: reduce) {
  .wt2-wait i, .wt2-typing i, .wt2-spin { animation: none; }
  .wt2-wait i { opacity: 0.7; }
  .wt2-typing i { opacity: 0.55; }
  .wt2-prog-fill { transition: none; }
  .wt2-later.is-shown { animation: none; }
}
