/* ==========================================================================
   Oplo Learn — application styles.
   Same design language as oplocloud.com: near-monochrome, one accent, space
   doing the work decoration usually does. Every class is `lx-` prefixed so
   nothing here can collide with the marketing stylesheet.
   ========================================================================== */

:root {
  --paper:  #ffffff;
  --canvas: #f5f5f7;
  --sunk:   #ececee;
  --ink:    #1d1d1f;
  --ink-2:  #6e6e73;
  --ink-3:  #86868b;
  --rule:   #d2d2d7;
  --hair:   #e6e6e8;

  --blue:   #0071e3;
  --blue-d: #0060c0;
  --green:  #12915a;
  --amber:  #b26a00;
  --red:    #d70015;

  --font: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Inter",
          "Helvetica Neue", Helvetica, Arial, sans-serif;
  --text: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Inter",
          "Helvetica Neue", Helvetica, Arial, sans-serif;

  --bar: 52px;
  --sub: 46px;
  --well: 980px;
  --gut: 22px;
  --ease: cubic-bezier(.28,.11,.32,1);
  --r: 16px;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--canvas); }
body {
  margin: 0; background: var(--canvas); color: var(--ink);
  font-family: var(--text); font-size: 17px; line-height: 1.47;
  letter-spacing: -.022em;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}
[hidden] { display: none !important; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input { font: inherit; }
svg { display: block; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 6px; }

/* ------------------------------------------------------------------ Bar */
.lx-bar {
  position: sticky; top: 0; z-index: 40;
  background: rgba(255,255,255,.82);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid var(--hair);
}
/* The bar is chrome, not content: it spans the window, so the mark and the
   sections sit at the left edge of the screen and the streak and the account
   at the right, instead of both floating in from a 1240px column. */
.lx-bar-in {
  height: var(--bar);
  padding-inline: max(var(--gut), env(safe-area-inset-left)) max(var(--gut), env(safe-area-inset-right));
  display: flex; align-items: center; gap: 14px;
}
.lx-mark { width: 21px; height: 21px; color: var(--ink); flex: none; }
.lx-name {
  font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.014em; flex: none;
}
.lx-back {
  display: flex; align-items: center; gap: 5px; flex: none;
  height: 30px; padding: 0 11px 0 8px; margin-left: -6px;
  border-radius: 100px; background: var(--canvas);
  font-size: 13px; font-weight: 500; color: var(--ink-2);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.lx-back:hover { background: var(--sunk); color: var(--ink); }
.lx-spacer { flex: 1 1 auto; }

.lx-top { display: flex; gap: 2px; flex: none; }
.lx-top button {
  height: 32px; padding: 0 13px; border-radius: 100px;
  font-size: 14px; font-weight: 500; color: var(--ink-2);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.lx-top button:hover { color: var(--ink); background: var(--canvas); }
.lx-top button[aria-current="true"] { color: var(--ink); background: var(--sunk); }

.lx-streak {
  display: flex; align-items: center; gap: 5px; flex: none;
  font-size: 13px; font-weight: 600; color: var(--amber);
}
.lx-user {
  display: flex; align-items: center; gap: 8px; flex: none;
  height: 34px; padding: 0 11px 0 3px; border-radius: 100px;
  transition: background .15s var(--ease);
}
.lx-user:hover { background: var(--canvas); }
.lx-user .av {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  display: grid; place-items: center; background: var(--ink); color: #fff;
  font-family: var(--font); font-size: 11.5px; font-weight: 600; letter-spacing: .01em;
}
.lx-user .nm { font-size: 14px; font-weight: 500; }

/* Progress hairline, shown only while a lesson or test is running. */
.lx-prog { flex: 1 1 auto; height: 4px; border-radius: 100px; background: var(--sunk); max-width: 420px; }
.lx-prog i { display: block; height: 100%; border-radius: 100px; background: var(--blue);
             width: 0; transition: width .32s var(--ease); }

/* Subject bar */
.lx-subbar { border-top: 1px solid var(--hair); background: rgba(255,255,255,.7); }
.lx-subbar-in {
  height: var(--sub);
  padding-inline: max(var(--gut), env(safe-area-inset-left));
  display: flex; align-items: center; gap: 4px; overflow-x: auto;
  scrollbar-width: none;
}
.lx-subbar-in::-webkit-scrollbar { display: none; }
.lx-subbar-in button {
  height: 30px; padding: 0 12px; border-radius: 100px; white-space: nowrap;
  font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.lx-subbar-in button:hover { color: var(--ink); background: var(--canvas); }
.lx-subbar-in button[aria-current="true"] { color: var(--ink); background: var(--sunk); }

/* ---------------------------------------------------------------- Views */
.lx-wrap {
  max-width: var(--well); margin-inline: auto;
  padding: clamp(26px, 4vw, 46px) max(var(--gut), env(safe-area-inset-left))
           120px max(var(--gut), env(safe-area-inset-right));
}
.lx-wrap.wide { max-width: 1240px; }
/* The reader is the one view that wants the whole screen: the rail belongs at
   the left edge, the margin at the right, and the text between them. The cap
   is not a column, it is a limit on how far apart the three can drift — past
   it the layout stays left-anchored so the rail keeps the screen edge, because
   a note that ends up 500px from its own sentence is no longer a margin note.
   `margin-inline` is 0 for the same reason: auto would centre it and take the
   rail off the edge. */
/* Centred, not left-anchored. An earlier pass pinned this to the left so the
   rail could hold the screen edge, and the cost only shows on a wide window:
   the text ends up sitting well left of the middle with a field of nothing on
   the right, which reads as a page that ran out rather than a page composed.
   The rail is still the leftmost thing; it now has a margin instead of being
   jammed against the glass. */
.lx-wrap.full {
  max-width: 1680px; margin-inline: auto;
  padding-top: clamp(38px, 5.5vh, 76px);
}
/* Predict borrows the reader's view, and the reader is left-anchored so its
   rail can hold the screen edge. A single centred card must not inherit that
   or it sits off-centre on any window wider than the cap. Both classes are
   required, so leaving the reader takes the override with it. */
.lx-wrap.full.pd-on {
  max-width: none; margin-inline: auto;
  /* The 120px at the foot of every other view is room for the action bar,
     which this screen does not have. Symmetric padding is what lets the
     composition sit in the true middle of the window. */
  padding-bottom: clamp(26px, 4vw, 46px);
}
.lx-view { display: none; }
/* No fill mode on purpose. `both` holds the 0% keyframe before the animation
   runs, so a throttled or backgrounded tab can leave a whole view stranded at
   opacity 0. Without it the view is simply visible, and the animation is the
   enhancement it should have been. */
.lx-view.on { display: block; animation: lx-in .34s var(--ease); }
@keyframes lx-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .lx-view.on { animation: none; } }

.lx-h1 {
  font-family: var(--font); font-size: clamp(28px, 4.4vw, 40px); font-weight: 600;
  line-height: 1.08; letter-spacing: -.021em;
}
.lx-h2 {
  font-family: var(--font); font-size: 21px; font-weight: 600;
  letter-spacing: -.016em; margin: 40px 0 15px;
}
.lx-h3 { font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.012em; }
.lx-lede { margin-top: 11px; font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 62ch; }
.lx-eyebrow {
  font-family: var(--font); font-size: 12px; font-weight: 600;
  letter-spacing: .006em; color: var(--ink-3); margin-bottom: 9px;
}
/* The trail of pages above this one, after BoardUI's Breadcrumb (lab/core.js,
   crumbs): 12px medium, a soft pill under the pointer, a chevron between the
   links, and the page you are on last, a shade darker and not a link. It
   scrolls sideways, without a bar, sooner than wrap. */
.bc { display: flex; align-items: center; margin: 0 0 9px -4px; padding: 0 4px; overflow-x: auto; scrollbar-width: none; }
.bc::-webkit-scrollbar { display: none; }
.bc ol { display: flex; align-items: center; gap: 10px; margin: 0; padding: 0; list-style: none; }
.bc li { display: flex; align-items: center; font-family: var(--font); font-size: 12px; font-weight: 500; line-height: 16px; white-space: nowrap; }
.bc-a {
  margin: 0 -4px; padding: 2px 4px; border-radius: 6px; font: inherit; color: var(--ink-3);
  transition: color .15s var(--ease), background-color .15s var(--ease);
}
.bc-a:hover { color: var(--ink-2); background: var(--sunk); }
.bc-a:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.bc-sep { color: var(--ink-3); }
.bc-sep svg { display: block; width: 12px; height: 12px; }
.bc-cur { color: var(--ink-2); }
.lx-note {
  margin-top: 44px; padding: 16px 19px; border-radius: 13px; background: var(--paper);
  border: 1px solid var(--hair); font-size: 14px; line-height: 1.55; color: var(--ink-2);
}
.lx-note b { color: var(--ink); font-weight: 600; }
.lx-note a { color: var(--blue); }

/* --------------------------------------------------------------- Button */
.lx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 38px; padding: 0 18px; border-radius: 100px;
  background: var(--blue); color: #fff;
  font-size: 15px; font-weight: 500; letter-spacing: -.01em;
  transition: background .15s var(--ease), opacity .15s var(--ease), transform .08s var(--ease);
}
.lx-btn:hover { background: var(--blue-d); }
.lx-btn:active { transform: scale(.975); }
.lx-btn:disabled { opacity: .4; cursor: default; transform: none; background: var(--blue); }
.lx-btn.lg { height: 46px; padding: 0 26px; font-size: 16px; }
.lx-btn.quiet { background: var(--canvas); color: var(--ink); }
.lx-btn.quiet:hover { background: var(--sunk); }
.lx-btn.ghost { background: transparent; color: var(--blue); padding: 0 6px; }
.lx-btn.ghost:hover { background: var(--canvas); }

/* ---------------------------------------------------------------- Cards */
.lx-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 14px; }
.lx-card {
  display: flex; flex-direction: column; text-align: left;
  padding: 20px; border-radius: var(--r); background: var(--paper);
  border: 1px solid var(--hair); min-height: 178px;
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.lx-card:hover { transform: translateY(-2px); border-color: var(--rule); box-shadow: 0 6px 20px rgba(0,0,0,.05); }
.lx-card .ic {
  width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;
  margin-bottom: 14px; flex: none;
}
.lx-card .ic svg { width: 19px; height: 19px; }
.lx-card h3 { font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.012em; }
.lx-card p { margin-top: 6px; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.lx-card .foot {
  margin-top: auto; padding-top: 15px; display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; color: var(--ink-3);
}
.lx-tag {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border-radius: 100px; background: var(--canvas); color: var(--ink-2);
  font-size: 11.5px; font-weight: 500; letter-spacing: 0;
}
.lx-tag.soon { color: var(--ink-3); }
.lx-tag.live { background: #e8f5ee; color: var(--green); }
.lx-tag.late { background: #fdeceb; color: #c9372c; }

/* Resume strip */
.lx-resume {
  margin-top: 26px; padding: 20px 22px; border-radius: var(--r);
  background: var(--ink); color: #fff;
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
.lx-resume .k { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.55); }
.lx-resume h3 { font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.016em; margin-top: 4px; }
.lx-resume p { margin-top: 5px; font-size: 14px; color: rgba(255,255,255,.66); max-width: 52ch; }
.lx-resume .lx-btn { background: #fff; color: var(--ink); }
.lx-resume .lx-btn:hover { background: #e8e8ea; }

/* Shelf */
.lx-shelf { margin-top: 42px; }
.lx-shelf-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.lx-shelf-head h2 { font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.016em; }
.lx-shelf-head p { font-size: 14px; color: var(--ink-2); }

/* --------------------------------------------------------- Course layout */
.lx-hero { padding-bottom: 26px; border-bottom: 1px solid var(--hair); }
.lx-hero .row { display: flex; align-items: flex-start; gap: 16px; }
.lx-hero .ic { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; flex: none; }
.lx-hero .ic svg { width: 25px; height: 25px; }
.lx-hero .meta { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }

.lx-two { display: grid; grid-template-columns: minmax(0,1fr) 268px; gap: 40px; margin-top: 30px; align-items: start; }
@media (max-width: 1040px) {
  .cn-row { grid-template-columns: minmax(0, 1fr) 120px 150px; }
}
@media (max-width: 900px) { .lx-two { grid-template-columns: 1fr; gap: 30px; } }

.lx-side { position: sticky; top: calc(var(--bar) + var(--sub) + 18px); display: grid; gap: 14px; }
.lx-panel { padding: 18px 19px; border-radius: 14px; background: var(--paper); border: 1px solid var(--hair); }
.lx-panel h3 { font-family: var(--font); font-size: 14px; font-weight: 600; margin-bottom: 11px; }
.lx-panel li { display: flex; gap: 10px; padding: 7px 0; font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }
.lx-panel li b { flex: none; color: var(--ink); font-weight: 500; }
.lx-panel li span:last-child { margin-left: auto; color: var(--ink-3); }
.lx-panel p { font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }

/* Mastery bar */
.lx-mastery { display: flex; height: 8px; border-radius: 100px; overflow: hidden; background: var(--sunk); gap: 2px; }
.lx-mastery i { display: block; flex: 1; background: var(--sunk); }
.lx-mastery i.fam   { background: #b8d8f7; }
.lx-mastery i.prof  { background: #61a8ee; }
.lx-mastery i.master{ background: var(--blue); }
.lx-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 12px; font-size: 12px; color: var(--ink-2); }
.lx-legend span { display: flex; align-items: center; gap: 6px; }
.lx-legend i { width: 9px; height: 9px; border-radius: 3px; background: var(--sunk); }
.lx-legend i.fam { background: #b8d8f7; } .lx-legend i.prof { background: #61a8ee; }
.lx-legend i.master { background: var(--blue); }

/* Unit list */
.lx-units { display: grid; gap: 10px; }
.lx-unit {
  display: flex; align-items: center; gap: 15px; width: 100%; text-align: left;
  padding: 17px 19px; border-radius: 14px; background: var(--paper);
  border: 1px solid var(--hair);
  transition: border-color .16s var(--ease), transform .16s var(--ease);
}
.lx-unit:hover { border-color: var(--rule); transform: translateX(2px); }
.lx-unit .n {
  width: 29px; height: 29px; border-radius: 50%; flex: none; display: grid; place-items: center;
  background: var(--canvas); color: var(--ink-2);
  font-family: var(--font); font-size: 12.5px; font-weight: 600;
}
.lx-unit.done .n { background: var(--blue); color: #fff; }
.lx-unit .txt { min-width: 0; flex: 1; }
.lx-unit .txt b { display: block; font-family: var(--font); font-size: 15.5px; font-weight: 600; letter-spacing: -.01em; }
.lx-unit .txt span { display: block; margin-top: 2px; font-size: 13px; color: var(--ink-3); }
.lx-unit .go { flex: none; color: var(--ink-3); }
/* A unit's own progress, on a course page whose panel replaces the
   course-mastery bars (Algebra I). Tokens only, so both looks follow. */
.lx-umeter { flex: none; width: 64px; height: 4px; border-radius: 4px; background: var(--sunk); overflow: hidden; }
.lx-umeter i { display: block; height: 100%; border-radius: 4px; background: var(--blue); }
.lx-spine { font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.01em; margin: 0 0 12px; }
.lx-part {
  margin: 30px 0 13px; font-family: var(--font); font-size: 12px; font-weight: 600;
  color: var(--ink-3);
}
.lx-part:first-child { margin-top: 0; }

/* ------------------------------------------------------------ Unit page */
.lx-block { margin-top: 26px; }
.lx-block h2 {
  font-family: var(--font); font-size: 13px; font-weight: 600; color: var(--ink-3);
  padding-bottom: 10px; border-bottom: 1px solid var(--hair); margin-bottom: 4px;
}
.lx-item {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 15px 4px; border-bottom: 1px solid var(--hair);
}
.lx-item:last-child { border-bottom: 0; }
.lx-item .ic { width: 22px; height: 22px; flex: none; color: var(--ink-3); }
.lx-item .ic svg { width: 22px; height: 22px; }
.lx-item .txt { flex: 1; min-width: 0; }
.lx-item .txt b { display: block; font-size: 15px; font-weight: 500; }
.lx-item .txt span { display: block; margin-top: 1px; font-size: 13px; color: var(--ink-3); }
.lx-item:hover:not(:disabled) .txt b { color: var(--blue); }
.lx-item:disabled { cursor: default; opacity: .5; }

.lx-pending {
  margin-top: 22px; padding: 22px; border-radius: 14px; background: var(--paper);
  border: 1px dashed var(--rule); text-align: center;
}
.lx-pending b { display: block; font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-pending p { margin-top: 6px; font-size: 14px; line-height: 1.5; color: var(--ink-2); max-width: 50ch; margin-inline: auto; }

/* ============================================================ Study set */
.lx-modes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 26px; }
@media (max-width: 700px) { .lx-modes { grid-template-columns: repeat(2, 1fr); } }
.lx-mode {
  display: flex; flex-direction: column; align-items: flex-start; gap: 9px;
  padding: 17px 16px; border-radius: 14px; background: var(--paper);
  border: 1px solid var(--hair); text-align: left;
  transition: transform .16s var(--ease), border-color .16s var(--ease);
}
.lx-mode:hover { transform: translateY(-2px); border-color: var(--rule); }
.lx-mode svg { width: 21px; height: 21px; color: var(--blue); }
.lx-mode b { font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-mode span { font-size: 12.5px; line-height: 1.4; color: var(--ink-3); }

.lx-terms { margin-top: 34px; display: grid; gap: 9px; }
.lx-term {
  display: grid; grid-template-columns: 210px 1fr auto; gap: 20px; align-items: start;
  padding: 15px 18px; border-radius: 13px; background: var(--paper); border: 1px solid var(--hair);
}
.lx-term b { font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-term p { font-size: 14.5px; line-height: 1.5; color: var(--ink-2); }
.lx-term .star { color: var(--ink-3); width: 20px; height: 20px; flex: none; }
.lx-term .star.on { color: var(--amber); }
/* Two rows on a narrow screen: term and star on the first, definition across
   the second. Auto-placement pushed the star onto a third row of its own. */
@media (max-width: 640px) {
  .lx-term { grid-template-columns: 1fr auto; gap: 8px 14px; }
  .lx-term b    { grid-area: 1 / 1; }
  .lx-term .star{ grid-area: 1 / 2; }
  .lx-term p    { grid-area: 2 / 1 / 3 / 3; }
}

/* --------------------------------------------------------- Flashcards */
.lx-deck { max-width: 680px; margin: 30px auto 0; perspective: 1600px; }
.lx-flip {
  position: relative; width: 100%; aspect-ratio: 16 / 10; min-height: 260px;
  transform-style: preserve-3d; transition: transform .5s var(--ease); cursor: pointer;
}
.lx-flip.back { transform: rotateX(180deg); }
.lx-face {
  position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border-radius: 20px; background: var(--paper); border: 1px solid var(--hair);
  display: grid; place-items: center; padding: 34px; text-align: center;
}
.lx-face.b { transform: rotateX(180deg); }
.lx-face .kind {
  position: absolute; top: 16px; left: 20px;
  font-family: var(--font); font-size: 11.5px; font-weight: 600; color: var(--ink-3);
}
.lx-face p { font-size: clamp(19px, 2.6vw, 27px); line-height: 1.32; letter-spacing: -.014em; }
.lx-face.b p { font-size: clamp(16px, 2vw, 20px); line-height: 1.5; color: var(--ink-2); max-width: 46ch; }
@media (prefers-reduced-motion: reduce) { .lx-flip { transition: none; } }

.lx-deck-bar {
  display: flex; align-items: center; justify-content: center; gap: 22px; margin-top: 22px;
}
.lx-round {
  width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper); border: 1px solid var(--hair); color: var(--ink);
  transition: background .15s var(--ease), border-color .15s var(--ease);
}
.lx-round:hover { border-color: var(--rule); background: var(--canvas); }
.lx-round:disabled { opacity: .35; cursor: default; }
.lx-count { font-family: var(--font); font-size: 15px; font-weight: 500; color: var(--ink-2); min-width: 74px; text-align: center; }
.lx-deck-side { display: flex; justify-content: center; gap: 10px; margin-top: 18px; }
.lx-pill {
  height: 34px; padding: 0 15px; border-radius: 100px; border: 1px solid var(--hair);
  background: var(--paper); font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  display: inline-flex; align-items: center; gap: 7px;
  transition: border-color .15s var(--ease), color .15s var(--ease);
}
.lx-pill:hover { border-color: var(--rule); color: var(--ink); }
.lx-pill[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.lx-pill.warm { color: var(--amber); } .lx-pill.cool { color: var(--green); }

/* -------------------------------------------------------------- Learn */
.lx-stage { max-width: 720px; margin-inline: auto; }
.lx-ask { font-family: var(--font); font-size: clamp(21px, 3vw, 27px); font-weight: 600;
          line-height: 1.24; letter-spacing: -.017em; }
.lx-hint { margin-top: 10px; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.lx-prompt {
  margin-top: 22px; padding: 22px 24px; border-radius: 16px;
  background: var(--paper); border: 1px solid var(--hair);
  font-size: 17px; line-height: 1.5;
}
.lx-figure { margin: 26px 0; display: grid; place-items: center; }
.lx-figure svg { max-width: 100%; height: auto; max-height: 240px; }

.lx-opts { display: grid; gap: 9px; margin-top: 24px; }
.lx-opt {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  padding: 15px 17px; border-radius: 13px; background: var(--paper);
  border: 1.5px solid var(--hair); font-size: 15.5px; line-height: 1.4;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.lx-opt:hover:not(:disabled) { border-color: var(--rule); }
.lx-opt[aria-pressed="true"] { border-color: var(--blue); background: #f2f8fe; }
.lx-opt .lx-key {
  width: 25px; height: 25px; border-radius: 7px; flex: none; display: grid; place-items: center;
  background: var(--canvas); font-family: var(--font); font-size: 12px; font-weight: 600; color: var(--ink-2);
}
.lx-opt[aria-pressed="true"] .lx-key { background: var(--blue); color: #fff; }
.lx-opt.right { border-color: var(--green); background: #eff8f3; }
.lx-opt.right .lx-key { background: var(--green); color: #fff; }
.lx-opt.wrong { border-color: var(--red); background: #fdf1f2; }
.lx-opt.wrong .lx-key { background: var(--red); color: #fff; }
.lx-opt:disabled { cursor: default; }

.lx-numwrap { margin-top: 24px; }
.lx-num {
  width: 100%; height: 54px; padding: 0 17px; border-radius: 13px;
  border: 1.5px solid var(--hair); background: var(--paper); color: var(--ink);
  font-size: 17px; outline: none;
  transition: border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.lx-num:focus { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(0,113,227,.14); }
.lx-num.right { border-color: var(--green); background: #eff8f3; }
.lx-num.wrong { border-color: var(--red); background: #fdf1f2; }
.lx-num:disabled { color: var(--ink-2); }

.lx-verdict {
  margin-top: 22px; padding: 17px 19px; border-radius: 13px;
  border-left: 3px solid var(--rule); background: var(--paper);
}
.lx-verdict b { display: block; font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-verdict p { margin-top: 6px; font-size: 14.5px; line-height: 1.55; color: var(--ink-2); }
.lx-verdict.right { border-left-color: var(--green); }
.lx-verdict.right b { color: var(--green); }
.lx-verdict.wrong { border-left-color: var(--red); }
.lx-verdict.wrong b { color: var(--red); }

.lx-foot {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: rgba(255,255,255,.86);
  -webkit-backdrop-filter: saturate(180%) blur(18px); backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--hair);
}
.lx-foot-in {
  max-width: var(--well); margin-inline: auto;
  padding: 12px max(var(--gut), env(safe-area-inset-left))
           max(12px, env(safe-area-inset-bottom)) max(var(--gut), env(safe-area-inset-right));
  display: flex; align-items: center; gap: 14px;
}
.lx-foot .msg { font-size: 13.5px; color: var(--ink-2); }

/* -------------------------------------------------------------- Match */
.lx-match {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 24px;
}
@media (max-width: 800px) { .lx-match { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .lx-match { grid-template-columns: repeat(2, 1fr); } }
.lx-tile {
  min-height: 116px; padding: 13px; border-radius: 13px;
  background: var(--paper); border: 1.5px solid var(--hair);
  font-size: 13.5px; line-height: 1.38; text-align: left; color: var(--ink);
  display: flex; align-items: center;
  transition: border-color .13s var(--ease), background .13s var(--ease),
              transform .18s var(--ease), opacity .18s var(--ease);
}
.lx-tile.term { font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-tile:hover:not(.gone) { border-color: var(--rule); }
.lx-tile.pick { border-color: var(--blue); background: #f2f8fe; }
.lx-tile.hit  { border-color: var(--green); background: #eff8f3; }
.lx-tile.miss { border-color: var(--red); background: #fdf1f2; }
.lx-tile.gone { opacity: 0; pointer-events: none; transform: scale(.94); }
.lx-timer {
  font-family: var(--font); font-size: 34px; font-weight: 600; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- Test */
.lx-q { padding: 24px 0; border-bottom: 1px solid var(--hair); }
.lx-q:last-of-type { border-bottom: 0; }
.lx-q .qn { font-family: var(--font); font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 9px; }
.lx-q .qt { font-size: 17px; line-height: 1.45; }
.lx-q .lx-opts { margin-top: 16px; }
.lx-q .lx-numwrap { margin-top: 16px; }
.lx-tf { display: flex; gap: 9px; margin-top: 16px; }
.lx-tf .lx-opt { flex: 1; }

/* -------------------------------------------------------------- Result */
.lx-done { max-width: 520px; margin: 30px auto 0; text-align: center; }
.lx-ring { width: 132px; height: 132px; margin: 0 auto 24px; }
.lx-score {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin: 28px 0; padding: 20px 0; border-block: 1px solid var(--hair);
}
.lx-score b { display: block; font-family: var(--font); font-size: 27px; font-weight: 600; letter-spacing: -.018em; }
.lx-score span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--ink-3); }
.lx-review { margin-top: 30px; text-align: left; display: grid; gap: 9px; }
.lx-rev {
  padding: 14px 17px; border-radius: 12px; background: var(--paper);
  border: 1px solid var(--hair); border-left: 3px solid var(--green);
}
.lx-rev.bad { border-left-color: var(--red); }
.lx-rev b { display: block; font-family: var(--font); font-size: 14.5px; font-weight: 600; }
.lx-rev p { margin-top: 4px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.lx-rev .yours { color: var(--red); }

/* ------------------------------------------------------------- Account */
.lx-acct-head { display: flex; align-items: center; gap: 18px; }
.lx-acct-head .av {
  width: 62px; height: 62px; border-radius: 50%; flex: none; display: grid; place-items: center;
  background: var(--ink); color: #fff; font-family: var(--font); font-size: 22px; font-weight: 600;
}
.lx-stars { display: flex; align-items: center; gap: 7px; margin-top: 8px; font-size: 13.5px; color: var(--ink-2); }
.lx-stars svg { width: 14px; height: 14px; color: var(--amber); }
.lx-stat-row {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; margin-top: 26px;
  background: var(--hair); border: 1px solid var(--hair); border-radius: 14px; overflow: hidden;
}
@media (max-width: 800px) { .lx-stat-row { grid-template-columns: repeat(2, 1fr); } }
.lx-stat { background: var(--paper); padding: 17px 18px; }
.lx-stat b { display: block; font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.016em; }
.lx-stat span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--ink-3); }
.lx-fields { display: grid; gap: 0; }
.lx-fields div {
  display: flex; align-items: baseline; gap: 18px; padding: 12px 2px;
  border-bottom: 1px solid var(--hair); font-size: 14.5px;
}
.lx-fields div:last-child { border-bottom: 0; }
.lx-fields b { flex: none; width: 200px; color: var(--ink-2); font-weight: 400; }
.lx-fields span { color: var(--ink); font-weight: 500; }
@media (max-width: 560px) {
  .lx-fields div { flex-direction: column; gap: 2px; }
  .lx-fields b { width: auto; font-size: 13px; }
}
.lx-bal {
  margin-top: 20px; padding: 20px 22px; border-radius: 14px;
  background: var(--paper); border: 1px solid var(--hair);
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
.lx-bal .amt { font-family: var(--font); font-size: 30px; font-weight: 600; letter-spacing: -.02em; }
.lx-bal .k { font-size: 12.5px; color: var(--ink-3); }

/* ---------------------------------------------------------------- Toast */
.lx-toast {
  position: fixed; left: 50%; bottom: 26px; z-index: 60;
  transform: translateX(-50%) translateY(12px);
  padding: 11px 20px; border-radius: 100px;
  background: var(--ink); color: #fff; font-size: 14px;
  opacity: 0; pointer-events: none;
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.lx-toast.on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ----------------------------------------------------------- Small screens */
@media (max-width: 734px) {
  .lx-bar-in { gap: 10px; }
  .lx-user .nm, .lx-name { display: none; }
  .lx-top button { padding: 0 10px; font-size: 13.5px; }
  .lx-wrap { padding-top: 22px; padding-bottom: 110px; }
  .lx-h2 { margin-top: 32px; }
  .lx-term { padding: 14px 15px; }
  .lx-resume { flex-direction: column; align-items: flex-start; gap: 15px; }
  .lx-resume .lx-btn { width: 100%; }
  .lx-modes { gap: 9px; }
  .lx-mode { padding: 14px 13px; }
  .lx-mode span { display: none; }
  .lx-flip { min-height: 220px; aspect-ratio: 3 / 2; }
  .lx-face { padding: 24px; }
}

/* ============================================================== Sign in
   The sign-in form's fields. The page around it — the welcome page, and the
   panel the form sits in — is landing.css. */
.lx-form { margin-top: 26px; display: grid; gap: 10px; text-align: left; }
.lx-field label {
  display: block; margin-bottom: 6px;
  font-family: var(--font); font-size: 12.5px; font-weight: 600; color: var(--ink-2);
}
.lx-field input {
  width: 100%; height: 48px; padding: 0 15px; border-radius: 12px;
  border: 1.5px solid var(--hair); background: var(--paper); color: var(--ink);
  font-size: 16px; outline: none; -webkit-appearance: none; appearance: none;
  transition: border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.lx-field input:focus { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(0,113,227,.14); }
.lx-field input.bad { border-color: var(--red); }

/* ============================================== Home: command centre */
.lx-hello { font-size: 15px; color: var(--ink-2); }
.lx-next {
  margin-top: 20px; padding: 24px 26px; border-radius: 18px;
  background: var(--ink); color: #fff;
}
.lx-next .k { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.5); }
.lx-next h2 {
  font-family: var(--font); font-size: clamp(22px, 3vw, 28px); font-weight: 600;
  letter-spacing: -.018em; margin-top: 6px;
}
.lx-next .why { margin-top: 8px; font-size: 14.5px; line-height: 1.5; color: rgba(255,255,255,.68); max-width: 54ch; }
.lx-next .lx-btn { margin-top: 18px; background: #fff; color: var(--ink); }
.lx-next .lx-btn:hover { background: #e8e8ea; }
.lx-next .warn {
  margin-top: 14px; padding: 12px 15px; border-radius: 11px;
  background: rgba(255,255,255,.08); font-size: 13.5px; line-height: 1.5;
  color: rgba(255,255,255,.8);
}
.lx-next .warn b { color: #fff; font-weight: 600; }

/* Session plan */
.lx-plan { display: grid; gap: 8px; margin-top: 15px; }
.lx-step {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  padding: 13px 16px; border-radius: 12px; background: var(--paper);
  border: 1px solid var(--hair);
  transition: border-color .15s var(--ease), transform .15s var(--ease);
}
.lx-step:hover { border-color: var(--rule); transform: translateX(2px); }
.lx-step .ic { width: 20px; height: 20px; flex: none; color: var(--blue); }
.lx-step .txt { flex: 1; min-width: 0; }
.lx-step .txt b { display: block; font-size: 14.5px; font-weight: 500; }
.lx-step .txt span { display: block; margin-top: 1px; font-size: 12.5px; color: var(--ink-3); }
.lx-step .mins { flex: none; font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.lx-step.done { opacity: .55; }
.lx-step.done .txt b { text-decoration: line-through; }

/* Subject progress */
.lx-bars { display: grid; gap: 13px; margin-top: 15px; }
.lx-barrow { display: grid; grid-template-columns: 118px 1fr 44px; gap: 14px; align-items: center; }
.lx-barrow b { font-family: var(--font); font-size: 14px; font-weight: 500; }
.lx-barrow .track { height: 8px; border-radius: 100px; background: var(--sunk); overflow: hidden; }
.lx-barrow .track i { display: block; height: 100%; border-radius: 100px; background: var(--blue);
                      transition: width .7s var(--ease); }
.lx-barrow .pc { font-size: 13px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
@media (max-width: 560px) { .lx-barrow { grid-template-columns: 92px 1fr 40px; gap: 10px; } }

/* ================================================ Mastery, four ways */
.lx-dims { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 16px; }
@media (max-width: 620px) { .lx-dims { grid-template-columns: repeat(2, 1fr); } }
.lx-dim { text-align: center; }
.lx-dim svg { width: 62px; height: 62px; margin: 0 auto 8px; }
.lx-dim b { display: block; font-family: var(--font); font-size: 13px; font-weight: 600; }
.lx-dim span { display: block; margin-top: 2px; font-size: 11.5px; color: var(--ink-3); }

/* ==================================================== Knowledge map
   One stage: what you have, what to do next, then the map beside the unit
   you are looking at. Colour is spent on state and nothing else — the
   course hue for progress, amber for what is slipping, red for a confident
   mistake — so a glance at the board reads as a sentence. */
.km { --hue: var(--blue); --amber: #ff9f0a; padding-bottom: 36px; }
.km svg .trk { fill: none; stroke: var(--sunk); }
.km svg .arc { fill: none; stroke: var(--hue); stroke-linecap: round; animation: km-fill 1.1s var(--ease) both .2s; }

.km-hud { display: grid; gap: 24px; margin-bottom: 24px; }
.km-lede { max-width: 640px; margin-top: 10px; font-size: 19px; line-height: 1.45; letter-spacing: -.01em; color: var(--ink-2); }
.km-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 10px; }
.km-stat {
  display: flex; flex-direction: column; justify-content: space-between; gap: 10px; min-height: 98px;
  padding: 16px 16px 14px; border-radius: 18px; background: var(--paper); border: 1px solid var(--hair);
  animation: km-rise .5s var(--ease) both;
}
.km-stat:nth-child(2) { animation-delay: .04s; } .km-stat:nth-child(3) { animation-delay: .08s; }
.km-stat:nth-child(4) { animation-delay: .12s; } .km-stat:nth-child(5) { animation-delay: .16s; }
.km-stat .v { display: flex; align-items: center; gap: 10px; }
.km-stat b { font-family: var(--font); font-size: 28px; font-weight: 600; line-height: 1; letter-spacing: -.02em; color: var(--ink); }
.km-stat b small { margin-left: 2px; font-size: 15px; font-weight: 500; color: var(--ink-3); }
.km-stat > span { font-size: 12.5px; color: var(--ink-3); }
.km-stat.ring svg { width: 44px; height: 44px; flex: none; }
.km-stat.ring .trk, .km-stat.ring .arc { stroke-width: 6; }
.km-stat.streak svg { width: 26px; height: 26px; flex: none; color: #d8d8dc; }
.km-stat.streak.on svg { color: #ff7a00; filter: drop-shadow(0 3px 6px rgba(255,122,0,.35)); animation: km-flicker 3s ease-in-out infinite; transform-origin: 50% 90%; }
.km-stat.rank .v { flex-direction: column; align-items: stretch; gap: 11px; }
.km-stat.rank b { font-size: 21px; }
.km-bar { display: block; height: 6px; border-radius: 99px; background: var(--sunk); overflow: hidden; }
.km-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--hue); transform-origin: left; animation: km-grow 1s var(--ease) both .25s; }

.km-news {
  display: flex; align-items: center; gap: 12px; margin-bottom: 24px; padding: 13px 16px; border-radius: 16px;
  background: color-mix(in srgb, var(--hue) 9%, #fff); font-size: 14.5px; line-height: 1.45; color: var(--ink);
  animation: km-rise .5s var(--ease) both .1s;
}
.km-news svg { width: 22px; height: 22px; flex: none; color: var(--hue); animation: km-spin 1.2s var(--ease) both .3s; }
.km-news p { margin: 0; }

.km-h2 { margin: 0 0 12px; font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.015em; }
.km-missions { margin-bottom: 30px; }
.km-mrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }
.km-m {
  --mc: var(--hue);
  display: grid; grid-template-columns: 42px 1fr; grid-template-rows: 1fr auto; gap: 4px 13px;
  padding: 16px; border-radius: 18px; background: var(--paper); border: 1px solid var(--hair);
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s;
  animation: km-rise .5s var(--ease) both; animation-delay: calc(.08s * var(--i, 0) + .15s);
}
.km-m:hover { transform: translateY(-3px); border-color: transparent; box-shadow: 0 14px 32px rgba(0,0,0,.08); }
.km-m:active { transform: translateY(-1px) scale(.99); }
.km-m .ic { grid-row: 1 / 3; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 13px; background: color-mix(in srgb, var(--mc) 13%, #fff); color: var(--mc); }
.km-m .ic svg { width: 22px; height: 22px; }
.km-m .tx b { display: block; font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--ink); }
.km-m .tx span { display: block; margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.km-m .xp { justify-self: start; margin-top: 9px; padding: 3px 10px; border-radius: 99px; font-size: 12px; font-weight: 700; background: color-mix(in srgb, var(--mc) 13%, #fff); color: color-mix(in srgb, var(--mc) 78%, #000); }
.km-m.k-fading { --mc: #e58a00; }
.km-m.k-flagged { --mc: var(--red); }
.km-m.k-open { --mc: var(--green); }

.km-stage { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 16px; align-items: start; }
@media (max-width: 1080px) { .km-stage { grid-template-columns: 1fr; } }
.km-board {
  container: km / inline-size; overflow-x: auto; padding: 4px 0 10px; border-radius: 24px;
  border: 1px solid var(--hair);
  background: radial-gradient(circle at 1px 1px, #e2e2e7 1px, transparent 0) 0 0 / 22px 22px, var(--paper);
}
.km-board-in { position: relative; width: var(--w); height: var(--h); margin: 0 auto; }
.km-edges { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.km-edges.v { display: none; }
.km-edges path { fill: none; stroke-width: 3; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.km-edges .dim { stroke: #d6d6db; stroke-width: 2; stroke-dasharray: .012 .02; }
.km-edges .lit { stroke: var(--hue); stroke-dasharray: 1; opacity: .85; animation: km-draw 1s var(--ease) both; animation-delay: calc(.07s * var(--i, 0) + .25s); }
.km-edges .flow { stroke: #fff; stroke-width: 3; stroke-dasharray: .025 .075; opacity: .9; animation: km-flow 2.4s linear infinite; }

.km-node {
  position: absolute; left: var(--x); top: var(--y); width: 144px; margin: -40px 0 0 -72px; padding: 0;
  display: flex; flex-direction: column; align-items: center; background: none; border: 0;
  font: inherit; color: inherit; text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent;
  animation: km-pop .6s var(--ease) both; animation-delay: calc(.05s * var(--i, 0) + .1s);
}
.km-orb { position: relative; width: 80px; height: 80px; border-radius: 50%; background: var(--paper); box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 8px 20px rgba(0,0,0,.07); transition: transform .25s var(--ease), box-shadow .25s var(--ease); }
.km-orb > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.km-orb .trk, .km-orb .arc { stroke-width: 6; }
.km-core { position: absolute; inset: 11px; display: grid; place-items: center; border-radius: 50%; background: var(--canvas); font-family: var(--font); font-size: 22px; font-weight: 600; color: var(--ink); transition: background .2s; }
.km-core svg { width: 26px; height: 26px; }
.km-node:hover .km-orb { transform: translateY(-3px) scale(1.05); box-shadow: 0 2px 4px rgba(0,0,0,.06), 0 16px 32px rgba(0,0,0,.11); }
.km-node:active .km-orb { transform: scale(.97); }
.km-node:focus-visible { outline: none; }
.km-node:focus-visible .km-orb { box-shadow: 0 0 0 3px var(--paper), 0 0 0 6px var(--hue); }
.km-node.on .km-orb { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5.5px color-mix(in srgb, var(--hue) 60%, transparent), 0 14px 32px rgba(0,0,0,.12); }
.km-txt { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.km-name { max-width: 134px; margin-top: 11px; overflow: hidden; font-size: 13px; font-weight: 600; line-height: 1.25; color: var(--ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.km-state { margin-top: 3px; font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }

.km-node.s-mastered .km-core { background: var(--hue); color: #fff; box-shadow: inset 0 -8px 16px rgba(0,0,0,.14), inset 0 6px 12px rgba(255,255,255,.18); }
.km-node.s-mastered .km-state { font-weight: 600; color: color-mix(in srgb, var(--hue) 80%, #000); }
.km-node.s-fading .km-core { background: color-mix(in srgb, var(--hue) 55%, #fff); color: #fff; }
.km-node.s-fading .arc { stroke: var(--amber); }
.km-node.s-fading .km-state { font-weight: 600; color: #b86200; }
.km-node.s-active .km-core { background: color-mix(in srgb, var(--hue) 11%, #fff); color: color-mix(in srgb, var(--hue) 82%, #000); }
.km-node.s-ready .km-core { background: #fff; color: var(--hue); }
.km-node.s-ready .trk { stroke: color-mix(in srgb, var(--hue) 28%, #fff); }
.km-node.s-ready .km-state { font-weight: 600; color: var(--hue); }
.km-node.s-ready .km-orb::after, .km-node.is-here .km-orb::after {
  content: ""; position: absolute; inset: -7px; border: 2px solid var(--hue); border-radius: 50%;
  opacity: 0; pointer-events: none; animation: km-halo 2.4s var(--ease) infinite 1s;
}
.km-node.s-fading.is-here .km-orb::after { border-color: var(--amber); }
.km-node.s-locked .km-orb { background: rgba(255,255,255,.7); box-shadow: none; }
.km-node.s-locked .trk { stroke: #cfcfd4; stroke-dasharray: 4 5; }
.km-node.s-locked .km-core { background: transparent; color: var(--ink-3); }
.km-node.s-locked .km-name { color: var(--ink-2); }
.km-lock { position: absolute; right: -2px; bottom: -2px; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--paper); color: var(--ink-3); box-shadow: 0 1px 4px rgba(0,0,0,.12); }
.km-lock svg { width: 14px; height: 14px; }
.km-node.s-unwritten .km-orb { background: transparent; box-shadow: none; transform: scale(.8); }
.km-node.s-unwritten:hover .km-orb { transform: scale(.84); box-shadow: none; }
.km-node.s-unwritten .trk { stroke: #d9d9de; stroke-width: 3; stroke-dasharray: .1 7; stroke-linecap: round; }
.km-node.s-unwritten .km-core { background: transparent; font-size: 19px; color: #b9b9bf; }
.km-node.s-unwritten .km-name, .km-node.s-unwritten .km-state { font-weight: 500; color: #a8a8ae; }

.km-pip { position: absolute; top: -3px; right: -5px; display: grid; place-items: center; min-width: 24px; height: 24px; padding: 0 6px; border: 2.5px solid var(--paper); border-radius: 99px; font-size: 12px; font-weight: 700; color: #fff; }
.km-pip.fade { background: var(--amber); }
.km-pip.flag { background: var(--red); }
.km-flag {
  position: absolute; top: -36px; left: 50%; z-index: 2; padding: 5px 11px; border-radius: 99px;
  background: var(--ink); color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap; transform: translateX(-50%); box-shadow: 0 8px 18px rgba(0,0,0,.2); animation: km-bob 2.8s ease-in-out infinite;
}
.km-flag::after { content: ""; position: absolute; left: 50%; bottom: -4px; width: 9px; height: 9px; margin-left: -4.5px; border-radius: 2px; background: inherit; transform: rotate(45deg); }
.km-delta { position: absolute; top: -10px; left: calc(50% + 32px); font-family: var(--font); font-size: 15px; font-weight: 700; color: var(--green); pointer-events: none; animation: km-up 2.6s var(--ease) both .9s; }
.km-node.is-up .km-orb { animation: km-glow 1.4s var(--ease) .7s 2; }

/* Narrow: a path down the left, names beside the orbs. */
@container km (max-width: 620px) {
  .km-board-in { width: 100%; height: var(--vh); }
  .km-edges.h { display: none; }
  .km-edges.v { display: block; }
  .km-node { left: 16px; top: var(--vy); flex-direction: row; gap: 14px; width: calc(100% - 32px); margin: -40px 0 0; text-align: left; }
  .km-orb { flex: none; }
  .km-txt { align-items: flex-start; }
  .km-name { max-width: none; margin-top: 0; font-size: 14.5px; }
  .km-state { margin-top: 2px; font-size: 12.5px; white-space: normal; }
  .km-flag { top: -13px; left: 94px; padding: 3px 9px; font-size: 10px; transform: none; animation: none; }
  .km-flag::after { display: none; }
  .km-delta { top: -4px; left: 70px; }
}

.km-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 16px; padding: 12px 8px 0; font-size: 12px; color: var(--ink-3); }
.km-legend span { display: inline-flex; align-items: center; gap: 6px; }
.km-legend i { width: 11px; height: 11px; border-radius: 50%; border: 2px solid #cfcfd4; background: var(--paper); }
.km-legend i.s-mastered { border-color: var(--hue); background: var(--hue); }
.km-legend i.s-active { border-color: var(--hue); background: color-mix(in srgb, var(--hue) 22%, #fff); }
.km-legend i.s-ready { border-color: var(--hue); }
.km-legend i.s-locked { border-style: dashed; }
.km-legend i.s-fading { border-color: var(--amber); background: color-mix(in srgb, var(--hue) 55%, #fff); }

.km-sheet { position: sticky; top: calc(var(--bar) + 16px); max-height: calc(100vh - var(--bar) - 32px); overflow-y: auto; padding: 22px; border-radius: 24px; background: var(--paper); border: 1px solid var(--hair); overscroll-behavior: contain; }
@media (max-width: 1080px) { .km-sheet { position: static; max-height: none; } }
.km-sheet-in { animation: km-rise .35s var(--ease) both; }
.km-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; font-size: 12px; font-weight: 600; letter-spacing: .02em; color: var(--ink-3); }
.km-tag { padding: 2px 9px; border-radius: 99px; font-size: 11px; font-weight: 700; letter-spacing: .01em; background: var(--sunk); color: var(--ink-2); }
.km-tag.s-mastered { background: color-mix(in srgb, var(--hue) 14%, #fff); color: color-mix(in srgb, var(--hue) 78%, #000); }
.km-tag.s-fading { background: #fff0d6; color: #9a5300; }
.km-tag.s-active { background: color-mix(in srgb, var(--hue) 10%, #fff); color: color-mix(in srgb, var(--hue) 75%, #000); }
.km-tag.s-ready { background: #e2f5e9; color: var(--green); }
.km-sheet-h { margin: 8px 0 16px; font-family: var(--font); font-size: 25px; font-weight: 600; line-height: 1.15; letter-spacing: -.02em; }
.km-sheet-top { display: flex; align-items: center; gap: 18px; }
.km-big { position: relative; width: 96px; height: 96px; flex: none; }
.km-big svg { width: 100%; height: 100%; }
.km-big .trk, .km-big .arc { stroke-width: 8; }
.km-big b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: -.02em; }
.km-big b small { font-size: 13px; font-weight: 500; color: var(--ink-3); }
.km-facts { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: 13px; color: var(--ink-2); }
.km-facts b { font-weight: 600; color: var(--ink); }
.km-facts .amber b { color: #b86200; }
.km-facts .red b { color: var(--red); }
.km-say { margin: 16px 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.km-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.km-sub { margin: 26px 0 4px; font-family: var(--font); font-size: 15px; font-weight: 600; }
.km-subp { margin: 0 0 4px; font-size: 12.5px; line-height: 1.45; color: var(--ink-3); }
.km-tier { margin-top: 12px; }
.km-tier > span { display: block; margin-bottom: 7px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
.km-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.km-c {
  --b: #c7c7cc; display: inline-flex; align-items: center; gap: 7px; padding: 6px 10px 6px 8px; border-radius: 99px;
  border: 1px solid var(--hair); background: var(--paper); font: inherit; font-size: 12.5px; color: var(--ink); cursor: pointer;
  transition: border-color .15s, background .15s, transform .15s var(--ease);
}
.km-c::before { content: ""; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--b); }
.km-c b { font-weight: 500; }
.km-c:hover { border-color: var(--rule); transform: translateY(-1px); }
.km-c.on { border-color: var(--ink); background: var(--canvas); }
.km-c .lad { display: inline-flex; gap: 2.5px; }
.km-c .lad i { width: 4.5px; height: 4.5px; border-radius: 50%; background: #dcdce0; }
.km-c .lad i.on { background: var(--b); }
.km-c svg { width: 13px; height: 13px; color: var(--amber); }
.km-c em { font-style: normal; font-weight: 800; color: var(--red); }
.km-c.b-mastered { border-color: color-mix(in srgb, var(--b) 35%, #fff); background: color-mix(in srgb, var(--b) 9%, #fff); }
.km-c.fading { border-color: #ffd08a; }
.km-c.flagged { border-color: #ffb3b9; }
.km-cd { margin-top: 12px; padding: 15px; border-radius: 16px; background: var(--canvas); animation: km-rise .3s var(--ease) both; }
.km-cd .km-eyebrow i { width: 8px; height: 8px; border-radius: 50%; }
.km-cd h4 { margin: 6px 0 4px; font-family: var(--font); font-size: 17px; font-weight: 600; }
.km-cd p { margin: 0 0 8px; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.km-cd .why { color: var(--ink); }
.km-ladder { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; margin: 12px 0; padding: 0; list-style: none; }
.km-ladder li { display: flex; flex-direction: column; align-items: center; gap: 5px; font-size: 10.5px; color: var(--ink-3); }
.km-ladder svg { width: 24px; height: 24px; padding: 4px; border-radius: 50%; background: var(--paper); color: #c7c7cc; }
.km-ladder li.on { font-weight: 600; color: var(--ink); }
.km-ladder li.on svg { background: var(--hue); color: #fff; }
.km-ladder li.na { opacity: .35; }
.km-cd .km-warn { padding: 9px 11px; border-radius: 11px; background: #ffe8ea; color: #9c000e; }
.km-cd .km-warn.amber { background: #fff0d6; color: #884a00; }
.km-cd .km-rests { font-size: 12.5px; color: var(--ink-3); }

.km-teaser {
  display: block; width: 100%; margin-bottom: 22px; padding: 18px 19px; border-radius: 14px;
  border: 1px solid var(--hair); background: var(--paper); font: inherit; color: inherit; text-align: left; cursor: pointer;
  transition: box-shadow .22s var(--ease), transform .22s var(--ease);
}
.km-teaser:hover { transform: translateY(-2px); box-shadow: 0 12px 30px rgba(0,0,0,.07); }
.km-t-top { display: flex; align-items: center; justify-content: space-between; }
.km-t-top b { font-family: var(--font); font-size: 14px; font-weight: 600; }
.km-t-top .go { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 600; color: var(--blue); }
.km-t-top .go svg { width: 15px; height: 15px; transition: transform .2s var(--ease); }
.km-teaser:hover .go svg { transform: translateX(3px); }
.km-t-trail { position: relative; display: flex; align-items: center; justify-content: space-between; margin: 18px 2px 15px; }
.km-t-trail::before { content: ""; position: absolute; left: 7px; right: 7px; top: 50%; height: 2px; margin-top: -1px; background: var(--sunk); }
.km-t-trail i { position: relative; width: 16px; height: 16px; border-radius: 50%; border: 2.5px solid #d2d2d7; background: var(--paper); }
.km-t-trail i.s-mastered { border-color: var(--hue); background: var(--hue); }
.km-t-trail i.s-fading { border-color: var(--amber); background: color-mix(in srgb, var(--hue) 55%, #fff); }
.km-t-trail i.s-active { border-color: var(--hue); background: color-mix(in srgb, var(--hue) 25%, #fff); }
.km-t-trail i.s-ready { border-color: var(--hue); }
.km-t-trail i.s-locked { border-style: dashed; }
.km-t-trail i.is-here { box-shadow: 0 0 0 5px color-mix(in srgb, var(--hue) 22%, transparent); }
.km-t-say { display: block; font-size: 14px; line-height: 1.45; color: var(--ink); }
.km-t-facts { display: block; margin-top: 4px; font-size: 12.5px; color: var(--ink-3); }

@keyframes km-rise { from { opacity: 0; transform: translateY(10px); } }
@keyframes km-pop { 0% { opacity: 0; transform: scale(.55); } 65% { opacity: 1; transform: scale(1.06); } 100% { transform: none; } }
@keyframes km-draw { from { stroke-dashoffset: 1; } }
@keyframes km-flow { to { stroke-dashoffset: -1; } }
@keyframes km-fill { from { stroke-dasharray: 0 100; } }
@keyframes km-grow { from { transform: scaleX(0); } }
@keyframes km-halo { 0% { opacity: .6; transform: scale(.9); } 100% { opacity: 0; transform: scale(1.28); } }
@keyframes km-bob { 50% { transform: translate(-50%, -4px); } }
@keyframes km-up { 0% { opacity: 0; transform: translateY(8px); } 18% { opacity: 1; transform: none; } 78% { opacity: 1; } 100% { opacity: 0; transform: translateY(-16px); } }
@keyframes km-glow { 50% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--green) 22%, transparent), 0 14px 32px rgba(0,0,0,.1); } }
@keyframes km-spin { from { transform: rotate(-90deg) scale(.4); opacity: 0; } }
@keyframes km-flicker { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.06, .96); } 60% { transform: scale(.97, 1.04); } }
@media (prefers-reduced-motion: reduce) {
  .km *, .km-teaser, .km-teaser * { animation: none !important; transition: none !important; }
}
@media (max-width: 560px) {
  .km-lede { font-size: 16px; }
  .km-stats { grid-template-columns: repeat(2, 1fr); }
  .km-stat { min-height: 86px; padding: 13px; }
  .km-stat b { font-size: 24px; }
  .km-stat.rank:nth-child(odd) { grid-column: 1 / -1; }
  .km-sheet { padding: 18px; border-radius: 20px; }
  .km-board { border-radius: 20px; }
}

/* ==================================================== Mistake book */
.lx-mistakes { display: grid; gap: 9px; margin-top: 15px; }
.lx-mistake {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 14px 17px; border-radius: 12px; background: var(--paper);
  border: 1px solid var(--hair); border-left: 3px solid var(--red);
}
.lx-mistake .txt { flex: 1; min-width: 0; }
.lx-mistake b { display: block; font-family: var(--font); font-size: 14.5px; font-weight: 600; }
.lx-mistake p { margin-top: 3px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.lx-mistake .n {
  flex: none; font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.lx-empty {
  margin-top: 15px; padding: 22px; border-radius: 13px; background: var(--paper);
  border: 1px dashed var(--rule); text-align: center; font-size: 14px; color: var(--ink-2);
}

/* ======================================================== AI tutor */
.lx-tutor {
  margin-top: 26px; padding: 22px 24px; border-radius: 16px;
  background: var(--paper); border: 1px solid var(--hair);
}
.lx-tutor-head { display: flex; align-items: center; gap: 11px; }
.lx-tutor-head svg { width: 20px; height: 20px; color: var(--blue); }
.lx-tutor-head b { font-family: var(--font); font-size: 15px; font-weight: 600; }
.lx-tutor p { margin-top: 10px; font-size: 14.5px; line-height: 1.55; color: var(--ink-2); max-width: 58ch; }
.lx-modes-row { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 15px; }
.lx-modes-row span {
  display: inline-flex; align-items: center; height: 27px; padding: 0 11px;
  border-radius: 100px; background: var(--canvas); color: var(--ink-2);
  font-size: 12.5px; font-weight: 500;
}

/* ==================================================================== Read
   The reading view. Apple News sets an article the way a magazine does — a
   kicker, a headline with real size to it, a standfirst in a lighter weight,
   then a narrow, generous column of body text. Everything below follows that,
   including the rule that a definition or a pulled quote gets its own shape
   rather than being a paragraph in bold. */
.rd {
  --measure: 34em;
  max-width: 760px; margin-inline: auto;
  font-size: 19px; line-height: 1.62; letter-spacing: -.013em;
}
.rd-kicker {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font); font-size: 13px; font-weight: 600;
  letter-spacing: .004em; color: var(--blue);
}
.rd-kicker .num {
  display: inline-flex; align-items: center; height: 21px; padding: 0 8px;
  border-radius: 100px; background: rgba(0,113,227,.1); font-size: 12px;
}
.rd h1 {
  margin-top: 14px;
  font-family: var(--font); font-size: clamp(34px, 5vw, 50px); font-weight: 600;
  line-height: 1.05; letter-spacing: -.024em;
}
.rd-stand {
  margin-top: 18px; font-size: clamp(19px, 2.1vw, 23px); line-height: 1.45;
  letter-spacing: -.017em; color: var(--ink-2);
}
.rd-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
  margin-top: 24px; padding: 15px 0; border-block: 1px solid var(--hair);
  font-size: 13.5px; color: var(--ink-3);
}
.rd-meta b { font-family: var(--font); font-weight: 600; color: var(--ink-2); }
.rd-obj { margin-top: 18px; padding-left: 0; }
.rd-obj li {
  position: relative; padding-left: 22px; margin-bottom: 6px;
  font-size: 15px; line-height: 1.5; color: var(--ink-2);
}
.rd-obj li::before {
  content: ""; position: absolute; left: 4px; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--blue);
}

.rd-body { margin-top: 34px; }
.rd-body > * { max-width: var(--measure); }
.rd-body p { margin-bottom: 1.3em; }
.rd-body p em { font-style: italic; }
.rd-body h2 {
  margin: 2.4em 0 .8em;
  font-family: var(--font); font-size: 25px; font-weight: 600;
  letter-spacing: -.018em; line-height: 1.2;
}
.rd-body h2:first-child { margin-top: 0; }

/* A definition is a thing, not a sentence in bold. */
/* ------------------------------------------------------------- Figures
   Pictures inside a section. They sit in the reading column at its measure,
   with room above and below, so a photograph reads as a pause rather than a
   wall. Photo pairs share a row and a crop; comparisons keep each image's
   own shape; diagrams keep their own edges and no rounded frame. The caption
   is set for reading, the credit beneath it small. */
.rd-fig { max-width: var(--measure); margin: 2.1em 0; }
.rd-fig-imgs { display: grid; gap: 10px; align-items: start; }
.rd-fig.cols-2 .rd-fig-imgs { grid-template-columns: 1fr 1fr; }
.rd-fig.cols-3 .rd-fig-imgs { grid-template-columns: repeat(3, 1fr); gap: 8px; }
.rd-fig-frame { position: relative; line-height: 0; }
.rd-fig img {
  display: block; width: 100%; height: auto;
  border-radius: 14px; background: var(--sunk);
}
.rd-fig.cols-2:not(.natural) img { aspect-ratio: 4 / 3; object-fit: cover; }
.rd-fig.cols-3 img { border-radius: 10px; }
.rd-fig.diagram img { border-radius: 0; background: none; }
.rd-fig.small .rd-fig-imgs { max-width: 320px; margin-inline: auto; }
/* Tall portraits and narrow diagrams: full width would make a portrait taller
   than the screen, so it is held to a column a reader can take in whole. */
.rd-fig.medium .rd-fig-imgs { max-width: 420px; margin-inline: auto; }
.rd-fig-label {
  display: block; margin-bottom: 7px;
  font-family: var(--text); font-size: 11px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.rd-fig figcaption {
  margin-top: 11px;
  font-family: var(--text); font-size: 14px; line-height: 1.5; letter-spacing: 0;
  color: var(--ink-2);
}
.rd-fig.small figcaption, .rd-fig.medium figcaption { max-width: 460px; margin-inline: auto; text-align: center; }
.rd-fig .credit { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-3); }
.rd-fig .credit a {
  color: inherit;
  text-decoration: underline; text-decoration-color: var(--rule); text-underline-offset: 2px;
}
.rd-fig .credit a:hover { color: var(--ink-2); }

/* Every picture enlarges. The hint sits in the corner of the picture and
   shows on hover or focus, so the column stays quiet until it is wanted; on
   a touch screen, where nothing hovers, it stays faintly visible. */
.rd-zoomable { cursor: zoom-in; }
.rd-zoomable:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
.rd-fig-hint {
  position: absolute; right: 10px; bottom: 10px; display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 8px; border-radius: 100px; pointer-events: none;
  background: rgba(29,29,31,.72); color: #fff; line-height: 1;
  font-family: var(--text); font-size: 12px; font-weight: 600; letter-spacing: 0;
  opacity: 0; transform: translateY(3px); transition: opacity .18s var(--ease), transform .18s var(--ease);
}
.rd-fig-hint svg { width: 13px; height: 13px; }
.rd-fig-frame:hover .rd-fig-hint, .rd-zoomable:focus-visible + .rd-fig-hint { opacity: 1; transform: none; }
@media (hover: none) { .rd-fig-hint { opacity: .82; transform: none; } }

.rd-zoom {
  position: fixed; inset: 0; z-index: 3000; display: flex; flex-direction: column;
  align-items: center; gap: 16px; padding: 64px 28px 28px;
  background: rgba(16,16,18,.95); animation: rd-zoom-in .2s var(--ease);
}
@keyframes rd-zoom-in { from { opacity: 0; } to { opacity: 1; } }
.rd-zoom-stage { flex: 1; min-height: 0; width: 100%; display: flex; align-items: center; justify-content: center; }
.rd-zoom-stage img { display: block; max-width: 100%; max-height: 100%; border-radius: 12px; }
.rd-zoom-stage img.vector {
  width: min(100%, calc((100dvh - 190px) * var(--ar, 1.4)), 1500px); height: auto; max-height: none;
  padding: 18px; background: #fff;
}
.rd-zoom-cap {
  max-width: 780px; margin: 0; text-align: center;
  font-family: var(--text); font-size: 16px; line-height: 1.55; color: rgba(255,255,255,.88);
}
.rd-zoom-x {
  position: absolute; top: 14px; right: 16px; width: 44px; height: 44px; border: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; background: rgba(255,255,255,.14); color: #fff;
}
.rd-zoom-x:hover { background: rgba(255,255,255,.24); }
.rd-zoom-x svg { width: 20px; height: 20px; }
@media (prefers-reduced-motion: reduce) { .rd-zoom { animation: none; } .rd-fig-hint { transition: none; } }

/* Sources, at a size a reader will actually read. */
.rd-refs {
  max-width: var(--measure); margin: 2.6em 0 .6em; padding: 20px 22px 18px;
  border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--rule);
  font-family: var(--text); letter-spacing: 0;
}
.rd-refs h3 {
  margin: 0 0 10px; font-size: 13px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-2);
}
.rd-refs ol { margin: 0; padding-left: 22px; list-style: decimal; display: flex; flex-direction: column; gap: 9px; }
.rd-refs li { display: list-item; }
.rd-refs li { font-size: 15.5px; line-height: 1.5; color: var(--ink); }
.rd-refs li::marker { color: var(--ink-3); font-size: 14px; }
.rd-refs a {
  color: var(--blue); font-weight: 500; text-decoration: underline;
  text-decoration-color: rgba(0,113,227,.35); text-underline-offset: 3px; white-space: nowrap;
}
.rd-refs-note { display: block; margin-top: 2px; font-size: 14px; color: var(--ink-2); }

/* Composition grids, drawn over the photograph rather than into it. The lines
   carry a faint dark edge so they read on a bright sky and on a dark field. */
.rd-fig-grid {
  --a: 33.333%; --b: 66.667%; --c: rgba(255, 255, 255, .92);
  position: absolute; inset: 0; pointer-events: none;
  border-radius: 14px; overflow: hidden;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, .55));
  background:
    linear-gradient(to right, transparent calc(var(--a) - 1px), var(--c) calc(var(--a) - 1px),
                    var(--c) calc(var(--a) + 1px), transparent calc(var(--a) + 1px)),
    linear-gradient(to right, transparent calc(var(--b) - 1px), var(--c) calc(var(--b) - 1px),
                    var(--c) calc(var(--b) + 1px), transparent calc(var(--b) + 1px)),
    linear-gradient(to bottom, transparent calc(var(--a) - 1px), var(--c) calc(var(--a) - 1px),
                    var(--c) calc(var(--a) + 1px), transparent calc(var(--a) + 1px)),
    linear-gradient(to bottom, transparent calc(var(--b) - 1px), var(--c) calc(var(--b) - 1px),
                    var(--c) calc(var(--b) + 1px), transparent calc(var(--b) + 1px));
}
.rd-fig-grid.phi { --a: 38.197%; --b: 61.803%; }
.rd-fig-grid::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at var(--a) var(--a), var(--c) 0 4px, transparent 5px),
    radial-gradient(circle at var(--b) var(--a), var(--c) 0 4px, transparent 5px),
    radial-gradient(circle at var(--a) var(--b), var(--c) 0 4px, transparent 5px),
    radial-gradient(circle at var(--b) var(--b), var(--c) 0 4px, transparent 5px);
}

/* The display filters a comparison may apply. A fixed set, named, rather than
   arbitrary CSS in the unit data. */
.fx-sepia     { filter: sepia(1) contrast(1.04); }
.fx-vintage   { filter: sepia(.42) saturate(.72) contrast(.9) brightness(1.07); }
.fx-dramatic  { filter: grayscale(.25) contrast(1.55) brightness(.8); }
.fx-saturated { filter: saturate(2) contrast(1.06); }
.fx-swapped   { filter: url(#fx-swap-gb); }

@media (max-width: 560px) {
  .rd-fig.cols-2:not(.natural) .rd-fig-imgs { grid-template-columns: 1fr; }
  .rd-fig.cols-2:not(.natural) img { aspect-ratio: 3 / 2; }
  .rd-fig.cols-3 .rd-fig-imgs { gap: 5px; }
  .rd-fig-label { font-size: 10px; letter-spacing: .04em; }
}

.rd-def {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 20px 22px; border-radius: 15px;
  background: var(--paper); border: 1px solid var(--hair);
}
.rd-def b {
  display: block; font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.012em; margin-bottom: 5px;
}
.rd-def p { margin: 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
/* The same idea, said the way you would say it out loud. It sits under a rule
   inside the same card rather than in a card of its own, because it is not a
   second fact — it is the first one, in words a reader already owns. */
.rd-def .plain {
  margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--hair);
  font-size: 15.5px; color: var(--ink);
}
.rd-def .plain span {
  display: block; margin-bottom: 4px;
  font-family: var(--text); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}

/* Pulled out, and set at the size the sentence deserves. */
.rd-quote {
  max-width: var(--measure);
  margin: 2.1em 0; padding-left: 22px; border-left: 3px solid var(--ink);
}
.rd-quote p {
  margin: 0; font-family: var(--font);
  font-size: clamp(23px, 2.6vw, 29px); font-weight: 600;
  line-height: 1.22; letter-spacing: -.021em;
}
.rd-quote span {
  display: block; margin-top: 10px; font-size: 15.5px; line-height: 1.5;
  color: var(--ink-2); letter-spacing: -.01em;
}

/* A number worth stopping on. */
.rd-stat {
  max-width: var(--measure);
  margin: 2em 0; padding: 24px 0; border-block: 1px solid var(--hair);
  text-align: center;
}
.rd-stat b {
  display: block; font-family: var(--font);
  font-size: clamp(38px, 5.4vw, 54px); font-weight: 600;
  line-height: 1; letter-spacing: -.028em;
}
.rd-stat span {
  display: block; margin: 12px auto 0; max-width: 40ch;
  font-size: 15px; line-height: 1.5; color: var(--ink-2);
}

.rd-list { max-width: var(--measure); margin: 1.7em 0; }
.rd-list > b {
  display: block; font-family: var(--font); font-size: 13px; font-weight: 600;
  color: var(--ink-3); margin-bottom: 4px;
}
.rd-list li {
  display: grid; grid-template-columns: 190px 1fr; gap: 18px;
  padding: 14px 0; border-bottom: 1px solid var(--hair);
  font-size: 16px; line-height: 1.5;
}
.rd-list li:last-child { border-bottom: 0; }
.rd-list li b { font-family: var(--font); font-weight: 600; }
.rd-list li span { color: var(--ink-2); }
@media (max-width: 640px) { .rd-list li { grid-template-columns: 1fr; gap: 3px; } }

/* An aside the course text calls a side note. */
.rd-note {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 17px 20px; border-radius: 14px;
  background: var(--canvas); font-size: 16px; line-height: 1.55; color: var(--ink-2);
}
.rd-note::before {
  content: "Side note"; display: block;
  font-family: var(--font); font-size: 12px; font-weight: 600;
  color: var(--ink-3); margin-bottom: 5px;
}

/* Everyday words a section leans on, in plain language. Tinted, so a reader
   can find them again, and set as a two-column list a glance can scan. */
.rd-words {
  max-width: var(--measure);
  margin: 1.6em 0; padding: 15px 20px 7px; border-radius: 15px; background: #f2f7fd;
}
.rd-words > b {
  display: block; margin-bottom: 4px;
  font-family: var(--text); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--blue);
}
.rd-words dl { margin: 0; display: grid; grid-template-columns: max-content 1fr; column-gap: 18px; }
.rd-words dt, .rd-words dd { padding: 8px 0; border-top: 1px solid rgba(0,113,227,.12); line-height: 1.45; }
.rd-words dt { font-family: var(--font); font-size: 16px; font-weight: 600; }
.rd-words dd { margin: 0; font-size: 16px; color: var(--ink-2); }
.rd-words dt:first-of-type, .rd-words dd:first-of-type { border-top: 0; }
@media (max-width: 560px) {
  .rd-words dl { grid-template-columns: 1fr; }
  .rd-words dd { padding-top: 0; border-top: 0; }
}

/* A depth marker on a definition. Small, coloured, always secondary. */
.rd-depth {
  display: inline-block; margin-left: 8px;
  font-family: var(--text); font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 100px; vertical-align: middle;
}
.rd-depth[data-depth="CORE"] { background: rgba(0,113,227,.1); color: var(--blue); }
.rd-depth[data-depth="MORE"] { background: rgba(212,155,0,.12); color: #9a6d00; }
.rd-depth[data-depth="DEEP DIVE"] { background: rgba(191,40,40,.1); color: #b12828; }

/* Something to try, and somewhere the idea turns up in the world. */
.rd-call {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 17px 20px 16px; border-radius: 15px;
  background: var(--paper); border: 1px solid var(--hair);
}
.rd-call > span {
  display: flex; align-items: center; gap: 7px; margin-bottom: 6px;
  font-family: var(--text); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
}
.rd-call > span svg { width: 15px; height: 15px; }
.rd-call.try > span { color: var(--green); }
.rd-call.world > span { color: var(--amber); }
.rd-call > b {
  display: block; font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.012em;
}
.rd-body .rd-call p { margin: 4px 0 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }

/* A common misconception and the specific correction. */
.rd-mcon {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 17px 20px 16px; border-radius: 15px;
  background: rgba(191,40,40,.05); border: 1px solid rgba(191,40,40,.2);
}
.rd-mcon > span {
  display: flex; align-items: center; gap: 7px; margin-bottom: 6px;
  font-family: var(--text); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: #b12828;
}
.rd-mcon > span svg { width: 15px; height: 15px; }
.rd-mcon > b {
  display: block; font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.012em; margin-bottom: 4px;
}
.rd-mcon p { margin: 4px 0 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
.rd-mcon p.why { font-style: italic; color: var(--ink-3); }

/* A flashback — a concept from earlier the student is about to need. */
.rd-fbk {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 15px 20px; border-radius: 15px;
  background: rgba(0,113,227,.05); border: 1px solid rgba(0,113,227,.2);
}
.rd-fbk > span {
  display: flex; align-items: center; gap: 7px; margin-bottom: 6px;
  font-family: var(--text); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--blue);
}
.rd-fbk > span svg { width: 15px; height: 15px; }
.rd-fbk > b {
  display: block; font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.012em; margin-bottom: 4px;
}
.rd-fbk p { margin: 4px 0 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }

/* CER — Claim, Evidence, Reasoning. */
.rd-cer {
  max-width: var(--measure);
  margin: 1.7em 0; padding: 18px 22px; border-radius: 15px;
  background: var(--paper); border: 1px solid var(--hair);
}
.rd-cer > b {
  display: block; font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.012em; margin-bottom: 12px;
}
.rd-cer-part {
  padding: 10px 0;
  border-top: 1px solid var(--hair);
}
.rd-cer-part .k {
  display: inline-block; margin-bottom: 4px;
  font-family: var(--text); font-size: 10.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 100px;
  background: rgba(0,113,227,.1); color: var(--blue);
}
.rd-cer-part p { margin: 0; font-size: 15.5px; line-height: 1.55; color: var(--ink-2); }

/* ------------------------------------------------------------ Motion labs
   A figure with a clock: the stage, a strip of frames, the transport, and
   the switches. It reads as one object, so it sits in a single card. */
.rd-motion .rd-mo {
  overflow: hidden; border-radius: 16px;
  background: var(--paper); box-shadow: 0 0 0 1px var(--hair);
}
.rd-mo-stage { position: relative; background: #fbfbfd; border-bottom: 1px solid var(--hair); }
.rd-mo-stage svg { width: 100%; height: auto; }
.rd-mo-read {
  position: absolute; right: 10px; top: 9px; padding: 3px 9px; border-radius: 100px;
  background: rgba(255,255,255,.92); box-shadow: 0 0 0 1px var(--hair);
  font-family: var(--text); font-size: 12px; font-weight: 600; line-height: 1.5; letter-spacing: 0;
  font-variant-numeric: tabular-nums; color: var(--ink-2);
}
.rd-mo-strip { display: flex; gap: 2px; padding: 13px 16px 0; }
.rd-mo-strip i { flex: 1 1 0; min-width: 2px; height: 16px; border-radius: 2px; background: var(--hair); }
.rd-mo-strip i.d { background: #9cc0ea; }
.rd-mo-strip i.k { background: var(--blue); }
.rd-mo-strip i.on { box-shadow: 0 0 0 2px var(--ink); }
.rd-mo-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 16px 0;
  font-family: var(--text); font-size: 12px; line-height: 1.4; letter-spacing: 0; color: var(--ink-3);
}
.rd-mo-legend span { display: inline-flex; align-items: center; gap: 6px; }
.rd-mo-legend i { width: 10px; height: 10px; border-radius: 2px; background: var(--hair); }
.rd-mo-legend i.d { background: #9cc0ea; }
.rd-mo-legend i.k { background: var(--blue); }
.rd-mo-bar { display: flex; align-items: center; gap: 6px; padding: 12px 16px; }
.rd-mo-btn {
  display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%;
  background: var(--canvas); color: var(--ink);
}
.rd-mo-btn:hover { background: var(--sunk); }
.rd-mo-btn.main { width: 44px; height: 44px; background: var(--blue); color: #fff; }
.rd-mo-btn.main:hover { background: var(--blue-d); }
.rd-mo-btn svg { width: 17px; height: 17px; }
.rd-mo-onion {
  margin-left: auto; height: 34px; padding: 0 14px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2);
  font-size: 13.5px; font-weight: 500; letter-spacing: -.005em;
}
.rd-mo-onion:hover { background: var(--sunk); }
.rd-mo-onion[aria-pressed="true"] { background: var(--ink); color: #fff; }
.rd-mo-ctl {
  display: flex; flex-wrap: wrap; gap: 12px 22px;
  padding: 14px 16px 16px; border-top: 1px solid var(--hair);
}
.rd-mo-grp { display: flex; flex-direction: column; gap: 6px; }
.rd-mo-grp > span {
  font-family: var(--text); font-size: 11px; font-weight: 700; line-height: 1.3;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.rd-mo-seg { display: inline-flex; padding: 3px; border-radius: 100px; background: var(--canvas); }
.rd-mo-seg button {
  height: 30px; padding: 0 13px; border-radius: 100px; white-space: nowrap;
  font-size: 13.5px; font-weight: 500; letter-spacing: -.005em; color: var(--ink-2);
}
.rd-mo-seg button[aria-pressed="true"] {
  background: #fff; color: var(--ink);
  box-shadow: 0 1px 3px rgba(0,0,0,.14), 0 0 0 .5px rgba(0,0,0,.06);
}
@media (max-width: 560px) {
  .rd-mo-strip, .rd-mo-legend, .rd-mo-bar, .rd-mo-ctl { padding-left: 12px; padding-right: 12px; }
  .rd-mo-strip { gap: 1px; }
  .rd-mo-grp, .rd-mo-seg { width: 100%; }
  .rd-mo-seg button { flex: 1 1 0; padding: 0 6px; }
  .rd-mo-read { font-size: 11px; }
}

/* The check at the end of a section. */
.rd-check {
  max-width: var(--measure);
  margin: 3em 0 0; padding: 26px; border-radius: 18px;
  background: var(--paper); border: 1px solid var(--hair);
}
.rd-check .k {
  font-family: var(--font); font-size: 12px; font-weight: 600;
  color: var(--ink-3); margin-bottom: 9px;
}
.rd-check .q {
  font-family: var(--font); font-size: 19px; font-weight: 600;
  letter-spacing: -.014em; line-height: 1.3;
}
.rd-check .lx-opts { margin-top: 18px; }
.rd-check .lx-verdict { margin-top: 18px; }

.rd-next {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  max-width: var(--measure); margin: 3em 0 0; padding-top: 26px;
  border-top: 1px solid var(--hair);
}
.rd-next .t { font-size: 13px; color: var(--ink-3); }
.rd-next b {
  display: block; margin-top: 3px;
  font-family: var(--font); font-size: 19px; font-weight: 600; letter-spacing: -.014em;
}

/* Reading progress, as a hairline under the bar. */
.rd-rail {
  position: fixed; left: 0; right: 0; top: var(--bar); height: 2px;
  background: transparent; z-index: 39; pointer-events: none;
}
.rd-rail i { display: block; height: 100%; width: 0; background: var(--blue); }

/* ================================================================ Predict
   Three questions before a unit. Deliberately quieter than the quiz screens:
   this is not a test and must not look like one, or a student answers to
   protect a score instead of saying what they actually think. No timer, no
   points, one card at a time, and the way out is a visible button rather
   than a thing to be found.

   It is also the only screen in the app that gets the whole window. The
   composition sits in the middle of it rather than at the top of it, because
   a single question stranded above a screen of nothing reads as an
   afterthought — and this is the first thing a student meets in a unit. The
   room around it is the design.
   ------------------------------------------------------------------------ */
.pd {
  max-width: 720px;
  margin-inline: auto;
  /* The wrap's own padding is already inside this box, so the window's height
     less the bar and that padding is what there is to centre within. */
  min-height: calc(100svh - var(--bar) - (2 * clamp(26px, 4vw, 46px)));
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(22px, 3vh, 36px);
  text-align: center;
}

.pd-head .eyebrow { letter-spacing: .07em; }
.pd-head h1 {
  font-family: var(--font);
  font-size: clamp(28px, 3.6vw, 38px);
  font-weight: 600; letter-spacing: -.022em; line-height: 1.1;
  margin-top: 14px;
  text-wrap: balance;
}
.pd-say {
  margin-top: 16px; font-size: 16px; line-height: 1.62; color: var(--ink-2);
  max-width: 48ch; margin-inline: auto;
  text-wrap: pretty;
}

/* The counter is a whisper. A student should know where they are without
   being told they are being measured. */
.pd-step {
  display: flex; align-items: center; gap: 14px;
  max-width: 300px; margin-inline: auto;
  font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.pd-step .track { flex: 1; height: 2px; border-radius: 100px; background: var(--sunk); overflow: hidden; }
.pd-step .track i { display: block; height: 100%; background: var(--ink-3); transition: width .5s var(--ease); }

/* No border. On the page's grey ground a white field with this much air
     around the type is already an object; a hairline around it as well is the
     thing that makes a screen look cheap. */
.pd-card {
  background: var(--paper);
  border-radius: 22px;
  padding: clamp(30px, 4vw, 44px) clamp(24px, 4.5vw, 52px);
  box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 12px 34px -18px rgba(0,0,0,.14);
}
.pd-ask {
  font-size: clamp(19px, 2.3vw, 23px);
  line-height: 1.45; font-weight: 500; letter-spacing: -.014em;
  max-width: 34ch; margin-inline: auto;
  text-wrap: pretty;
}
.pd-opts { display: grid; gap: 9px; margin-top: clamp(22px, 3vw, 32px); }
.pd-opts button {
  padding: 17px 22px; border-radius: 14px;
  border: 1px solid var(--hair); background: var(--paper);
  font-size: 15.5px; line-height: 1.4; color: var(--ink);
  transition: border-color .16s var(--ease), background .16s var(--ease),
              transform .16s var(--ease);
}
.pd-opts button:hover:not(:disabled) {
  border-color: var(--ink-3); background: var(--canvas); transform: translateY(-1px);
}
.pd-opts button:disabled { opacity: .45; cursor: default; }

.pd-conf { margin-top: clamp(28px, 4vw, 40px); padding-top: clamp(24px, 3.5vw, 34px); border-top: 1px solid var(--hair); }
.pd-conf b { display: block; font-size: 15px; font-weight: 500; color: var(--ink-2); }
.pd-conf-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px; margin-top: 18px; }
.pd-conf-row button {
  padding: 11px 18px; border-radius: 100px; border: 1px solid var(--hair);
  background: var(--paper); font-size: 14px; color: var(--ink-2);
  transition: border-color .16s var(--ease), color .16s var(--ease);
}
.pd-conf-row button:hover { border-color: var(--ink); color: var(--ink); }

.pd-verdict { margin-top: clamp(28px, 4vw, 40px); padding-top: clamp(24px, 3.5vw, 34px); border-top: 1px solid var(--hair); }
.pd-verdict b { display: block; font-size: 18px; font-weight: 600; letter-spacing: -.012em; color: var(--amber); }
.pd-verdict.ok b { color: var(--green); }
.pd-verdict p {
  margin-top: 12px; font-size: 15.5px; line-height: 1.6; color: var(--ink-2);
  max-width: 42ch; margin-inline: auto;
  text-wrap: pretty;
}
.pd-watch em { font-style: normal; font-weight: 600; color: var(--ink); }
.pd-next {
  margin-top: clamp(24px, 3.5vw, 32px); height: 46px; padding: 0 26px; border-radius: 100px;
  background: var(--ink); color: var(--paper);
  font-size: 15px; font-weight: 500; letter-spacing: -.006em;
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.pd-next:hover { opacity: .88; transform: translateY(-1px); }

.pd-skip {
  padding: 10px; font-size: 13.5px; color: var(--ink-3);
  transition: color .16s var(--ease);
}
.pd-skip:hover { color: var(--ink-2); }

@media (max-width: 560px) {
  .pd { gap: 26px; min-height: 0; padding-top: 8px; }
  .pd-card { padding: 30px 22px; border-radius: 20px; }
  .pd-opts button { padding: 15px 18px; }
}

/* =============================================================== Retrieve
   The section boundary, with the article gone. It keeps the reader's three
   columns because the shape is the point: the rail still says where you are,
   and the margin is where the passage comes back — the same place it lived
   while you were reading it. What is missing is the text, and that absence is
   the whole mechanism.
   ------------------------------------------------------------------------ */
.rt { padding-top: 4px; }
.rt-head .eyebrow { letter-spacing: .07em; }
.rt-head h1 {
  margin-top: 10px;
  font-family: var(--font); font-size: clamp(27px, 3.2vw, 36px);
  font-weight: 600; letter-spacing: -.021em; line-height: 1.1;
  text-wrap: balance;
}
.rt-say {
  margin-top: 12px; font-size: 15.5px; line-height: 1.6; color: var(--ink-2);
  max-width: 52ch; text-wrap: pretty;
}
.rt-step {
  display: flex; align-items: center; gap: 14px;
  margin: 26px 0 18px; max-width: 300px;
  font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.rt-step .track { flex: 1; height: 2px; border-radius: 100px; background: var(--sunk); overflow: hidden; }
.rt-step .track i { display: block; height: 100%; background: var(--ink-3); transition: width .5s var(--ease); }

.rt-card {
  background: var(--paper); border-radius: 20px;
  padding: clamp(24px, 3vw, 34px);
  box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 12px 34px -20px rgba(0,0,0,.13);
}
/* The pass is named, with its own colour, because the prompt only makes sense
   as a follow-up to the act: "which claim does this support" is a strange
   question until you remember you called something evidence. */
.rt-kind {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--ink-3);
}
.rt-kind i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.rt-kind b { font-weight: 600; color: var(--ink-2); }
.rt-ask {
  margin-top: 14px;
  font-size: clamp(19px, 2.1vw, 23px); line-height: 1.4;
  font-weight: 500; letter-spacing: -.014em;
  max-width: 36ch; text-wrap: pretty;
}

.rt-form { margin-top: 22px; display: grid; gap: 12px; justify-items: start; }
.rt-form textarea {
  width: 100%; resize: vertical;
  padding: 14px 16px; border-radius: 14px;
  border: 1px solid var(--rule); background: var(--paper);
  font: inherit; font-size: 15.5px; line-height: 1.55; color: var(--ink);
  transition: border-color .16s var(--ease);
}
.rt-form textarea:focus { outline: none; border-color: var(--ink-3); }
.rt-form textarea:disabled { background: var(--canvas); color: var(--ink-2); }
.rt-send {
  height: 42px; padding: 0 22px; border-radius: 100px;
  background: var(--ink); color: var(--paper);
  font-size: 14.5px; font-weight: 500;
  transition: opacity .16s var(--ease);
}
.rt-send:hover:not(:disabled) { opacity: .88; }
.rt-send:disabled { opacity: .4; cursor: default; }

.rt-verdict {
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--hair);
}
.rt-verdict b { display: block; font-size: 16.5px; font-weight: 600; color: var(--amber); }
.rt-verdict.ok b { color: var(--green); }
.rt-verdict p {
  margin-top: 9px; font-size: 15px; line-height: 1.6; color: var(--ink-2);
  max-width: 46ch; text-wrap: pretty;
}
.rt-verdict em { font-style: normal; font-weight: 600; color: var(--ink); }
.rt-next {
  margin-top: 20px; height: 42px; padding: 0 22px; border-radius: 100px;
  background: var(--ink); color: var(--paper);
  font-size: 14.5px; font-weight: 500;
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.rt-next:hover { opacity: .88; transform: translateY(-1px); }

/* The margin keeps its shape and starts empty on purpose: an empty panel that
   says what will fill it is a promise, and the promise is what makes a student
   answer before looking. */
.rt-margin .mg-head span { color: var(--ink-3); }
/* In the reader a margin note is positioned beside the line it belongs to,
   so `.mg` is absolute. Here there are no lines to sit beside, and an
   absolute note lies on top of whatever follows it — the unit's definition,
   after a miss. In flow, and not a control: nothing here opens on click. */
.rt-margin .mg { position: static; cursor: default; }
.rt-margin .mg:hover { transform: none; box-shadow: none; }
.rt-shown {
  border-left: 2px solid var(--rule);
  padding-left: 13px;
}
.rt-shown p { font-size: 14.5px; line-height: 1.55; color: var(--ink); }
.rt-shown span {
  display: block; margin-top: 9px; font-size: 13px; line-height: 1.5;
  color: var(--ink-2);
}

/* What the student wrote, once it is committed. Shown as a quotation rather
   than a disabled box, because it is no longer something to edit. */
.rt-said {
  margin-top: 22px; padding: 14px 16px; border-radius: 14px;
  background: var(--canvas);
  font-size: 15px; line-height: 1.55; color: var(--ink-2);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.rt-said span, .rt-belief span, .rt-instead span, .rt-says span {
  display: block; margin-bottom: 5px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3);
}

.rt-conf { margin-top: 22px; }
.rt-conf b { display: block; font-size: 14.5px; font-weight: 500; color: var(--ink-2); }
.rt-conf-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.rt-conf-row button {
  padding: 10px 16px; border-radius: 100px;
  border: 1px solid var(--hair); background: var(--paper);
  font-size: 13.5px; color: var(--ink-2);
  transition: border-color .16s var(--ease), color .16s var(--ease);
}
.rt-conf-row button:hover { border-color: var(--ink); color: var(--ink); }

/* -------------------------------------------------------------- Repair
   A miss names the mistake the concept already carries and what to think
   instead, then asks for the idea to be used. The belief is struck through
   rather than shown in red: it is being set aside, not scolded. */
.rt-repair { margin-top: 18px; display: grid; gap: 14px; }
.rt-flag {
  padding: 14px 16px; border-radius: 14px;
  background: rgba(215, 0, 21, .055);
  font-size: 14.5px; line-height: 1.55; color: var(--ink);
}
.rt-flag b { color: var(--red); font-weight: 600; }
.rt-belief p, .rt-instead p { font-size: 15px; line-height: 1.55; max-width: 52ch; }
.rt-belief p {
  color: var(--ink-2);
  text-decoration: line-through; text-decoration-color: rgba(0, 0, 0, .28);
}
.rt-instead p { color: var(--ink); }

.rt-again { margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--hair); }
.rt-q {
  margin-top: 10px; font-size: 17px; line-height: 1.45;
  font-weight: 500; letter-spacing: -.01em; max-width: 44ch;
}
.rt-again .lx-opts { margin-top: 16px; }

.rt-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 20px; margin-top: 22px; }
.rt-actions .rt-next { margin-top: 0; }
.rt-look {
  padding: 8px 2px; font-size: 14px; color: var(--blue);
  transition: color .16s var(--ease);
}
.rt-look:hover { text-decoration: underline; }

/* In the margin after a miss: the unit's own definition, beside the
   student's mark, so the correction has something to be checked against. */
.rt-says { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hair); }
.rt-says b { display: block; font-size: 14px; font-weight: 600; }
.rt-says p { margin-top: 5px; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }

/* Back in the article from a retrieval card. The banner is the way back to
   the questions, and the passage the card was about is lit when it arrives. */
.rd-review {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px 18px;
  margin-bottom: 30px; padding: 14px 16px 14px 18px;
  border-radius: 16px; background: var(--paper); border: 1px solid var(--hair);
}
.rd-review p { font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.rd-review b { color: var(--ink); font-weight: 600; }
mark.rt-flash {
  box-shadow: 0 0 0 3px rgba(0, 113, 227, .30);
  border-radius: 3px;
  animation: rt-flash 1.4s var(--ease) 2;
}
@keyframes rt-flash { 50% { box-shadow: 0 0 0 7px rgba(0, 113, 227, .10); } }
@media (prefers-reduced-motion: reduce) { mark.rt-flash { animation: none; } }

/* The door out of a section, at the foot of the article. */
.rd-next .why {
  margin-top: 6px; font-size: 13px; line-height: 1.5; color: var(--ink-3);
  max-width: 44ch;
}

@media (max-width: 900px) {
  .rt-margin { margin-top: 22px; }
}

/* ================================================== Reader, three columns
   Navigation left, text centre, margin right. It is the shape of a book with
   a wide outer margin and a reader who writes in it, and the reason it works
   on a screen is the same reason it worked on paper: a note beside the line
   it is about needs no explanation of what it is about.

   The bottom right corner stays empty. That is the tutor's, and a panel that
   opens over your own notes is a panel you close. */
.rd-three {
  display: grid;
  /* The flanks are the same width on purpose. Unequal ones put the text
     off-centre by half their difference, which is small enough to look like
     a mistake rather than a choice — and this is the column the reader is
     actually looking at. */
  grid-template-columns: 272px minmax(0, 720px) 272px;
  gap: clamp(22px, 3.4vw, 64px);
  justify-content: space-between; align-items: start;
}
/* The article is held to its measure and the whole of it is centred in the
   column — not each child separately. Centring the children independently is
   what gives a reading column two left edges: the heading starts at one x and
   the paragraph under it at another, and the eye reads that as a wobble. */
.rd-three .rd { max-width: var(--measure); margin-inline: auto; }

@media (max-width: 1220px) {
  .rd-three { grid-template-columns: 234px minmax(0, 1fr); }
  /* The margin stops being a margin and becomes a section, which is the
     honest thing for it to do when there is no room beside the text. */
  .rd-margin { grid-column: 1 / -1; }
  .rd-margin .mg-wrap { height: auto !important; display: grid; gap: 10px; }
  .rd-margin .mg { position: static !important; }
}
@media (max-width: 1040px) {
  .cn-row { grid-template-columns: minmax(0, 1fr) 120px 150px; }
}
@media (max-width: 900px) {
  .rd-three { grid-template-columns: 1fr; }
  .rd-rail-nav { position: static; }
}

.rd-rail-nav { position: sticky; top: calc(var(--bar) + 20px); display: grid; gap: 12px; }
/* The phone override for this lives in the breakpoints above, and at equal
   specificity the later rule wins — so on a phone the unit panel stayed
   sticky and slid over the text being read. Restated after the rule it
   overrides, where it can actually take effect. */
@media (max-width: 900px) { .rd-rail-nav { position: static; } }
.rd-panel {
  padding: 19px 16px; border-radius: 18px;
  background: var(--paper); border: 1px solid var(--hair);
}
.rd-panel h3 {
  font-family: var(--font); font-size: 13.5px; font-weight: 600;
  padding: 0 8px 10px; margin-bottom: 5px; border-bottom: 1px solid var(--hair);
}
.rd-panel h3 span {
  display: block; margin-top: 2px; font-size: 11.5px; font-weight: 400; color: var(--ink-3);
}
.rd-toc { display: grid; gap: 3px; }
.rd-toc button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 9px; border-radius: 10px; text-align: left;
  font-size: 13.5px; color: var(--ink-2); line-height: 1.32;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.rd-toc button:hover { background: var(--canvas); color: var(--ink); }
.rd-toc button[aria-current="true"] { background: var(--sunk); color: var(--ink); font-weight: 500; }
.rd-toc .n { flex: none; font-variant-numeric: tabular-nums; color: var(--ink-3); font-size: 12px; }
.rd-toc button[aria-current="true"] .n { color: var(--blue); }
.rd-toc .t { flex: 1; min-width: 0; }
.rd-toc .tick { margin-left: auto; color: var(--green); flex: none; }
.rd-toc .tick svg { width: 13px; height: 13px; }
.rd-toc .badge {
  margin-left: auto; min-width: 17px; height: 17px; padding: 0 5px; border-radius: 100px;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  background: var(--sunk); color: var(--ink-2);
  font-size: 10.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.rd-toc .badge + .tick { margin-left: 5px; }

/* Marks in a section, by pass. A dot per pass that has anything in it, with
   the count inside once there is more than one — so a row reads as the shape
   of a reading rather than as a total. */
.rd-toc .dots { margin-left: auto; display: flex; align-items: center; gap: 3px; flex: none; }
.rd-toc .dots:empty { display: none; }
.rd-toc .dots i {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 8px; height: 14px; padding: 0 3px; border-radius: 100px;
  font-style: normal; font-size: 9.5px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: rgba(0,0,0,.62);
}
.rd-toc .dots + .tick { margin-left: 5px; }
.rd-unitprog { padding: 12px 9px 2px; }
.rd-unitprog .track { height: 3px; border-radius: 100px; background: var(--sunk); overflow: hidden; }
.rd-unitprog .track i { display: block; height: 100%; background: var(--blue); transition: width .6s var(--ease); }
.rd-unitprog span { display: block; margin-top: 8px; font-size: 11.5px; color: var(--ink-3); }

/* The six passes, as a legend and as a filter on the margin. */
.rd-passes button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; border-radius: 10px; font-size: 13px; color: var(--ink-2);
  transition: background .14s var(--ease), color .14s var(--ease);
}
.rd-passes button:hover { background: var(--canvas); color: var(--ink); }
.rd-passes button[aria-pressed="true"] { background: var(--sunk); color: var(--ink); font-weight: 500; }
.rd-passes button i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.rd-passes button span { flex: 1; text-align: left; }
.rd-passes button em {
  font-style: normal; font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.rd-passes button[aria-pressed="true"] em { color: var(--ink-2); }

.rd-side-link {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 12px 14px; border-radius: 14px; background: var(--paper);
  border: 1px solid var(--hair); font-size: 13.5px; font-weight: 500;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.rd-side-link:hover { border-color: var(--rule); }
.rd-side-link svg { width: 16px; height: 16px; color: var(--ink-2); flex: none; }
.rd-side-link span:not(.c) { flex: 1; text-align: left; }
.rd-side-link .c {
  font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums;
  min-width: 16px; text-align: right;
}

/* ============================================================ Annotation
   Six passes, six colours, and one rule: a mark is a hue with a wash behind
   the text and a solid line under it. The wash says where; the line says
   which. That keeps two overlapping marks legible, which matters, because
   the sentence that is both a claim and the thing you doubt is the sentence
   worth finding again. */
.rd-body ::selection { background: rgba(0,113,227,.16); }

mark.hl {
  --hue: #f2c200;
  --wash: rgba(255,214,10,.34);
  background: var(--wash); color: inherit;
  border-radius: 2px; padding: .05em 0 .12em;
  box-shadow: inset 0 -2px 0 -1px var(--hue);
  cursor: pointer;
  transition: background .15s var(--ease), box-shadow .15s var(--ease);
}
mark.hl.p1 { --hue: #f2c200; --wash: rgba(255,214,10,.34); }
mark.hl.p2 { --hue: #8f5cff; --wash: rgba(143,92,255,.20); }
mark.hl.p3 { --hue: #34c759; --wash: rgba(52,199,89,.22); }
mark.hl.p4 { --hue: #4da3ff; --wash: rgba(77,163,255,.22); }
mark.hl.p5 { --hue: #ff453a; --wash: rgba(255,69,58,.18); }
mark.hl.p6 { --hue: #ff9f0a; --wash: rgba(255,159,10,.22); }
mark.hl:hover { box-shadow: inset 0 -2px 0 0 var(--hue); }
/* A mark that was written on, rather than only dragged over. */
mark.hl.noted { box-shadow: inset 0 -3px 0 -1px var(--hue), inset 0 0 0 1px rgba(0,0,0,.05); }
mark.hl.focus { background: color-mix(in srgb, var(--hue) 34%, transparent); }
/* Someone else's, arriving from a room: their colour, but a dotted underline,
   so at a glance you can tell your reading from theirs. */
mark.hl.theirs { background: transparent; box-shadow: none; border-bottom: 2px dotted var(--hue); }
mark.hl.theirs:hover { background: var(--wash); }

/* A peer pointing at a line. It leaves nothing behind. */
.rd-point {
  border-radius: 4px; padding: .05em .15em; margin: 0 -.15em;
  background: rgba(0,113,227,.2);
  animation: rd-point 2.6s var(--ease);
}
@keyframes rd-point {
  0%, 70% { background: rgba(0,113,227,.26); box-shadow: 0 0 0 3px rgba(0,113,227,.14); }
  100%    { background: rgba(0,113,227,0); box-shadow: 0 0 0 3px rgba(0,113,227,0); }
}

/* -------------------------------------------------------- The toolbar */
.rd-tools {
  position: absolute; z-index: 70; display: none;
  align-items: center; gap: 2px; padding: 4px;
  border-radius: 100px; background: rgba(29,29,31,.94);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  box-shadow: 0 10px 30px rgba(0,0,0,.26), 0 1px 2px rgba(0,0,0,.2);
  transform: translate(-50%, -100%);
  animation: rd-tools-in .16s var(--ease);
}
.rd-tools.below { transform: translate(-50%, 0); }
.rd-tools.on { display: flex; }
@keyframes rd-tools-in { from { opacity: 0; transform: translate(-50%, calc(-100% + 5px)); } }
.rd-tools button {
  height: 29px; padding: 0 10px 0 8px; border-radius: 100px;
  display: inline-flex; align-items: center; gap: 6px;
  color: rgba(255,255,255,.86); font-size: 12.5px; font-weight: 500; letter-spacing: -.006em;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.rd-tools button:hover { background: rgba(255,255,255,.14); color: #fff; }
.rd-tools .sw { width: 10px; height: 10px; border-radius: 3px; display: block; flex: none; }
.rd-tools .sep { width: 1px; height: 17px; background: rgba(255,255,255,.18); margin: 0 3px; flex: none; }
.rd-tools .act { width: 29px; padding: 0; justify-content: center; }
.rd-tools .act svg { width: 15px; height: 15px; }

/* -------------------------------------------------------- The editor */
.rd-pop {
  position: absolute; z-index: 71; display: none;
  width: 348px; padding: 14px; border-radius: 18px;
  background: rgba(252,252,253,.92);
  -webkit-backdrop-filter: saturate(180%) blur(26px);
  backdrop-filter: saturate(180%) blur(26px);
  border: 1px solid rgba(0,0,0,.08);
  box-shadow: 0 20px 54px rgba(0,0,0,.18), 0 2px 6px rgba(0,0,0,.06);
  transform: translate(-50%, 0);
  animation: rd-pop-in .2s var(--ease);
}
.rd-pop.on { display: block; }
@keyframes rd-pop-in { from { opacity: 0; transform: translate(-50%, -6px) scale(.97); } }
.rd-pop-head { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; }
.rd-pop-head .cite {
  flex: 1; min-width: 0; font-family: var(--font); font-size: 11.5px; font-weight: 600;
  color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rd-pop-x {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: var(--ink-3);
  transition: background .13s var(--ease), color .13s var(--ease);
}
.rd-pop-x svg { width: 13px; height: 13px; }
.rd-pop-x:hover { background: rgba(0,0,0,.06); color: var(--ink); }
.rd-pop .said {
  margin: 0 0 12px; padding-left: 11px; border-left: 2px solid var(--rule);
  font-size: 13.5px; line-height: 1.5; color: var(--ink-2);
  max-height: 4.4em; overflow: hidden;
}
.rd-pop .kinds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-bottom: 10px; }
.rd-pop .kinds button {
  height: 30px; border-radius: 9px; border: 1px solid var(--hair);
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 11.5px; font-weight: 500; color: var(--ink-2);
  transition: border-color .14s var(--ease), background .14s var(--ease), color .14s var(--ease);
}
.rd-pop .kinds button .sw { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.rd-pop .kinds button:hover { border-color: var(--rule); color: var(--ink); }
.rd-pop .kinds button[aria-pressed="true"] {
  border-color: var(--ink); background: var(--ink); color: #fff;
}
.rd-pop-ask { font-size: 12px; color: var(--ink-3); margin-bottom: 7px; }
.rd-pop textarea {
  width: 100%; min-height: 76px; resize: vertical; padding: 10px 12px;
  border-radius: 11px; border: 1px solid var(--hair); background: var(--paper);
  color: var(--ink); font: inherit; font-size: 14px; line-height: 1.45; outline: none;
  transition: border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.rd-pop textarea:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,113,227,.12); }
.rd-pop .tags {
  width: 100%; height: 34px; margin-top: 7px; padding: 0 12px; border-radius: 10px;
  border: 1px solid var(--hair); background: var(--paper); color: var(--ink);
  font-size: 13.5px; outline: none;
}
.rd-pop .tags:focus { border-color: var(--blue); }

.rd-pop-link { margin-top: 8px; }
.rd-pop-link select {
  width: 100%; height: 34px; padding: 0 10px; border-radius: 10px;
  border: 1px solid var(--hair); background: var(--paper); color: var(--ink-2);
  font: inherit; font-size: 13px; outline: none; -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2386868b' stroke-width='1.5' stroke-linecap='round' d='M3 4.75 6 7.75l3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 12px;
  padding-right: 28px;
}
.rd-pop-linked { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.rd-pop-linked .lk {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 4px 3px 8px; border-radius: 100px; background: var(--canvas);
  font-size: 11.5px; color: var(--ink-2); max-width: 100%;
}
.rd-pop-linked .lk i { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.rd-pop-linked .lk button {
  width: 16px; height: 16px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: var(--ink-3); font-size: 13px; line-height: 1;
}
.rd-pop-linked .lk button:hover { background: rgba(0,0,0,.08); color: var(--ink); }

.rd-pop .row { display: flex; gap: 7px; margin-top: 11px; }
.rd-pop .row button {
  height: 34px; border-radius: 100px; font-size: 13.5px; font-weight: 500;
  display: grid; place-items: center;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.rd-pop .row .save { flex: 1; background: var(--blue); color: #fff; }
.rd-pop .row .save:hover { background: var(--blue-d); }
.rd-pop .row .quote, .rd-pop .row .del { width: 34px; background: var(--canvas); color: var(--ink-2); }
.rd-pop .row .quote svg, .rd-pop .row .del svg { width: 15px; height: 15px; }
.rd-pop .row .quote:hover { background: var(--sunk); color: var(--ink); }
.rd-pop .row .del:hover { background: rgba(215,0,21,.1); color: var(--red); }

/* ============================================================== The margin
   Cards beside the lines they belong to. Positioned at their highlight and
   then pushed clear of the one above, which is what keeps the column
   readable when three marks land in the same paragraph. */
.rd-margin { position: relative; }
.mg-head {
  position: sticky; top: calc(var(--bar) + 16px); z-index: 2;
  display: flex; align-items: baseline; gap: 8px; padding-bottom: 12px;
  margin-bottom: 4px;
}
.mg-head-in { flex: 1; min-width: 0; }
.mg-head b {
  display: block; font-family: var(--font); font-size: 13.5px; font-weight: 600;
  letter-spacing: -.008em;
}
.mg-head span { display: block; margin-top: 1px; font-size: 11.5px; color: var(--ink-3); }
.mg-open {
  flex: none; height: 25px; padding: 0 11px; border-radius: 100px;
  background: var(--paper); border: 1px solid var(--hair);
  font-size: 12px; font-weight: 500; color: var(--ink-2);
  transition: border-color .14s var(--ease), color .14s var(--ease);
}
.mg-open:hover { border-color: var(--rule); color: var(--ink); }

.mg-wrap { position: relative; }

.mg-empty { padding: 2px 2px 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-3); }
.mg-empty p + p { margin-top: 9px; }
.mg-empty .k { font-size: 11.5px; color: var(--rule); }

.mg {
  position: absolute; left: 0; right: 0;
  --hue: #f2c200;
  padding: 11px 12px 11px 13px; border-radius: 13px;
  background: var(--paper); border: 1px solid var(--hair);
  border-left: 3px solid var(--hue);
  cursor: pointer;
  transition: top .28s var(--ease), border-color .15s var(--ease),
              box-shadow .18s var(--ease), transform .18s var(--ease);
}
.mg:hover, .mg.focus {
  border-color: var(--rule); border-left-color: var(--hue);
  box-shadow: 0 4px 16px rgba(0,0,0,.07);
  transform: translateX(-3px);
}
@media (prefers-reduced-motion: reduce) { .mg { transition: none; } }
.mg-top { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.mg-top .k {
  flex: 1; font-family: var(--font); font-size: 10.5px; font-weight: 600;
  letter-spacing: .01em; text-transform: uppercase; color: var(--ink-3);
}
.mg-who {
  width: 18px; height: 18px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: #fff;
  font-family: var(--font); font-size: 9px; font-weight: 600; letter-spacing: 0;
}
.mg q {
  display: block; font-size: 12.5px; line-height: 1.48; color: var(--ink-2);
  quotes: "“" "”";
}
.mg-note {
  margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--hair);
  font-size: 13px; line-height: 1.45; color: var(--ink);
}
.mg-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.mg-tags em {
  font-style: normal; font-size: 10.5px; padding: 2px 7px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2);
}
.mg-link { display: flex; align-items: center; gap: 5px; margin-top: 7px; font-size: 11px; color: var(--ink-3); }
.mg-link svg { width: 12px; height: 12px; }
.mg.theirs { background: var(--canvas); border-style: dashed; border-left-style: solid; }
.mg-keep {
  margin-top: 8px; height: 25px; padding: 0 11px; border-radius: 100px;
  background: var(--paper); border: 1px solid var(--hair);
  font-size: 11.5px; font-weight: 500; color: var(--ink-2);
}
.mg-keep:hover { border-color: var(--ink); color: var(--ink); }
/* A note whose passage has moved or changed. Kept, and said so. */
.mg.orphan { opacity: .62; border-left-style: dotted; }

/* ================================================================ Notebook */
.nb-prof {
  display: flex; flex-wrap: wrap; align-items: center; gap: clamp(18px, 3vw, 38px);
  margin-top: 28px; padding: 20px 22px; border-radius: 18px;
  background: var(--paper); border: 1px solid var(--hair);
}
.nb-depth { display: flex; align-items: center; gap: 13px; flex: none; }
.nb-depth .ring {
  width: 54px; height: 54px; border-radius: 50%; display: grid; place-items: center;
  background: conic-gradient(var(--blue) calc(var(--v) * 1%), var(--sunk) 0);
  position: relative;
}
.nb-depth .ring::after {
  content: ""; position: absolute; inset: 5px; border-radius: 50%; background: var(--paper);
}
.nb-depth .ring b {
  position: relative; z-index: 1; font-family: var(--font);
  font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.nb-depth > span { font-family: var(--font); font-size: 13.5px; font-weight: 600; }
.nb-depth > span em { display: block; font-style: normal; font-size: 11.5px; font-weight: 400; color: var(--ink-3); margin-top: 2px; }
.nb-counts { display: flex; flex-wrap: wrap; gap: clamp(12px, 2vw, 26px); }
.nb-count { display: grid; grid-template-columns: auto auto; align-items: center; gap: 0 7px; }
.nb-count i { width: 8px; height: 8px; border-radius: 3px; grid-row: span 2; }
.nb-count b { font-family: var(--font); font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; }
.nb-count span { font-size: 11.5px; color: var(--ink-3); }
.nb-count.nil { opacity: .38; }
.nb-count.wide { padding-left: clamp(12px, 2vw, 22px); border-left: 1px solid var(--hair); }

.nb-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 11px;
  margin-top: 22px; padding-bottom: 18px; border-bottom: 1px solid var(--hair);
}
.nb-search {
  flex: 1 1 220px; height: 36px; padding: 0 14px; border-radius: 100px;
  border: 1px solid var(--hair); background: var(--paper); color: var(--ink);
  font-size: 14px; outline: none; -webkit-appearance: none; appearance: none;
}
.nb-search:focus { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(0,113,227,.12); }
.nb-modes {
  display: flex; gap: 2px; padding: 2px; border-radius: 100px; background: var(--sunk);
}
.nb-seg {
  height: 28px; padding: 0 13px; border-radius: 100px;
  font-size: 12.5px; font-weight: 500; color: var(--ink-2);
  transition: background .16s var(--ease), color .16s var(--ease), box-shadow .16s var(--ease);
}
.nb-seg[aria-pressed="true"] {
  background: var(--paper); color: var(--ink);
  box-shadow: 0 1px 3px rgba(0,0,0,.1);
}
.nb-acts { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.nb-style {
  height: 30px; padding: 0 26px 0 11px; border-radius: 100px;
  border: 1px solid var(--hair); background: var(--paper); color: var(--ink-2);
  font: inherit; font-size: 12.5px; outline: none; -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2386868b' stroke-width='1.5' stroke-linecap='round' d='M3 4.75 6 7.75l3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 11px;
}

.nb-out { margin-top: 24px; }
.nb-group { margin-bottom: 30px; }
.nb-group-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; }
.nb-group-head h2 { font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.012em; }
.nb-group-head span {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 100px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--canvas); color: var(--ink-3); font-size: 11.5px; font-weight: 600;
}
.nb-group-head .nb-sub { font-style: normal; font-size: 12.5px; color: var(--ink-3); }
.nb-group-head .lx-btn { margin-left: auto; }

.nb-row {
  --hue: #f2c200;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 14px; margin-bottom: 7px; border-radius: 13px;
  background: var(--paper); border: 1px solid var(--hair);
  border-left: 3px solid var(--hue);
  transition: border-color .14s var(--ease);
}
.nb-row:hover { border-color: var(--rule); border-left-color: var(--hue); }
.nb-row-main { flex: 1; min-width: 0; }
.nb-row .kind {
  display: block; font-family: var(--font); font-size: 10.5px; font-weight: 600;
  letter-spacing: .01em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 4px;
}
.nb-row q { display: block; font-size: 14.5px; line-height: 1.5; color: var(--ink); }
.nb-row .note {
  margin-top: 7px; padding-left: 11px; border-left: 2px solid var(--hair);
  font-size: 14px; line-height: 1.5; color: var(--ink-2);
}
.nb-row .tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.nb-row .tags em {
  font-style: normal; font-size: 11.5px; padding: 2px 8px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2);
}
.nb-row-tools { display: flex; gap: 2px; flex: none; opacity: 0; transition: opacity .14s var(--ease); }
.nb-row:hover .nb-row-tools, .nb-row:focus-within .nb-row-tools { opacity: 1; }
.nb-row-tools button {
  width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center;
  color: var(--ink-3); transition: background .13s var(--ease), color .13s var(--ease);
}
.nb-row-tools button svg { width: 15px; height: 15px; }
.nb-row-tools button:hover { background: var(--canvas); color: var(--ink); }
.nb-row-tools button:last-child:hover { background: rgba(215,0,21,.09); color: var(--red); }

/* The argument view: a claim, and what a reader hung on it. */
.nb-thread {
  margin-bottom: 26px; padding: 4px 4px 4px 0; border-radius: 18px;
}
.nb-claim {
  --hue: #8f5cff;
  padding: 16px 18px; border-radius: 15px; margin-bottom: 10px;
  background: var(--paper); border: 1px solid var(--hair); border-left: 3px solid var(--hue);
}
.nb-claim .kind {
  display: block; font-family: var(--font); font-size: 10.5px; font-weight: 600;
  letter-spacing: .01em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 5px;
}
.nb-claim q { display: block; font-family: var(--font); font-size: 18px; line-height: 1.4; letter-spacing: -.012em; }
.nb-claim p { margin-top: 8px; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.nb-limb { margin: 0 0 4px 20px; padding-left: 18px; border-left: 1px solid var(--hair); }
.nb-limb h4 {
  font-family: var(--font); font-size: 11.5px; font-weight: 600; letter-spacing: .01em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 7px;
}
.nb-bare {
  margin: 0 0 4px 20px; padding: 11px 14px; border-radius: 11px;
  background: var(--canvas); font-size: 13.5px; color: var(--ink-3);
}

/* ============================================================== The video
   The placeholder is the resting state and the player is the upgrade, so a
   file that is not there costs a reader a designed frame rather than a broken
   control at the top of the article. */
.rd-video { margin: 26px 0 0; }
.rd-video.live {
  border-radius: 16px; overflow: hidden; background: #000; border: 1px solid var(--hair);
}
.rd-video video { display: block; width: 100%; height: auto; }
.rd-cap { margin-top: 9px; font-size: 13px; color: var(--ink-3); }

.rd-vph {
  display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: 18px; align-items: center;
  padding: 16px; border-radius: 16px;
  background: var(--paper); border: 1px solid var(--hair);
}
@media (max-width: 620px) { .rd-vph { grid-template-columns: 1fr; } }
.rd-vph-art {
  position: relative; aspect-ratio: 16 / 10; border-radius: 11px; overflow: hidden;
  background: linear-gradient(150deg, #1d1d1f, #3a3a3e 55%, #1d1d1f);
  display: grid; place-items: center;
}
/* A waveform, because this is a unit about sound and an empty grey box says
   nothing about what is missing. */
.rd-vph-art .wave {
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.16) 0 2px, transparent 2px 7px);
  -webkit-mask-image: radial-gradient(ellipse 78% 46% at 50% 50%, #000 20%, transparent 74%);
  mask-image: radial-gradient(ellipse 78% 46% at 50% 50%, #000 20%, transparent 74%);
  opacity: .8;
}
.rd-vph-art .glyph {
  position: relative; width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.14); color: rgba(255,255,255,.72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.rd-vph-art .glyph svg { width: 17px; height: 17px; margin-left: 2px; }
.rd-vph-say .k {
  display: block; font-family: var(--font); font-size: 11px; font-weight: 600;
  letter-spacing: .01em; text-transform: uppercase; color: var(--ink-3);
}
.rd-vph-say b {
  display: block; margin-top: 4px; font-family: var(--font); font-size: 17px;
  font-weight: 600; letter-spacing: -.014em;
}
.rd-vph-say p { margin-top: 7px; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.rd-vph-say code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
  background: var(--canvas); padding: 1px 6px; border-radius: 5px;
}

/* ========================================================== Read together
   Presence in the bar, a follow strip under it, and one panel that does the
   inviting. Nothing here takes room away from the text. */
.lx-presence { display: flex; align-items: center; flex: none; }
.pr-open {
  display: flex; align-items: center; gap: 7px; height: 30px; padding: 0 10px;
  border-radius: 100px; color: var(--ink-2);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.pr-open svg { width: 17px; height: 17px; }
.pr-open:hover { background: rgba(0,0,0,.05); color: var(--ink); }
.pr-open.on { color: var(--ink); }
.pr-stack { display: flex; }
.pr-stack .pr-av + .pr-av { margin-left: -6px; }
.pr-av {
  width: 21px; height: 21px; border-radius: 50%; display: grid; place-items: center;
  color: #fff; font-family: var(--font); font-size: 9.5px; font-weight: 600;
  border: 1.5px solid var(--paper);
}
.pr-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--green);
  box-shadow: 0 0 0 3px rgba(18,145,90,.16);
}

.fb {
  position: sticky; top: var(--bar); z-index: 38;
  display: flex; align-items: center; gap: 10px;
  padding: 8px max(var(--gut), env(safe-area-inset-left));
  background: rgba(0,113,227,.09);
  -webkit-backdrop-filter: saturate(180%) blur(18px); backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid rgba(0,113,227,.16);
}
.fb-av {
  width: 22px; height: 22px; border-radius: 50%; flex: none; display: grid; place-items: center;
  color: #fff; font-family: var(--font); font-size: 9.5px; font-weight: 600;
}
.fb-say { flex: 1; min-width: 0; font-size: 13px; color: var(--ink-2); }
.fb-say b { color: var(--ink); font-weight: 600; }
.fb-stop {
  flex: none; height: 26px; padding: 0 13px; border-radius: 100px;
  background: var(--paper); border: 1px solid rgba(0,113,227,.24);
  font-size: 12.5px; font-weight: 500; color: var(--blue);
}
.fb-stop:hover { background: var(--blue); border-color: var(--blue); color: #fff; }

.rm {
  position: fixed; right: 22px; top: calc(var(--bar) + 12px); z-index: 60;
  width: min(340px, calc(100vw - 30px));
  max-height: calc(100vh - var(--bar) - 34px); overflow-y: auto; overscroll-behavior: contain;
  padding: 14px; border-radius: 20px;
  background: rgba(252,252,253,.9);
  -webkit-backdrop-filter: saturate(180%) blur(28px); backdrop-filter: saturate(180%) blur(28px);
  border: 1px solid rgba(0,0,0,.08);
  box-shadow: 0 22px 62px rgba(0,0,0,.2), 0 2px 6px rgba(0,0,0,.05);
  animation: rm-in .24s var(--ease);
}
@keyframes rm-in { from { opacity: 0; transform: translateY(-8px) scale(.98); } }
@media (prefers-reduced-motion: reduce) { .rm { animation: none; } }
.rm-head { display: flex; align-items: center; margin-bottom: 10px; }
.rm-head b { flex: 1; font-family: var(--font); font-size: 15px; font-weight: 600; letter-spacing: -.012em; }
.rm-x {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; color: var(--ink-3);
}
.rm-x svg { width: 14px; height: 14px; }
.rm-x:hover { background: rgba(0,0,0,.06); color: var(--ink); }
.rm-say { font-size: 13px; line-height: 1.55; color: var(--ink-2); margin-bottom: 12px; }
.rm-go {
  width: 100%; height: 38px; border-radius: 100px; background: var(--ink); color: #fff;
  font-size: 14px; font-weight: 500;
}
.rm-go:hover { background: #000; }
.rm-here { display: grid; gap: 2px; margin-bottom: 11px; }
.rm-person {
  display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 11px;
}
.rm-person.me { background: var(--canvas); }
.rm-av {
  width: 28px; height: 28px; border-radius: 50%; flex: none; display: grid; place-items: center;
  color: #fff; font-family: var(--font); font-size: 11px; font-weight: 600;
}
.rm-nm { flex: 1; min-width: 0; }
.rm-nm b { display: block; font-size: 13.5px; font-weight: 500; letter-spacing: -.008em; }
.rm-nm span {
  display: block; font-size: 11.5px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rm-follow, .rm-inv {
  flex: none; height: 26px; padding: 0 12px; border-radius: 100px;
  border: 1px solid var(--hair); background: var(--paper);
  font-size: 12px; font-weight: 500; color: var(--ink-2);
  transition: border-color .14s var(--ease), background .14s var(--ease), color .14s var(--ease);
}
.rm-follow:hover, .rm-inv:hover { border-color: var(--ink); color: var(--ink); }
.rm-follow[aria-pressed="true"] { background: var(--blue); border-color: var(--blue); color: #fff; }
.rm-inv.in, .rm-inv:disabled { background: rgba(18,145,90,.1); border-color: transparent; color: var(--green); cursor: default; }
.rm-tag { flex: none; font-size: 10.5px; color: var(--ink-3); }
.rm-none { font-size: 12.5px; line-height: 1.5; color: var(--ink-3); padding: 6px 8px; }
.rm-link { display: flex; gap: 6px; margin-bottom: 9px; }
.rm-link input {
  flex: 1; min-width: 0; height: 32px; padding: 0 11px; border-radius: 9px;
  border: 1px solid var(--hair); background: var(--canvas); color: var(--ink-2);
  font-size: 12px; outline: none;
}
.rm-copy {
  flex: none; height: 32px; padding: 0 14px; border-radius: 9px;
  background: var(--ink); color: #fff; font-size: 12.5px; font-weight: 500;
}
.rm-leave {
  width: 100%; height: 32px; border-radius: 100px; background: var(--canvas);
  font-size: 13px; font-weight: 500; color: var(--ink-2);
}
.rm-leave:hover { background: rgba(215,0,21,.09); color: var(--red); }
.rm-dir { margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--hair); }
.rm-dir h4 {
  font-family: var(--font); font-size: 11px; font-weight: 600; letter-spacing: .01em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 6px; padding: 0 8px;
}
.rm-fine {
  margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--hair);
  font-size: 11.5px; line-height: 1.55; color: var(--ink-3);
}
.rm-fine code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px;
  background: var(--canvas); padding: 1px 5px; border-radius: 4px;
}

/* =================================================================== Admin */
.admin-grid { margin-top: 26px; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }
.admin-card { padding: 20px; border-radius: 18px; background: var(--paper); border: 1px solid var(--hair); }
.admin-head { display: flex; align-items: center; gap: 12px; }
.admin-av {
  width: 40px; height: 40px; border-radius: 50%; flex: none; display: grid; place-items: center;
  color: #fff; font-family: var(--font); font-size: 14px; font-weight: 600;
}
.admin-who { flex: 1; min-width: 0; }
.admin-who b { display: block; font-family: var(--font); font-size: 16px; font-weight: 600; letter-spacing: -.012em; }
.admin-who span { display: block; font-size: 12.5px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin-grade {
  flex: none; height: 22px; padding: 0 9px; border-radius: 100px; background: var(--canvas);
  display: inline-flex; align-items: center; font-size: 11.5px; font-weight: 500; color: var(--ink-2);
}
.admin-en { margin-top: 14px; padding: 11px 13px; border-radius: 11px; background: var(--canvas); }
.admin-en b { display: block; font-size: 13.5px; font-weight: 500; }
.admin-en span { display: block; margin-top: 2px; font-size: 12px; color: var(--ink-3); }
.admin-stats { display: flex; gap: 22px; margin-top: 16px; }
.admin-stat b { display: block; font-family: var(--font); font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.016em; }
.admin-stat span { font-size: 11.5px; color: var(--ink-3); }
.admin-passes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.admin-pass {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 100px;
  background: var(--canvas); font-size: 11.5px; color: var(--ink-2);
}
.admin-pass i { width: 7px; height: 7px; border-radius: 50%; }
.admin-shape { margin-top: 12px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.admin-shape.quiet { color: var(--ink-3); font-size: 12.5px; }
.admin-acts { display: flex; gap: 8px; margin-top: 16px; }
.admin-acts .lx-btn { height: 34px; font-size: 13.5px; }
/* The admin's own chip says so, quietly. */
body.is-admin .lx-user .av { box-shadow: 0 0 0 2px var(--paper), 0 0 0 3.5px var(--blue); }

/* ==================================================================== Tutor
   Bottom right, and quiet until it is wanted.

   The closed state is a pill; the open state is a panel that grows out of
   exactly where the pill was. That shared origin is the whole trick — it
   reads as one object changing size rather than two things swapping places,
   which is the difference between a panel that appears and a panel that
   arrives. Everything else here is material: a translucent ground, a hairline
   of light along the top edge, and a shadow deep enough to say the panel is
   in front of the page rather than printed on it. */
.tt-open {
  position: fixed; right: 22px; bottom: 22px; z-index: 55;
  display: flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 18px 0 15px; border-radius: 100px;
  background: rgba(29,29,31,.92); color: #fff;
  -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
  font-family: var(--font); font-size: 14px; font-weight: 500; letter-spacing: -.01em;
  box-shadow: 0 8px 28px rgba(0,0,0,.2), 0 1px 2px rgba(0,0,0,.14),
              inset 0 1px 0 rgba(255,255,255,.14);
  transition: transform .3s var(--ease), opacity .2s var(--ease), box-shadow .3s var(--ease);
}
.tt-open svg { width: 17px; height: 17px; }
.tt-open:hover { transform: translateY(-2px); box-shadow: 0 14px 38px rgba(0,0,0,.26), inset 0 1px 0 rgba(255,255,255,.16); }
.tt-open:active { transform: translateY(0) scale(.97); }
.tt-open.gone { opacity: 0; transform: translateY(8px) scale(.86); pointer-events: none; }

.tt {
  position: fixed; right: 22px; bottom: 22px; z-index: 56;
  width: min(388px, calc(100vw - 44px));
  height: min(580px, calc(100vh - 108px));
  display: flex; flex-direction: column;
  border-radius: 24px; overflow: hidden;
  background: rgba(250,250,252,.78);
  -webkit-backdrop-filter: saturate(190%) blur(34px);
  backdrop-filter: saturate(190%) blur(34px);
  border: .5px solid rgba(0,0,0,.12);
  box-shadow: 0 32px 80px rgba(0,0,0,.22), 0 6px 18px rgba(0,0,0,.08),
              inset 0 1px 0 rgba(255,255,255,.7);
  transform-origin: calc(100% - 22px) calc(100% - 22px);
  animation: tt-in .42s cubic-bezier(.2,.9,.24,1);
}
@keyframes tt-in {
  from { opacity: 0; transform: translateY(10px) scale(.9); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .tt { animation: none; } }

.tt-head {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 15px 11px 13px 17px;
  border-bottom: .5px solid rgba(0,0,0,.08);
}
.tt-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--ink-3); box-shadow: 0 0 0 3px rgba(0,0,0,.05);
  transition: background .3s var(--ease), box-shadow .3s var(--ease);
}
.tt-dot.live { background: var(--green); box-shadow: 0 0 0 3px rgba(18,145,90,.16); }
.tt-dot.busy { background: var(--blue); animation: tt-pulse 1.1s var(--ease) infinite; }
@keyframes tt-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.tt-title { flex: 1; min-width: 0; }
.tt-title b {
  display: block; font-family: var(--font); font-size: 14.5px; font-weight: 600;
  letter-spacing: -.014em;
}
.tt-title span {
  display: block; margin-top: 1px; font-size: 11.5px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tt-icon {
  width: 29px; height: 29px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: var(--ink-3);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.tt-icon svg { width: 15px; height: 15px; }
.tt-icon:hover { background: rgba(0,0,0,.055); color: var(--ink); }

/* The ladder, visible. A student can see how much help they are on, which is
   the point — help you cannot see the size of is help you cannot ration. */
.tt-ladder {
  display: flex; align-items: center; gap: 9px; flex: none;
  padding: 9px 17px; border-bottom: .5px solid rgba(0,0,0,.08);
}
.tt-ladder .rungs { display: flex; gap: 3px; }
.tt-ladder .rungs i {
  width: 16px; height: 3px; border-radius: 100px; background: rgba(0,0,0,.1);
  transition: background .35s var(--ease);
}
.tt-ladder .rungs i.on { background: var(--blue); }
.tt-ladder .lbl { font-size: 11.5px; color: var(--ink-2); letter-spacing: -.006em; }

.tt-log {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 17px; display: flex; flex-direction: column; gap: 11px;
  scrollbar-width: thin;
}
.tt-msg { max-width: 86%; font-size: 14.5px; line-height: 1.48; }
.tt-msg.me {
  align-self: flex-end; padding: 9px 14px; border-radius: 18px 18px 6px 18px;
  background: var(--blue); color: #fff;
  box-shadow: 0 1px 2px rgba(0,113,227,.24);
  animation: tt-msg-in .26s var(--ease);
}
.tt-msg.it {
  align-self: flex-start; color: var(--ink); white-space: pre-wrap;
  padding: 9px 14px; border-radius: 18px 18px 18px 6px;
  background: rgba(255,255,255,.72); border: .5px solid rgba(0,0,0,.06);
  box-shadow: 0 1px 2px rgba(0,0,0,.04);
  animation: tt-msg-in .26s var(--ease);
}
@keyframes tt-msg-in { from { opacity: 0; transform: translateY(5px); } }
@media (prefers-reduced-motion: reduce) { .tt-msg { animation: none; } }
.tt-msg.it b { font-weight: 600; }
.tt-msg.sys {
  align-self: stretch; padding: 14px 15px; border-radius: 15px;
  background: rgba(0,0,0,.038); font-size: 13.5px; line-height: 1.55; color: var(--ink-2);
}
.tt-msg.sys b { display: block; color: var(--ink); font-family: var(--font); font-weight: 600; margin-bottom: 4px; }
.tt-msg.sys code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px;
  background: var(--paper); padding: 2px 6px; border-radius: 6px; border: .5px solid var(--hair);
  display: inline-block; margin: 2px 0;
}
.tt-msg.sys a { color: var(--blue); }
.tt-caret::after {
  content: ""; display: inline-block; width: 2px; height: 1em;
  background: var(--ink-3); margin-left: 2px; vertical-align: -2px;
  animation: tt-blink .9s step-end infinite;
}
@keyframes tt-blink { 50% { opacity: 0; } }

.tt-ask { flex: none; padding: 11px 13px 13px; border-top: .5px solid rgba(0,0,0,.08); }
.tt-quick { display: flex; gap: 6px; margin-bottom: 9px; }
.tt-quick button {
  flex: 1; height: 29px; border-radius: 100px;
  background: rgba(255,255,255,.66); border: .5px solid rgba(0,0,0,.07);
  color: var(--ink-2); font-size: 12.5px; font-weight: 500;
  transition: background .15s var(--ease), color .15s var(--ease), transform .1s var(--ease);
}
.tt-quick button:hover { background: #fff; color: var(--ink); }
.tt-quick button:active { transform: scale(.97); }
.tt-quick button:disabled { opacity: .4; cursor: default; }
.tt-form { display: flex; align-items: flex-end; gap: 8px; }
.tt-form textarea {
  flex: 1; min-height: 38px; max-height: 120px; resize: none;
  padding: 9px 14px; border-radius: 19px;
  border: .5px solid rgba(0,0,0,.1); background: rgba(255,255,255,.9); color: var(--ink);
  font: inherit; font-size: 14.5px; line-height: 1.4; outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.tt-form textarea:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,113,227,.13); }
.tt-send {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  display: grid; place-items: center; background: var(--blue); color: #fff;
  box-shadow: 0 1px 3px rgba(0,113,227,.3);
  transition: opacity .15s var(--ease), transform .1s var(--ease), background .15s var(--ease);
}
.tt-send svg { width: 17px; height: 17px; }
.tt-send:disabled { opacity: .28; cursor: default; box-shadow: none; }
.tt-send:not(:disabled):hover { background: var(--blue-d); }
.tt-send:not(:disabled):active { transform: scale(.92); }

@media (max-width: 560px) {
  .tt { right: 10px; left: 10px; bottom: 10px; width: auto; height: min(74vh, 580px); }
  .tt-open { right: 14px; bottom: 14px; }
  .rm { right: 10px; left: 10px; width: auto; }
}

/* ===================================================================== Learn
   One card, and nothing else on the screen.

   A question a student is actually thinking about does not need a sidebar, a
   streak counter or a points total competing for the same attention — so the
   only things here are the question, the answers, and the help, in the order
   a tutor would offer it. The progress strip along the top is the exception,
   and it earns its place by being the student model rather than a decoration:
   one segment per concept, coloured by how well it is known. */
.ln { max-width: 820px; margin-inline: auto; }

.ln-top { display: flex; align-items: center; gap: 12px; margin-bottom: clamp(20px, 4vw, 34px); }
.ln-count {
  min-width: 30px; height: 30px; padding: 0 10px; border-radius: 100px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--green); color: #fff;
  font-family: var(--font); font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.ln-count.end { background: var(--sunk); color: var(--ink-2); }
.ln-track { flex: 1; display: flex; gap: 3px; min-width: 0; }
.ln-track i {
  flex: 1; height: 6px; border-radius: 100px; background: var(--sunk);
  transition: background .4s var(--ease), transform .2s var(--ease);
}
.ln-track i.here { transform: scaleY(1.7); }
.ln-quit {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: var(--ink-3);
  transition: background .14s var(--ease), color .14s var(--ease);
}
.ln-quit svg { width: 15px; height: 15px; }
.ln-quit:hover { background: var(--canvas); color: var(--ink); }

.ln-card {
  padding: clamp(24px, 4vw, 40px); border-radius: 26px;
  background: var(--paper); border: 1px solid var(--hair);
  box-shadow: 0 1px 2px rgba(0,0,0,.03), 0 12px 40px rgba(0,0,0,.05);
  animation: ln-card-in .3s var(--ease);
}
@keyframes ln-card-in { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .ln-card { animation: none; } }

.ln-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.ln-card-head .lbl {
  flex: 1; min-width: 0; font-family: var(--font); font-size: 11.5px; font-weight: 600;
  letter-spacing: .012em; text-transform: uppercase; color: var(--ink-3);
}
.ln-lv {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding: 0 11px 0 9px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2);
  font-size: 11.5px; font-weight: 500;
}
.ln-lv i { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); }
.ln-lv i.n0 { background: #c7c7cc; } .ln-lv i.n1 { background: #4da3ff; }
.ln-lv i.n2 { background: #ff9f0a; } .ln-lv i.n3 { background: #34c759; }
.ln-lv i.n4 { background: #8f5cff; }
.ln-diag {
  flex: none; height: 24px; padding: 0 11px; border-radius: 100px;
  display: inline-flex; align-items: center;
  background: rgba(0,113,227,.1); color: var(--blue); font-size: 11.5px; font-weight: 500;
}

.ln-prompt {
  font-family: var(--font); font-size: clamp(20px, 2.6vw, 27px); font-weight: 500;
  line-height: 1.34; letter-spacing: -.018em; color: var(--ink);
  max-width: 30em;
}
.ln-teach-h {
  font-family: var(--font); font-size: clamp(26px, 3.4vw, 36px); font-weight: 600;
  letter-spacing: -.021em; margin-bottom: 10px;
}
.ln-ask {
  margin-top: clamp(22px, 3vw, 32px); margin-bottom: 12px;
  font-family: var(--font); font-size: 11.5px; font-weight: 600;
  letter-spacing: .012em; text-transform: uppercase; color: var(--ink-3);
}

.ln-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 620px) { .ln-opts { grid-template-columns: 1fr; } }
/* When the options are whole definitions rather than single terms, two
   columns turn every one of them into a narrow column of broken lines. One
   column, top-aligned, and the number stays level with the first line. */
.ln-opts.long { grid-template-columns: 1fr; }
.ln-opts.long .ln-opt { align-items: flex-start; padding: 15px 17px; }
.ln-opts.long .ln-opt .n { margin-top: 1px; }
.ln-opt {
  display: flex; align-items: center; gap: 13px; text-align: left;
  min-height: 58px; padding: 13px 17px; border-radius: 15px;
  background: var(--paper); border: 1px solid var(--rule);
  font-size: 15.5px; line-height: 1.4; color: var(--ink);
  transition: border-color .15s var(--ease), background .15s var(--ease),
              transform .1s var(--ease), box-shadow .15s var(--ease);
}
.ln-opt .n {
  width: 22px; height: 22px; border-radius: 7px; flex: none;
  display: grid; place-items: center; background: var(--canvas); color: var(--ink-3);
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.ln-opt .t { flex: 1; min-width: 0; }
.ln-opt:not(:disabled):hover {
  border-color: var(--ink); box-shadow: 0 2px 10px rgba(0,0,0,.06);
}
.ln-opt:not(:disabled):hover .n { background: var(--ink); color: #fff; }
.ln-opt:not(:disabled):active { transform: scale(.99); }
.ln-opt:disabled { cursor: default; }
.ln-opt.right {
  border-color: var(--green); background: rgba(52,199,89,.08); color: var(--ink);
}
.ln-opt.right .n { background: var(--green); color: #fff; }
.ln-opt.wrong { border-color: var(--red); background: rgba(255,69,58,.06); }
.ln-opt.wrong .n { background: var(--red); color: #fff; }
.ln-opt:disabled:not(.right):not(.wrong) { opacity: .45; }

.ln-type { display: flex; gap: 9px; }
.ln-type input {
  flex: 1; min-width: 0; height: 52px; padding: 0 18px; border-radius: 15px;
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  font: inherit; font-size: 17px; outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.ln-type input:focus { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(0,113,227,.12); }
.ln-type input.right { border-color: var(--green); background: rgba(52,199,89,.07); }
.ln-type input.wrong { border-color: var(--red); background: rgba(255,69,58,.05); }
.ln-free textarea {
  width: 100%; resize: vertical; padding: 15px 18px; border-radius: 15px;
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  font: inherit; font-size: 16px; line-height: 1.5; outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.ln-free textarea:focus { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(0,113,227,.12); }
.ln-go {
  height: 52px; padding: 0 26px; border-radius: 15px; flex: none;
  background: var(--ink); color: #fff; font-size: 15.5px; font-weight: 500;
  transition: background .15s var(--ease), opacity .15s var(--ease);
}
.ln-go.wide { width: 100%; margin-top: 10px; }
.ln-go:hover { background: #000; }
.ln-go:disabled { opacity: .35; cursor: default; }

/* The help, in the order it should be offered. */
.ln-help {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--hair);
}
.ln-hint {
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 15px 0 12px; border-radius: 100px;
  background: rgba(255,214,10,.16); color: #7a5a00;
  font-size: 13.5px; font-weight: 500;
  transition: background .15s var(--ease), opacity .15s var(--ease);
}
.ln-hint svg { width: 15px; height: 15px; }
.ln-hint:hover { background: rgba(255,214,10,.3); }
.ln-hint:disabled { opacity: .4; cursor: default; }
.ln-why {
  height: 32px; padding: 0 14px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2); font-size: 13.5px;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.ln-why:hover { background: var(--sunk); color: var(--ink); }
.ln-dunno {
  margin-left: auto; height: 32px; padding: 0 14px; border-radius: 100px;
  color: var(--blue); font-size: 13.5px; font-weight: 500;
}
.ln-dunno:hover { background: rgba(0,113,227,.08); }
.ln-help-out { display: grid; gap: 8px; }
.ln-help-out:not(:empty) { margin-top: 12px; }
.ln-hintbox, .ln-note {
  padding: 13px 16px; border-radius: 13px; background: var(--canvas);
  animation: ln-card-in .22s var(--ease);
}
.ln-hintbox b, .ln-note b {
  display: block; font-family: var(--font); font-size: 11.5px; font-weight: 600;
  letter-spacing: .01em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 4px;
}
.ln-hintbox p, .ln-note p { font-size: 14.5px; line-height: 1.5; color: var(--ink-2); }
.ln-note .eg { margin-top: 7px; color: var(--ink-3); font-size: 13.5px; }

/* The verdict. A wrong answer gets more room than a right one, because a
   wrong answer is where the teaching is. */
.ln-verdict-slot:not(:empty) { margin-top: 20px; }
.ln-verdict {
  padding: 18px 20px; border-radius: 16px; border: 1px solid var(--hair);
  animation: ln-card-in .24s var(--ease);
}
.ln-verdict.right { background: rgba(52,199,89,.07); border-color: rgba(52,199,89,.24); }
.ln-verdict.wrong { background: rgba(255,69,58,.05); border-color: rgba(255,69,58,.2); }
.ln-verdict.skip { background: var(--canvas); }
.ln-verdict b {
  display: block; font-family: var(--font); font-size: 16px; font-weight: 600;
  letter-spacing: -.012em; margin-bottom: 6px;
}
.ln-verdict p { font-size: 15px; line-height: 1.55; color: var(--ink-2); }
.ln-verdict p + p { margin-top: 9px; }
.ln-verdict em { font-style: normal; font-weight: 500; color: var(--ink); }
.ln-verdict .ln-miss {
  padding: 11px 14px; border-radius: 11px; background: rgba(255,255,255,.7);
  border-left: 3px solid var(--red);
}
.ln-verdict .ln-miss em { display: block; margin-bottom: 3px; color: var(--red); font-weight: 500; }
.ln-verdict .eg { color: var(--ink-3); font-size: 14px; }

.ln-conf { padding: 16px 18px; border-radius: 16px; background: var(--canvas); }
.ln-conf b { display: block; font-family: var(--font); font-size: 14.5px; font-weight: 600; margin-bottom: 11px; }
.ln-conf-row { display: flex; gap: 7px; flex-wrap: wrap; }
.ln-conf-row button {
  flex: 1 1 auto; height: 38px; padding: 0 16px; border-radius: 100px;
  background: var(--paper); border: 1px solid var(--hair);
  font-size: 14px; font-weight: 500; color: var(--ink-2);
  transition: border-color .14s var(--ease), color .14s var(--ease);
}
.ln-conf-row button:hover { border-color: var(--ink); color: var(--ink); }

.ln-state {
  display: flex; align-items: center; gap: 9px; margin-top: 16px;
  padding-top: 14px; border-top: 1px solid rgba(0,0,0,.07); font-size: 13.5px;
}
.ln-state .dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.ln-state .nm { flex: 1; min-width: 0; color: var(--ink-2); }
.ln-state .nm b { display: inline; font-size: inherit; margin: 0; color: var(--ink); }
.ln-state .due { flex: none; font-size: 12.5px; color: var(--ink-3); }

.ln-dims { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin-top: 13px; }
@media (max-width: 620px) { .ln-dims { grid-template-columns: repeat(2, 1fr); } }
.ln-dim span {
  display: block; font-size: 10.5px; color: var(--ink-3); margin-bottom: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ln-dim .t { height: 3px; border-radius: 100px; background: rgba(0,0,0,.09); overflow: hidden; }
.ln-dim .t i { display: block; height: 100%; background: var(--ink-3); transition: width .5s var(--ease); }
.ln-dim.now span { color: var(--ink); font-weight: 500; }
.ln-dim.now .t i { background: var(--blue); }

.ln-next { display: flex; gap: 9px; margin-top: 16px; }
.ln-continue {
  flex: 1; height: 48px; border-radius: 100px; background: var(--blue); color: #fff;
  font-family: var(--font); font-size: 16px; font-weight: 500;
  transition: background .15s var(--ease), transform .1s var(--ease);
}
.ln-continue:hover { background: var(--blue-d); }
.ln-continue:active { transform: scale(.99); }
.ln-talk {
  flex: none; display: inline-flex; align-items: center; gap: 8px;
  height: 48px; padding: 0 20px; border-radius: 100px;
  background: var(--canvas); color: var(--ink-2); font-size: 15px; font-weight: 500;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.ln-talk svg { width: 17px; height: 17px; }
.ln-talk:hover { background: var(--sunk); color: var(--ink); }

/* ------------------------------------------------------------- The goal
   Asked first, and it changes the session rather than decorating it. */
.ln-open { max-width: 760px; margin-inline: auto; }
.ln-open-h {
  font-family: var(--font); font-size: clamp(28px, 4.4vw, 40px); font-weight: 600;
  line-height: 1.08; letter-spacing: -.021em;
}
.ln-open-p { margin-top: 12px; font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 54ch; }
.ln-goals {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: 10px; margin-top: 30px;
}
.ln-goal {
  text-align: left; padding: 18px; border-radius: 18px;
  background: var(--paper); border: 1px solid var(--hair);
  transition: border-color .15s var(--ease), transform .12s var(--ease), box-shadow .15s var(--ease);
}
.ln-goal:hover {
  border-color: var(--ink); transform: translateY(-2px);
  box-shadow: 0 8px 26px rgba(0,0,0,.07);
}
.ln-goal .ic {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 11px;
  background: var(--canvas); color: var(--ink-2); margin-bottom: 12px;
}
.ln-goal .ic svg { width: 17px; height: 17px; }
.ln-goal b { display: block; font-family: var(--font); font-size: 16px; font-weight: 600; letter-spacing: -.012em; }
.ln-goal .s { display: block; margin-top: 5px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }

.ln-known { margin-top: 32px; padding: 20px; border-radius: 18px; background: var(--paper); border: 1px solid var(--hair); }
.ln-known > b { display: block; font-family: var(--font); font-size: 13.5px; font-weight: 600; margin-bottom: 11px; }
.ln-known-bar { display: flex; gap: 2px; height: 8px; border-radius: 100px; overflow: hidden; background: var(--sunk); }
.ln-known-bar i { display: block; height: 100%; }
.ln-known-say { margin-top: 11px; font-size: 13px; color: var(--ink-3); }
.ln-known-flag {
  display: flex; align-items: flex-start; gap: 9px; margin-top: 12px;
  padding: 12px 14px; border-radius: 12px; background: rgba(255,69,58,.06);
  font-size: 13.5px; line-height: 1.5; color: var(--ink-2);
}
.ln-known-flag svg { width: 16px; height: 16px; flex: none; color: var(--red); margin-top: 1px; }

/* ----------------------------------------------------------- The report */
.ln-report { max-width: 800px; margin-inline: auto; }
.ln-rep-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px; margin-top: 30px;
}
.ln-rep-col { padding: 16px 18px; border-radius: 16px; background: var(--paper); border: 1px solid var(--hair); }
.ln-rep-col h3 {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--font); font-size: 13px; font-weight: 600;
  padding-bottom: 10px; margin-bottom: 9px; border-bottom: 1px solid var(--hair);
}
.ln-rep-col h3 i { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ln-rep-col h3 em {
  margin-left: auto; font-style: normal; font-size: 12px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.ln-rep-col li { font-size: 13.5px; line-height: 1.75; color: var(--ink-2); }

.ln-rep-moved, .ln-rep-flag, .ln-rep-plan {
  margin-top: 26px; padding: 20px; border-radius: 18px;
  background: var(--paper); border: 1px solid var(--hair);
}
.ln-rep-moved h3, .ln-rep-flag h3, .ln-rep-plan h3 {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font); font-size: 15px; font-weight: 600; letter-spacing: -.012em;
  margin-bottom: 13px;
}
.ln-rep-flag h3 svg { width: 17px; height: 17px; color: var(--red); }
.ln-rep-flag p { font-size: 14.5px; line-height: 1.55; color: var(--ink-2); }
.ln-rep-flag b { color: var(--ink); font-weight: 600; }
.ln-move { display: flex; align-items: center; gap: 12px; padding: 6px 0; font-size: 14px; }
.ln-move > span { flex: 0 0 34%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ln-move .t { flex: 1; position: relative; height: 6px; border-radius: 100px; background: var(--sunk); overflow: hidden; }
.ln-move .t i { position: absolute; left: 0; top: 0; height: 100%; border-radius: 100px; }
.ln-move .t .is { background: var(--green); }
.ln-move .t .was { background: var(--rule); z-index: 1; }
.ln-move em {
  flex: none; font-style: normal; font-size: 12.5px; font-weight: 600; color: var(--green);
  font-variant-numeric: tabular-nums;
}
.ln-rep-plan li {
  display: flex; align-items: baseline; gap: 10px; padding: 7px 0;
  border-bottom: 1px solid var(--hair); font-size: 14.5px;
}
.ln-rep-plan li:last-child { border-bottom: 0; }
.ln-rep-plan li b { flex: 1; font-weight: 500; }
.ln-rep-plan li span { flex: none; font-size: 13px; color: var(--ink-3); }
.ln-rep-say { margin-top: 12px; font-size: 13.5px; line-height: 1.55; color: var(--ink-3); }
.ln-rep-acts { display: flex; gap: 10px; margin-top: 30px; }

/* ==========================================================================
   The game layer.

   Everything here obeys one constraint: it is never allowed to move, flash or
   appear while a student is answering a question. So the award surfaces are
   fixed to the corners of the viewport rather than placed in the flow, the
   rank chip lives in the bar, and the only large celebration — a badge — is
   rare enough to be worth the interruption.
   ========================================================================== */

/* -------------------------------------------------------------- Rank chip */
.lx-rank {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 4px 9px 5px; border-radius: 8px; min-width: 78px;
  background: var(--sunk); transition: background .18s var(--ease);
}
.lx-rank:hover { background: #e2e2e5; }
.lx-rank b { font-size: 11px; font-weight: 600; letter-spacing: -.01em; line-height: 1; }
.lx-rank i {
  display: block; height: 3px; border-radius: 2px; background: var(--blue);
  min-width: 3px; transition: width .5s var(--ease);
}
.lx-rank i {
  /* The chip is its own track: the fill sits on the chip's sunk background,
     so there is no second element to keep in sync. */
  background: var(--blue); width: 0;
}

/* ------------------------------------------------------------- Experience
   Bottom left, opposite the tutor, so the two can never collide. */
.lx-xp {
  position: fixed; left: 20px; bottom: 20px; z-index: 60;
  display: flex; align-items: baseline; gap: 9px;
  padding: 9px 14px; border-radius: 999px;
  background: rgba(29,29,31,.92); color: #fff;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  opacity: 0; transform: translateY(8px) scale(.96);
  transition: opacity .22s var(--ease), transform .22s var(--ease);
  pointer-events: none;
}
.lx-xp.on { opacity: 1; transform: translateY(0) scale(1); }
.lx-xp b { font-size: 16px; font-weight: 600; letter-spacing: -.02em; }
.lx-xp span { font-size: 12px; color: rgba(255,255,255,.7); letter-spacing: -.01em; }

/* ----------------------------------------------------------------- Badge */
.lx-badge {
  position: fixed; left: 50%; bottom: 28px; z-index: 70;
  display: flex; align-items: center; gap: 14px;
  width: min(420px, calc(100vw - 40px));
  padding: 15px 18px; border-radius: 18px;
  background: var(--paper); color: var(--ink);
  box-shadow: 0 20px 60px rgba(0,0,0,.22), 0 0 0 .5px rgba(0,0,0,.08);
  opacity: 0; transform: translateX(-50%) translateY(16px) scale(.97);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
  pointer-events: none;
}
.lx-badge.on { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
.lx-badge .ic {
  flex: none; width: 42px; height: 42px; border-radius: 12px;
  display: grid; place-items: center;
  background: linear-gradient(160deg, #ffcf4d, #e8a317); color: #fff;
}
.lx-badge .ic svg { width: 22px; height: 22px; }
.lx-badge .t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lx-badge em {
  font-style: normal; font-size: 10.5px; font-weight: 600; color: var(--amber);
  text-transform: uppercase; letter-spacing: .07em;
}
.lx-badge b { font-size: 15px; font-weight: 600; letter-spacing: -.02em; }
.lx-badge .t > span { font-size: 12.5px; color: var(--ink-2); line-height: 1.4; }

/* ------------------------------------------------- Session report, earnings */
.ln-rep-xp {
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
  margin-top: 26px; padding: 20px 22px;
  background: var(--paper); border-radius: var(--r);
  box-shadow: 0 0 0 .5px var(--hair);
}
.ln-xp-num { display: flex; flex-direction: column; }
.ln-xp-num b { font-family: var(--font); font-size: 30px; font-weight: 600; letter-spacing: -.03em; }
.ln-xp-num span { font-size: 12px; color: var(--ink-3); }
.ln-xp-rank { flex: 1 1 200px; min-width: 180px; }
.ln-xp-rank .t {
  height: 5px; border-radius: 3px; background: var(--sunk); overflow: hidden; margin-bottom: 8px;
}
.ln-xp-rank .t i { display: block; height: 100%; background: var(--blue); border-radius: 3px; }
.ln-xp-rank p { font-size: 14px; }
.ln-xp-rank span { font-size: 12.5px; color: var(--ink-2); }
.ln-xp-streak { display: flex; flex-direction: column; align-items: flex-end; }
.ln-xp-streak b { font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: -.03em; }
.ln-xp-streak span { font-size: 12px; color: var(--ink-3); }

/* ----------------------------------------------------------- Resume offer */
.ln-resume { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 26px; }

/* ------------------------------------------------------ Home: the standing
   Rank, streak, week and goal, on the home screen where a student is
   deciding what to do rather than in the middle of doing it. */
.lx-standing {
  display: grid; grid-template-columns: 1.3fr 1fr; gap: 14px;
  margin: 8px 0 30px;
}
@media (max-width: 720px) { .lx-standing { grid-template-columns: 1fr; } }
.lx-stand-card {
  background: var(--paper); border-radius: var(--r); padding: 20px 22px;
  box-shadow: 0 0 0 .5px var(--hair);
}
.lx-stand-card .k {
  font-size: 11px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 10px;
}
.lx-stand-rank { display: flex; align-items: baseline; gap: 10px; }
.lx-stand-rank b { font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: -.03em; }
.lx-stand-rank em { font-style: normal; font-size: 13px; color: var(--ink-3); }
.lx-stand-track {
  height: 6px; border-radius: 3px; background: var(--sunk); overflow: hidden; margin: 12px 0 8px;
}
.lx-stand-track i { display: block; height: 100%; background: var(--blue); border-radius: 3px;
  transition: width .6s var(--ease); }
.lx-stand-card p { font-size: 13.5px; color: var(--ink-2); line-height: 1.45; }

.lx-week { display: flex; gap: 6px; align-items: flex-end; height: 58px; margin-bottom: 10px; }
.lx-week-day { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; height: 100%; }
.lx-week-bar {
  width: 100%; flex: 1; display: flex; align-items: flex-end;
  background: var(--sunk); border-radius: 4px; overflow: hidden;
}
.lx-week-bar i { display: block; width: 100%; background: var(--blue); border-radius: 4px; min-height: 2px; }
.lx-week-day.none .lx-week-bar i { background: var(--rule); }
.lx-week-day.today .lx-week-bar { box-shadow: 0 0 0 1.5px var(--blue); }
.lx-week-day span { font-size: 10.5px; color: var(--ink-3); }

.lx-goal { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.lx-goal b { font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.03em; }
.lx-goal span { font-size: 12.5px; color: var(--ink-3); }

.lx-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.lx-bdg {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 7px; border-radius: 999px;
  background: var(--sunk); font-size: 12px; letter-spacing: -.01em;
}
.lx-bdg svg { width: 13px; height: 13px; color: var(--amber); }
.lx-bdg.off { opacity: .38; }
.lx-bdg.off svg { color: var(--ink-3); }

/* ==========================================================================
   Games.

   Same restraint as everything else: one accent, a green for right and a red
   for wrong, and no animation that outlasts the moment it explains. A game
   here looks like the rest of the app because it is the rest of the app —
   what it collects goes into the same record.
   ========================================================================== */

.lx-games { margin-top: 12px; }

.gm { max-width: 660px; margin: 0 auto; }
.gm-top {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 26px; min-height: 24px;
}
.gm-count {
  font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums;
  min-width: 56px;
}
.gm-track {
  flex: 1; height: 4px; border-radius: 2px; background: var(--sunk); overflow: hidden;
}
.gm-track i {
  display: block; height: 100%; background: var(--blue); border-radius: 2px;
  transition: width .35s var(--ease);
}
.gm-streak {
  font-size: 12.5px; color: var(--ink-3); min-width: 72px; text-align: right;
  font-variant-numeric: tabular-nums;
}
.gm-streak.hot { color: var(--amber); font-weight: 600; }

.gm-card {
  background: var(--paper); border-radius: var(--r); padding: 30px 32px;
  box-shadow: 0 0 0 .5px var(--hair), 0 2px 14px rgba(0,0,0,.04);
}
.gm-kind {
  display: block; font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 12px;
}
.gm-def {
  font-family: var(--font); font-size: 23px; line-height: 1.34;
  letter-spacing: -.022em;
}

.gm-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 20px; }
@media (max-width: 560px) { .gm-opts { grid-template-columns: 1fr; } }
.gm-opt {
  min-height: 54px; padding: 13px 18px; border-radius: 14px; text-align: left;
  background: var(--paper); border: 1px solid var(--rule);
  font-size: 15.5px; line-height: 1.35;
  transition: border-color .15s var(--ease), background .15s var(--ease),
              transform .1s var(--ease);
}
.gm-opt:not(:disabled):hover { border-color: var(--ink); }
.gm-opt:not(:disabled):active { transform: scale(.99); }
.gm-opt:disabled { cursor: default; }
.gm-opt.right { border-color: var(--green); background: #eaf7f0; color: #0b6b43; font-weight: 500; }
.gm-opt.wrong { border-color: var(--red); background: #fdeced; color: #a30010; }

/* --------------------------------------------------------------- Word hunt */
.gm-hunt { max-width: 880px; }
.hunt-board { display: grid; grid-template-columns: minmax(0,1fr) 220px; gap: 28px; }
@media (max-width: 780px) { .hunt-board { grid-template-columns: 1fr; } }
.hunt-grid {
  display: grid; grid-template-columns: repeat(var(--n), 1fr); gap: 3px;
  background: var(--paper); padding: 12px; border-radius: var(--r);
  box-shadow: 0 0 0 .5px var(--hair);
}
.hunt-cell {
  aspect-ratio: 1; display: grid; place-items: center; border-radius: 6px;
  font-family: var(--font); font-size: clamp(11px, 1.6vw, 15px); font-weight: 500;
  color: var(--ink); background: transparent;
  transition: background .12s var(--ease), color .12s var(--ease), transform .1s var(--ease);
}
.hunt-cell:hover { background: var(--sunk); }
.hunt-cell.pick { background: var(--ink); color: #fff; transform: scale(1.06); }
.hunt-cell.hit { background: #d9f0e4; color: #0b6b43; font-weight: 600; }
.hunt-cell.hit:hover { background: #d9f0e4; }
.hunt-cell.nope { background: #fdeced; color: var(--red); }

.hunt-words b {
  display: block; font-size: 11px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 12px;
}
.hunt-words li {
  padding: 6px 0; font-size: 14.5px; border-bottom: 1px solid var(--hair);
  transition: color .2s var(--ease);
}
.hunt-words li.got { color: var(--ink-3); text-decoration: line-through; }
.hunt-say { margin-top: 16px; font-size: 12.5px; color: var(--ink-3); line-height: 1.45; }

/* ----------------------------------------------------------------- Hangman */
.gm-hang { max-width: 620px; }
.hang-lives { display: flex; gap: 4px; align-items: center; }
.hang-lives i {
  width: 7px; height: 7px; border-radius: 50%; background: var(--hair);
  transition: background .25s var(--ease);
}
.hang-lives i.on { background: var(--ink); }

.hang-word {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 7px;
  margin: 34px 0 30px;
}
.hang-word .sl {
  width: 30px; height: 40px; display: grid; place-items: center;
  border-bottom: 2.5px solid var(--rule);
  font-family: var(--font); font-size: 23px; font-weight: 600; letter-spacing: -.02em;
  transition: border-color .2s var(--ease);
}
.hang-word .sl.on { border-bottom-color: var(--ink); }
.hang-word .sp {
  width: 16px; height: 40px; display: grid; place-items: center;
  font-size: 21px; color: var(--ink-3);
}

.hang-keys {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(38px, 1fr));
  gap: 7px; max-width: 470px; margin: 0 auto;
}
.hang-key {
  height: 44px; border-radius: 10px; background: var(--paper);
  border: 1px solid var(--rule); font-size: 15px; font-weight: 500;
  transition: background .12s var(--ease), border-color .12s var(--ease),
              transform .1s var(--ease), opacity .2s var(--ease);
}
.hang-key:not(:disabled):hover { border-color: var(--ink); background: var(--canvas); }
.hang-key:not(:disabled):active { transform: scale(.95); }
.hang-key:disabled { cursor: default; }
.hang-key.hit { background: #eaf7f0; border-color: #a8ddc2; color: #0b6b43; }
.hang-key.miss { opacity: .32; }

.hang-help { display: flex; justify-content: center; margin-top: 22px; }

.hang-end { text-align: center; margin-top: 8px; }
.hang-end b {
  display: block; font-family: var(--font); font-size: 26px; font-weight: 600;
  letter-spacing: -.03em; margin-bottom: 6px;
}
.hang-end.won b { color: var(--green); }
.hang-end.lost b { color: var(--red); }
.hang-end p {
  font-size: 14.5px; color: var(--ink-2); max-width: 420px; margin: 0 auto 20px;
  line-height: 1.45;
}

/* ==========================================================================
   The console.

   Forms, tables and lists. Nothing here is styled to look important, because
   the work is: a gradebook that draws attention to itself is a gradebook
   somebody misreads.
   ========================================================================== */

.admin-tabs {
  display: flex; gap: 4px; margin: 22px 0 26px;
  border-bottom: 1px solid var(--hair); flex-wrap: wrap;
}
.admin-tab {
  padding: 9px 14px 11px; font-size: 14.5px; color: var(--ink-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.admin-tab:hover { color: var(--ink); }
.admin-tab.on { color: var(--ink); font-weight: 500; border-bottom-color: var(--ink); }

.admin-body { padding-bottom: 60px; }

/* ------------------------------------------------------------------ Lists */
.admin-list { margin-top: 18px; }
.admin-row {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 4px; border-bottom: 1px solid var(--hair);
}
.admin-row .t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.admin-row .t b { font-size: 15px; font-weight: 500; letter-spacing: -.015em; }
.admin-row .t > span { font-size: 12.5px; color: var(--ink-3); }

.admin-av.sm { width: 30px; height: 30px; font-size: 11px; }

/* ------------------------------------------------------------------ Forms */
.admin-form {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px;
  margin: 22px 0 26px;
}
@media (max-width: 640px) { .admin-form { grid-template-columns: 1fr; } }
.admin-field { display: flex; flex-direction: column; gap: 6px; }
.admin-field:has(textarea) { grid-column: 1 / -1; }
.admin-field > span {
  font-size: 11px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em;
}
.admin-field input, .admin-field textarea, .admin-field select {
  font: inherit; font-size: 15px; color: var(--ink);
  padding: 10px 13px; border-radius: 11px;
  border: 1px solid var(--rule); background: var(--paper);
  transition: border-color .15s var(--ease);
}
.admin-field textarea { resize: vertical; line-height: 1.45; }
.admin-field input:focus, .admin-field textarea:focus, .admin-field select:focus {
  outline: none; border-color: var(--blue);
}
.admin-field input:disabled, .admin-field textarea:disabled, .admin-field select:disabled {
  background: var(--sunk); color: var(--ink-2);
}

/* ----------------------------------------------------------------- Tables */
.admin-table { margin: 18px 0 22px; }
.admin-tr {
  display: grid; grid-template-columns: 1.4fr 1fr 90px 90px 34px;
  gap: 8px; align-items: center; padding: 7px 0;
  border-bottom: 1px solid var(--hair);
}
.admin-table.cards .admin-tr { grid-template-columns: 1fr 2.2fr 34px; align-items: start; }
@media (max-width: 700px) {
  .admin-tr, .admin-table.cards .admin-tr { grid-template-columns: 1fr; }
  .admin-tr.head { display: none; }
}
.admin-tr.head span {
  font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; padding-bottom: 4px;
}
.admin-tr input, .admin-tr textarea, .admin-tr select {
  font: inherit; font-size: 14.5px; width: 100%;
  padding: 8px 11px; border-radius: 9px;
  border: 1px solid var(--rule); background: var(--paper);
}
.admin-tr textarea { resize: vertical; line-height: 1.4; }
.admin-tr input:focus, .admin-tr textarea:focus, .admin-tr select:focus {
  outline: none; border-color: var(--blue);
}
.admin-tr input:disabled, .admin-tr textarea:disabled, .admin-tr select:disabled {
  background: var(--sunk); color: var(--ink-2);
}
.admin-x {
  width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center;
  color: var(--ink-3); transition: background .15s var(--ease), color .15s var(--ease);
}
.admin-x svg { width: 15px; height: 15px; }
.admin-x:hover { background: #fdeced; color: var(--red); }

/* -------------------------------------------------------------- Gradebook */
.admin-mark {
  background: var(--paper); border-radius: var(--r); padding: 22px 24px;
  box-shadow: 0 0 0 .5px var(--hair); margin-bottom: 22px;
}
.admin-mark .big { display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px; }
.admin-mark .big b {
  font-family: var(--font); font-size: 40px; font-weight: 600; letter-spacing: -.04em;
  line-height: 1;
}
.admin-mark .big span { font-size: 17px; color: var(--ink-2); }
.admin-mark-part {
  display: grid; grid-template-columns: 130px 1fr 46px; gap: 12px;
  align-items: center; padding: 7px 0;
}
.admin-mark-part > span:first-child { font-size: 14px; }
.admin-mark-part .t { height: 5px; border-radius: 3px; background: var(--sunk); overflow: hidden; }
.admin-mark-part .t i { display: block; height: 100%; background: var(--blue); border-radius: 3px; }
.admin-mark-part em {
  font-style: normal; font-size: 14px; font-weight: 600; text-align: right;
  font-variant-numeric: tabular-nums;
}
.admin-mark-part .w { grid-column: 1 / -1; font-size: 11.5px; color: var(--ink-3); margin-top: -4px; }
.admin-mark-say { margin-top: 14px; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }

.admin-books { display: flex; flex-direction: column; gap: 6px; margin: 14px 0; }
.admin-book {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 12px; border-radius: 10px; background: var(--canvas); text-align: left;
  transition: background .15s var(--ease);
}
.admin-book:hover { background: var(--sunk); }
.admin-book b { font-size: 13.5px; font-weight: 500; }
.admin-book .mk { display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; color: var(--ink-2); }
.admin-book .mk em {
  font-style: normal; font-family: var(--font); font-size: 16px; font-weight: 600;
  color: var(--ink); letter-spacing: -.02em;
}
.admin-book .mk.none { color: var(--ink-3); }

/* ----------------------------------------------------------- Pick lists */
.admin-picklist { margin: 18px 0 22px; }
.admin-pick {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 4px; border-bottom: 1px solid var(--hair); cursor: pointer;
}
.admin-pick input { width: 17px; height: 17px; accent-color: var(--blue); flex: none; }
.admin-pick .t { display: flex; flex-direction: column; gap: 1px; }
.admin-pick .t b { font-size: 14.5px; font-weight: 500; }
.admin-pick .t > span { font-size: 12.5px; color: var(--ink-3); }

/* --------------------------------------------------------------- Notices */
.admin-warn {
  background: #fff8ea; border-radius: var(--r); padding: 20px 22px;
  box-shadow: 0 0 0 .5px #f0dfba; margin-bottom: 30px;
}
.admin-warn b { display: block; font-size: 15px; margin-bottom: 8px; }
.admin-warn p { font-size: 13.5px; color: #6b5424; line-height: 1.5; }
.admin-warn p + p { margin-top: 10px; }
.admin-warn code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px;
  background: rgba(0,0,0,.05); padding: 1px 5px; border-radius: 4px;
}

/* ------------------------------------------------- A student's own grades */
.ac-grades { margin-top: 14px; }
.ac-grade {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 13px 0; border-bottom: 1px solid var(--hair);
}
.ac-grade .t b { display: block; font-size: 15px; font-weight: 500; }
.ac-grade .t span { font-size: 12.5px; color: var(--ink-3); }
.ac-grade .mk { display: flex; align-items: baseline; gap: 8px; }
.ac-grade .mk b {
  font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.03em;
}
.ac-grade .mk span { font-size: 13px; color: var(--ink-2); }

/* --------------------------------------------------- Console: async states
   Every screen in the console waits on a network call, so the three states a
   network call actually has get drawn rather than assumed. A spinner that
   never resolves into an error is how a broken backend looks like a broken
   app. */
.admin-loading, .ac-loading {
  padding: 22px 0; font-size: 14px; color: var(--ink-3);
}
.admin-failed {
  background: #fdf3f3; border-radius: var(--r); padding: 20px 22px;
  box-shadow: 0 0 0 .5px #f0cfcf; margin: 18px 0;
}
.admin-failed b { display: block; font-size: 15px; margin-bottom: 8px; color: #8a1420; }
.admin-failed p { font-size: 13.5px; color: #6f2b30; line-height: 1.5; margin-bottom: 14px; }

.admin-course { margin: 30px 0 40px; }
.admin-course-head { margin-bottom: 14px; }
.admin-course-head h2 {
  font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.025em;
}
.admin-course-head span { font-size: 12.5px; color: var(--ink-3); }

.admin-cellname { font-size: 14.5px; }
.admin-cellcat, .admin-cellout { font-size: 13px; color: var(--ink-3); }
.admin-cellstate { font-size: 11.5px; color: var(--ink-3); text-align: right; }
.admin-cellstate.ok { color: var(--green); }
.admin-cellstate.bad { color: var(--red); }
.admin-cellstate.busy { color: var(--ink-3); }

/* The System tab: what is real, and where the line is. */
.admin-sys { margin: 20px 0 30px; }
.admin-sys-row {
  display: grid; grid-template-columns: 150px 160px 1fr; gap: 14px;
  padding: 13px 0; border-bottom: 1px solid var(--hair); align-items: baseline;
}
@media (max-width: 720px) { .admin-sys-row { grid-template-columns: 1fr; gap: 3px; } }
.admin-sys-row b { font-size: 14px; font-weight: 500; }
.admin-sys-row em {
  font-style: normal; font-size: 12.5px; color: var(--blue); font-weight: 500;
}
.admin-sys-row span { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }

.ld-sheet .err code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
  background: rgba(0,0,0,.05); padding: 1px 5px; border-radius: 4px;
}

/* The term editor: four columns, because a term's optional fields are what
   decide how hard a question can be asked about it, and hiding them behind a
   disclosure means nobody ever fills them in. */
.admin-table.terms .admin-tr {
  grid-template-columns: 0.9fr 1.5fr 1.2fr 1.2fr 34px;
  align-items: start;
}
@media (max-width: 1040px) {
  .cn-row { grid-template-columns: minmax(0, 1fr) 120px 150px; }
}
@media (max-width: 900px) {
  .admin-table.terms .admin-tr { grid-template-columns: 1fr; }
}
.admin-depth {
  font-size: 12.5px; color: var(--ink-2); margin: 14px 0 4px;
  padding: 9px 13px; background: var(--sunk); border-radius: 9px; display: inline-block;
}

/* A study set a teacher gave you, on the home screen. Distinct from a course
   card because it is a smaller commitment — twenty minutes, not a term. */
.lx-setcard {
  display: flex; flex-direction: column; gap: 8px; text-align: left;
  padding: 20px; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair);
  transition: box-shadow .18s var(--ease), transform .12s var(--ease);
}
.lx-setcard:hover {
  box-shadow: 0 0 0 .5px var(--rule), 0 6px 22px rgba(0,0,0,.07);
  transform: translateY(-1px);
}
.lx-setcard .ic {
  width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center;
  background: var(--sunk); color: var(--ink-2);
}
.lx-setcard .ic svg { width: 18px; height: 18px; }
.lx-setcard b { font-size: 16px; font-weight: 600; letter-spacing: -.02em; }
.lx-setcard span:last-child { font-size: 12.5px; color: var(--ink-3); }

/* ==========================================================================
   Grades.

   The one screen in Learn allowed to celebrate, because it is the one screen
   a student opens to see how far they have come rather than to work. Even
   here the charts stay quiet — thin marks, hairline grids, the data the only
   loud thing — and the celebrating is done by the numbers moving into place
   and the badges arriving, not by decoration.

   Colours are the reference data palette, checked against this card surface:
   blue for what transferred, orange for what is earned at EHS, the lighter
   blue step for credit that may not transfer. Text always wears text colours;
   a colour only ever sits on a mark or a key swatch beside a label.
   ========================================================================== */
.gr {
  --gr-blue: #2a78d6;        /* series 1: transferred */
  --gr-blue-soft: #86b6ef;   /* ordinal step: may not transfer */
  --gr-blue-track: #cde2fb;  /* the ring's own track */
  --gr-orange: #eb6834;      /* series 2: earned at EHS */
  --gr-grid: #e6e6e8;
  --gr-axis: #c3c2b7;
  --gr-good: #006300;
  --gr-good-fill: #0ca30c;
  --gr-bad: #d03b3b;
  --gr-warn: #8a5a00;
  --gr-warn-fill: #fab219;
  display: flex; flex-direction: column; gap: 34px; margin-top: 8px; padding-bottom: 60px;
}

/* ------------------------------------------------------------------ Hero */
.gr-hero {
  display: grid; grid-template-columns: auto 1fr; gap: 40px; align-items: center;
  padding: 32px 36px; border-radius: 22px; background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair), 0 10px 40px rgba(0,0,0,.05);
}
@media (max-width: 760px) { .gr-hero { grid-template-columns: 1fr; padding: 26px 22px; gap: 24px; justify-items: center; } }
.gr-ring-side { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.gr-ring { position: relative; width: 196px; height: 196px; }
.gr-ring svg { width: 100%; height: 100%; }
.gr-ring-track { fill: none; stroke: var(--gr-blue-track); stroke-width: 14; }
.gr-arc { fill: none; stroke-width: 14; transition: stroke-dasharray 1.1s var(--ease); }
.gr-arc.sure { stroke: var(--gr-blue); }
.gr-arc.maybe { stroke: var(--gr-blue-soft); }
.gr-ring-mid {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
}
.gr-ring-mid b {
  font-family: var(--font); font-size: 48px; font-weight: 600; letter-spacing: -.04em; line-height: 1;
}
.gr-ring-mid span { font-size: 12px; color: var(--ink-3); margin-top: 6px; }

.gr-key { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12px; color: var(--ink-2); }
.gr-key span { display: inline-flex; align-items: center; gap: 6px; }
.gr-key i { width: 12px; height: 8px; border-radius: 2px; display: inline-block; }
.gr-key i.t { background: var(--gr-blue); }
.gr-key i.maybe { background: var(--gr-blue-soft); }
.gr-key i.e { background: var(--gr-orange); }
.gr-key i.left { background: var(--sunk); box-shadow: inset 0 0 0 .5px var(--rule); }
.gr-ring-side .gr-key { justify-content: center; max-width: 220px; }

.gr-hero-txt { min-width: 0; }
.gr-kicker {
  font-size: 11px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 10px;
}
.gr-hero-txt h2 {
  font-family: var(--font); font-size: clamp(24px, 3.4vw, 32px); font-weight: 600;
  letter-spacing: -.03em; line-height: 1.15;
}
.gr-lede { margin-top: 10px; font-size: 15px; color: var(--ink-2); line-height: 1.5; }
.gr-lede b { color: var(--ink); font-weight: 600; }
.gr-togo {
  display: inline-flex; align-items: baseline; gap: 10px; margin-top: 18px;
  padding: 10px 16px; border-radius: 12px; background: var(--canvas);
}
.gr-togo b { font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: -.03em; }
.gr-togo span { font-size: 13px; color: var(--ink-2); }

/* The milestone track: a line that fills to where you are, four stops on it. */
.gr-miles {
  position: relative; display: grid; grid-template-columns: repeat(4, 1fr);
  margin-top: 26px; padding-top: 4px;
}
.gr-miles::before, .gr-miles::after {
  content: ""; position: absolute; top: 13px; left: 12.5%; height: 3px; border-radius: 2px;
}
.gr-miles::before { right: 12.5%; background: var(--sunk); }
.gr-miles::after { width: var(--gr-fill, 0%); background: var(--gr-blue); }
.gr-miles li { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.gr-miles i {
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper); box-shadow: 0 0 0 2px var(--rule);
}
.gr-miles i svg { width: 13px; height: 13px; color: #fff; }
.gr-miles li.done i { background: var(--gr-blue); box-shadow: 0 0 0 3px var(--paper); }
.gr-miles li.next i { box-shadow: 0 0 0 2px var(--gr-blue); animation: gr-beat 2.2s ease-in-out infinite; }
.gr-miles span { font-size: 12.5px; font-weight: 500; }
.gr-miles em { font-style: normal; font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.gr-miles li:not(.done):not(.next) span { color: var(--ink-3); }
@keyframes gr-beat {
  0%, 100% { box-shadow: 0 0 0 2px var(--gr-blue), 0 0 0 0 rgba(42,120,214,.35); }
  50% { box-shadow: 0 0 0 2px var(--gr-blue), 0 0 0 7px rgba(42,120,214,0); }
}
.gr-next {
  display: flex; align-items: center; gap: 10px; margin-top: 20px;
  font-size: 14px; color: var(--ink-2);
}
.gr-next svg { width: 18px; height: 18px; color: var(--amber); flex: none; }
.gr-next b { color: var(--ink); font-weight: 600; }

/* -------------------------------------------------------------- KPI row */
.gr-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
@media (max-width: 820px) { .gr-kpis { grid-template-columns: repeat(2, 1fr); } }
.gr-kpi {
  display: flex; flex-direction: column; gap: 4px; padding: 18px 18px 16px;
  border-radius: var(--r); background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.gr-kpi b { font-family: var(--font); font-size: 30px; font-weight: 600; letter-spacing: -.03em; line-height: 1.1; }
.gr-kpi span { font-size: 13px; font-weight: 500; }
.gr-kpi em { font-style: normal; font-size: 12px; color: var(--ink-3); line-height: 1.4; }

/* -------------------------------------------------------------- Sections */
.gr-sec { display: flex; flex-direction: column; gap: 16px; }
.gr-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.gr-sec-head h2 { font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.025em; }
.gr-sec-head span { font-size: 13px; color: var(--ink-3); }
.gr-card {
  padding: 20px 22px; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); min-width: 0;
}
.gr-card h3 { font-size: 15px; font-weight: 600; letter-spacing: -.015em; }
.gr-sub { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
.gr-note { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; margin-top: 12px; }
.gr-two { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.gr-two.wide { grid-template-columns: 1.45fr 1fr; }
@media (max-width: 820px) { .gr-two, .gr-two.wide { grid-template-columns: 1fr; } }
.gr-stack { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* ---------------------------------------------------------------- Badges */
.gr-badges { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }

/* ------------------------------------------------------------- The one move
   Given the weight of a decision rather than an alert: one accent rule, no
   filled panel. A page that shouts at a student about their diploma is a page
   they stop opening. */
.gr-focus {
  padding: 22px 24px; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); border-left: 3px solid var(--blue);
}
.gr-focus-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.gr-focus h2 { font-family: var(--font); font-size: 24px; letter-spacing: -.01em; line-height: 1.2; }
.gr-effort { text-align: right; white-space: nowrap; }
.gr-effort b { display: block; font-size: 14px; color: var(--ink); }
.gr-effort em {
  font-style: normal; font-size: 10.5px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.gr-why {
  margin-top: 12px; padding-left: 12px; border-left: 2px solid var(--hair);
  font-size: 13.5px; color: var(--ink-2); line-height: 1.55;
}

/* The commitment. Sunk into the card, because it is the student's half of it. */
.gr-commit { margin-top: 18px; padding: 16px 18px; border-radius: 12px; background: var(--canvas); }
.gr-plan-said { font-size: 16px; color: var(--ink); line-height: 1.45; font-weight: 500; }
.gr-commit-acts { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.gr-plan-form { margin-top: 4px; }
.gr-plan-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.gr-plan-line span { font-size: 13.5px; color: var(--ink-2); }
.gr-plan-line input {
  flex: 1 1 180px; min-width: 140px; padding: 9px 12px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--paper); border: none; border-radius: 10px;
  box-shadow: 0 0 0 .5px var(--rule); transition: box-shadow .15s var(--ease);
}
.gr-plan-line input:focus { outline: none; box-shadow: 0 0 0 2px var(--blue); }

/* ------------------------------------------------------------ When it ends */
.gr-plan-big { display: flex; align-items: baseline; gap: 10px; }
.gr-plan-big b { font-family: var(--font); font-size: 32px; letter-spacing: -.02em; }
.gr-plan-big span { font-size: 13px; color: var(--ink-3); }

/* ------------------------------------------------------------------- Risk
   Amber, once, on the rule — never a red panel. This names where an hour is
   worth the most, and a student should be able to read it on a bad day. */
.gr-risk {
  padding: 20px 22px; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); border-left: 3px solid var(--amber);
}
.gr-risk h3 { font-family: var(--font); font-size: 19px; letter-spacing: -.01em; }
.gr-evidence { margin: 12px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.gr-evidence li {
  position: relative; padding-left: 16px; font-size: 13.5px; color: var(--ink-2); line-height: 1.5;
}
.gr-evidence li::before { content: "—"; position: absolute; left: 0; color: var(--ink-3); }

/* --------------------------------------------------------- The exam board */
.gr-core { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.gr-core-cell {
  padding: 14px 16px; border-radius: 12px; background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); border-top: 2px solid var(--rule);
  display: flex; flex-direction: column; gap: 2px;
}
.gr-core-cell b { font-size: 13px; color: var(--ink); }
.gr-core-cell .sc { font-family: var(--font); font-size: 26px; letter-spacing: -.02em; line-height: 1.1; }
.gr-core-cell em { font-style: normal; font-size: 12px; color: var(--ink-2); }
.gr-core-cell i { font-style: normal; font-size: 11px; color: var(--ink-3); }
.gr-core-cell.met { border-top-color: var(--green); }
.gr-core-cell.met em { color: var(--green); }
.gr-core-cell.low_pass { border-top-color: var(--amber); }
.gr-core-cell.low_pass em { color: var(--amber); }
.gr-core-cell.short { border-top-color: var(--red); }
.gr-core-cell.short em { color: var(--red); }
.gr-core-cell.none .sc { color: var(--ink-3); }

.gr-paths { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; }
.gr-path {
  padding: 18px 20px; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair);
}
.gr-path h4 { display: flex; align-items: center; gap: 7px; font-size: 15px; font-weight: 600; }
.gr-path h4 svg { width: 15px; height: 15px; color: var(--green); flex: none; }
.gr-path.met { box-shadow: 0 0 0 1px var(--green); }
.gr-near {
  display: flex; gap: 12px; align-items: flex-start; padding: 16px 18px;
  border-radius: 12px; background: var(--canvas);
}
.gr-near .ic svg { width: 18px; height: 18px; color: var(--amber); }
.gr-near b { font-size: 15px; }
.gr-near p { margin-top: 3px; font-size: 13.5px; color: var(--ink-2); line-height: 1.5; }

@media (max-width: 720px) {
  .gr-focus h2 { font-size: 21px; }
  .gr-focus-head { flex-direction: column; gap: 4px; }
  .gr-effort { text-align: left; }
}
.gr-badge {
  display: flex; gap: 12px; align-items: flex-start; padding: 14px 15px;
  border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.gr-badge .ic {
  flex: none; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
}
.gr-badge .ic svg { width: 19px; height: 19px; }
.gr-badge.earned .ic { background: linear-gradient(160deg, #ffcf4d, #e8a317); color: #fff; }
.gr-badge.locked .ic { background: var(--sunk); color: var(--ink-3); }
.gr-badge b { display: block; font-size: 14px; font-weight: 600; letter-spacing: -.015em; }
.gr-badge p { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; margin-top: 2px; }
.gr-badge.locked b { color: var(--ink-2); }
.gr-badge.locked p { color: var(--ink-3); }
.gr-badge.earned { animation: gr-pop .55s var(--ease) both; }
@keyframes gr-pop {
  from { opacity: 0; transform: translateY(8px) scale(.96); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------- Requirements */
.gr-areas {
  display: flex; flex-direction: column; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); padding: 10px 26px; position: relative;
}
.gr-area {
  display: grid; grid-template-columns: 220px 1fr 190px; gap: 24px; align-items: center;
  padding: 18px 0; border-bottom: 1px solid var(--hair);
}
.gr-area:last-child { border-bottom: 0; }
@media (max-width: 720px) { .gr-area { grid-template-columns: 1fr; gap: 8px; } }
.gr-area-name { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.gr-area-name b { font-size: 14.5px; font-weight: 500; }
.gr-area-name span { font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.gr-meter { display: flex; gap: 2px; height: 10px; border-radius: 3px; background: var(--sunk); overflow: hidden; }
.gr-meter .seg { height: 100%; transform-origin: left; animation: gr-grow .9s var(--ease) both; }
.gr-meter .seg.t { background: var(--gr-blue); }
.gr-meter .seg.e { background: var(--gr-orange); }
.gr-meter .seg.end { border-radius: 0 4px 4px 0; }
@keyframes gr-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.gr-area-state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; font-size: 13px; color: var(--ink-2); }
.gr-area-state b { font-weight: 600; color: var(--ink); }
.gr-area-state em { font-style: normal; font-size: 11.5px; color: var(--ink-3); }
.gr-area-state .ok { display: inline-flex; align-items: center; gap: 5px; color: var(--gr-good); font-weight: 600; }
.gr-area-state .ok svg { width: 14px; height: 14px; }

/* -------------------------------------------------------------- Transfer */
.gr-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
@media (max-width: 720px) { .gr-steps { grid-template-columns: 1fr 1fr; } }
.gr-steps li {
  display: flex; flex-direction: column; gap: 8px; padding: 14px; border-radius: 14px;
  background: var(--paper); box-shadow: 0 0 0 .5px var(--hair); font-size: 13px; color: var(--ink-3);
}
.gr-steps i {
  width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  font-style: normal; font-size: 12px; font-weight: 600; background: var(--sunk); color: var(--ink-3);
}
.gr-steps i svg { width: 13px; height: 13px; }
.gr-steps li.done { color: var(--ink-2); }
.gr-steps li.done i { background: var(--gr-blue); color: #fff; }
.gr-steps li.now { color: var(--ink); box-shadow: 0 0 0 1.5px var(--gr-blue); }
.gr-steps li.now i { background: var(--ink); color: #fff; }
.gr-steps li span { font-weight: 500; line-height: 1.35; }
.gr-steps em { font-style: normal; font-size: 11px; font-weight: 600; color: var(--gr-blue); text-transform: uppercase; letter-spacing: .06em; }
.gr-range { margin-top: 10px; font-size: 14px; color: var(--ink-2); }
.gr-range b { font-family: var(--font); font-size: 30px; font-weight: 600; letter-spacing: -.03em; color: var(--ink); margin-right: 4px; }
.gr-act { background: linear-gradient(180deg, #f3f8ff, #fff); box-shadow: 0 0 0 .5px #cfe0f6; }
.gr-act h3 { font-size: 16px; margin-bottom: 6px; line-height: 1.35; }
.gr-act p:last-child { font-size: 13px; color: var(--ink-2); line-height: 1.5; }
.gr-review { display: flex; flex-direction: column; gap: 8px; }
.gr-review h3 { font-size: 14px; font-weight: 600; }
.gr-review-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: start;
  padding: 12px 14px; border-radius: 12px; background: #fffaf0; box-shadow: 0 0 0 .5px #f0dfba;
}
.gr-review-row .ic svg { width: 17px; height: 17px; color: var(--gr-warn); margin-top: 1px; }
.gr-review-row b { font-size: 13.5px; font-weight: 600; }
.gr-review-row p { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; margin-top: 2px; }
.gr-review-row em { font-style: normal; font-size: 12px; font-weight: 600; color: var(--gr-warn); white-space: nowrap; }

/* ----------------------------------------------------------------- Charts */
.gr-plot { position: relative; margin-top: 12px; }
.gr-plot svg { width: 100%; height: auto; display: block; overflow: visible; }
.gr-plot svg:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 6px; }
.gr-grid { stroke: var(--gr-grid); stroke-width: 1; }
.gr-ref { stroke: var(--gr-axis); stroke-width: 1; }
.gr-base { stroke: var(--gr-axis); stroke-width: 1; }
.gr-tick { font-size: 11px; fill: #898781; font-variant-numeric: tabular-nums; }
.gr-line { fill: none; stroke: var(--gr-blue); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.gr-area-fill { fill: var(--gr-blue); opacity: .1; }
.gr-dot { fill: var(--gr-blue); stroke: var(--paper); stroke-width: 2; }
.gr-endlabel { font-size: 12px; font-weight: 600; fill: var(--ink); }
.gr-cross { stroke: var(--ink-3); stroke-width: 1; }
/* The tooltip floats over the chart it belongs to, so it is above everything
   drawn there — without a z-index the chips painted after it covered it — and
   it sits clear of the thing it describes, above by default and below when
   there is no room above (.under, set in app.js). */
.gr-tip {
  position: absolute; z-index: 30; transform: translate(-50%, calc(-100% - 14px)); pointer-events: none;
  display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 10px 14px;
  border-radius: 12px; background: var(--ink); color: #fff; white-space: nowrap;
  box-shadow: 0 10px 30px rgba(0,0,0,.28);
}
.gr-tip.under { transform: translate(-50%, 14px); }
.gr-tip b { font-size: 14px; font-weight: 600; }
.gr-tip span { font-size: 11.5px; line-height: 1.35; color: rgba(255,255,255,.76); }
.gr-bar { fill: var(--gr-blue); transition: opacity .15s var(--ease); }
.gr-col:hover .gr-bar { opacity: .82; }
.gr-val { font-size: 12px; font-weight: 600; fill: var(--ink); }
.gr-card > svg { width: 100%; height: auto; display: block; margin-top: 10px; }
.gr-gpa { margin-top: 10px; font-size: 13px; color: var(--ink-2); }
.gr-gpa b { font-family: var(--font); font-size: 22px; font-weight: 600; color: var(--ink); letter-spacing: -.02em; margin-right: 4px; }
.gr-table { margin-top: 12px; font-size: 12.5px; }
.gr-table summary { cursor: pointer; color: var(--ink-2); }
.gr-table table { width: 100%; border-collapse: collapse; margin-top: 8px; }
.gr-table th, .gr-table td { text-align: left; padding: 6px 4px; border-bottom: 1px solid var(--hair); font-variant-numeric: tabular-nums; }
.gr-table th { font-weight: 600; color: var(--ink-3); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }

.gr-hbars { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.gr-hbar { display: grid; grid-template-columns: 118px 1fr 38px; gap: 10px; align-items: center; font-size: 13px; }
.gr-hbar .trk { height: 10px; border-radius: 3px; background: var(--sunk); overflow: hidden; }
.gr-hbar .trk i { display: block; height: 100%; background: var(--gr-blue); border-radius: 0 4px 4px 0; transform-origin: left; animation: gr-grow .9s var(--ease) both; }
.gr-hbar b { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ State exams */
.gr-exams {
  display: flex; flex-direction: column; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); padding: 4px 22px;
}
.gr-exam {
  display: grid; grid-template-columns: 1.3fr 1fr 112px; gap: 18px; align-items: center;
  padding: 12px 0; border-bottom: 1px solid var(--hair);
}
.gr-exam .chip { justify-self: end; }
.gr-exam:last-child { border-bottom: 0; }
@media (max-width: 640px) { .gr-exam { grid-template-columns: 1fr; gap: 6px; } }
.gr-exam .n b { display: block; font-size: 14px; font-weight: 500; }
.gr-exam .n span { font-size: 12px; color: var(--ink-3); }
.gr-exam .sc { display: grid; grid-template-columns: 1fr 34px; gap: 10px; align-items: center; }
.gr-exam .trk { position: relative; height: 8px; border-radius: 3px; background: var(--sunk); }
.gr-exam .trk i { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--gr-blue); }
.gr-exam .trk u { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--ink); border-radius: 1px; }
.gr-exam .sc b { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px 4px 8px;
  border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap; background: var(--sunk);
}
.chip svg { width: 13px; height: 13px; }
.chip.ok { color: var(--gr-good); background: #e7f5e7; }
.chip.bad { color: #a3262a; background: #fdecec; }
.chip.warn { color: var(--gr-warn); background: #fff4dc; }
.chip.muted { color: var(--ink-3); }

/* ------------------------------------------------------ This year at EHS */
.gr-current { display: flex; flex-direction: column; gap: 8px; }
.gr-cur {
  display: grid; grid-template-columns: 1fr auto auto; gap: 16px; align-items: center;
  padding: 14px 18px; border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.gr-cur b { display: block; font-size: 15px; font-weight: 500; }
.gr-cur div span { font-size: 12px; color: var(--ink-3); }
.gr-cur .let { font-family: var(--font); font-size: 24px; font-weight: 600; letter-spacing: -.02em; }
.gr-cur strong { font-size: 14px; color: var(--ink-2); font-weight: 500; font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------- Course history */
.gr-year { border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair); overflow: hidden; }
.gr-year summary {
  display: flex; justify-content: space-between; gap: 16px; padding: 15px 20px; cursor: pointer;
  list-style: none;
}
.gr-year summary::-webkit-details-marker { display: none; }
.gr-year summary b { font-size: 15px; font-weight: 600; }
.gr-year summary span { font-size: 12.5px; color: var(--ink-3); }
.gr-year[open] summary { border-bottom: 1px solid var(--hair); }
.gr-term { padding: 12px 20px 8px; }
.gr-term h4 { font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
.gr-crs {
  display: grid; grid-template-columns: 1fr 58px 26px 52px minmax(0, 150px); gap: 10px; align-items: center;
  padding: 7px 0; border-bottom: 1px solid var(--hair); font-size: 13.5px;
}
.gr-term .gr-crs:last-child { border-bottom: 0; }
@media (max-width: 640px) { .gr-crs { grid-template-columns: 1fr auto auto; } .gr-crs .fl, .gr-crs .cr { display: none; } }
.gr-crs .mk { color: var(--ink-2); font-variant-numeric: tabular-nums; text-align: right; }
.gr-crs .let { font-weight: 600; text-align: center; }
.gr-crs .cr { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; text-align: right; }
.gr-crs .fl { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.gr-crs .fl em {
  display: inline-flex; align-items: center; gap: 3px; font-style: normal; font-size: 10.5px; font-weight: 600;
  padding: 2px 7px; border-radius: 999px; background: var(--sunk); color: var(--ink-2); white-space: nowrap;
}
.gr-crs .fl em svg { width: 10px; height: 10px; }
.gr-crs .fl em.rec { background: #e7f5e7; color: var(--gr-good); }
.gr-crs .fl em.no { background: #fdecec; color: #a3262a; }
.gr-crs.miss .t { color: var(--ink-2); }

/* ------------------------------------------------------------------ Notes */
.gr-notes { padding: 18px 22px; border-radius: var(--r); background: var(--canvas); box-shadow: inset 0 0 0 .5px var(--hair); }
.gr-notes h3 { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.gr-notes ul { display: flex; flex-direction: column; gap: 6px; padding-left: 16px; list-style: disc; }
.gr-notes li { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }

/* ============================================================ Grades · the record
   The pieces an enrolled student's record needs and an applicant's did not:
   credit that stays where it was earned, a map of every credit, two schools
   on one timeline, every mark as a dot, and the record checked against itself.

   Two series colours carry identity everywhere on this page — blue for what
   was transferred, orange for what was earned at EHS — validated as a pair
   for colour-blind separation. Extra credit is grey on purpose: it is real,
   and it fills nothing, and a colour would suggest otherwise. Identity is
   never colour alone: every mark has a label, a tooltip or a table row. */
.gr { --gr-extra: #8f8e86; }
/* What the ring leaves open is "not yet earned", and it is the same grey as
   "still to earn" everywhere else on the page rather than a tint of a series. */
.gr-ring-track { stroke: var(--sunk); }
.gr-arc.t { stroke: var(--gr-blue); }
.gr-arc.e { stroke: var(--gr-orange); }
.gr-arc.x { stroke: var(--gr-extra); }
.gr-key i.x { background: var(--gr-extra); }
.gr-key i.cap { background: var(--rule); }
.gr-key i.line { width: 2px; height: 13px; border-radius: 1px; background: var(--ink); }
.gr-key i.dot { width: 9px; height: 9px; border-radius: 50%; }

.gr-facts { display: flex; flex-wrap: wrap; gap: 10px 28px; margin-top: 18px; }
.gr-facts div { display: flex; flex-direction: column; gap: 2px; }
.gr-facts dt {
  font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em;
}
.gr-facts dd { margin: 0; font-family: var(--font); font-size: 19px; font-weight: 600; letter-spacing: -.02em; }

.gr-table-scroll { overflow-x: auto; }

/* ------------------------------------------------------------- Credit map */
.gcm { position: relative; padding: 20px 24px 18px; }
.gcm > .gr-key { margin-bottom: 12px; }
.gcm-rows { display: flex; flex-direction: column; }
.gcm-group { padding: 2px 0; border-top: 1px solid var(--hair); }
.gcm-group:first-child { border-top: 0; }
.gcm-group.multi { padding-top: 12px; }
.gcm-grouphead { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.gcm-grouphead b { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.gcm-grouphead span { font-size: 12px; color: var(--ink-3); }
.gcm-row { display: grid; grid-template-columns: 208px 1fr 150px; gap: 16px; align-items: center; padding: 9px 0; }
.gcm-group.multi .gcm-row { padding: 6px 0; }
.gcm-name { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-width: 0; }
.gcm-name b { font-size: 14px; font-weight: 500; white-space: nowrap; }
.gcm-group.multi .gcm-name b { font-weight: 400; color: var(--ink-2); padding-left: 10px; }
.gcm-name span { font-size: 12.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.gcm-track { position: relative; height: 28px; }
.gcm-bed {
  position: absolute; left: 0; top: 0; bottom: 0; border-radius: 5px; background-color: var(--sunk);
  background-image: linear-gradient(90deg, transparent calc(100% - 1px), rgba(0,0,0,.08) calc(100% - 1px));
  background-repeat: repeat-x;
}
.gcm-line {
  position: absolute; top: -5px; bottom: -5px; width: 2px; margin-left: -1px; border-radius: 1px;
  background: var(--ink); pointer-events: none; z-index: 2;
}
.gcm-seg {
  position: absolute; top: 0; bottom: 0; padding: 0; border: 0; border-radius: 4px; cursor: default;
  display: grid; place-items: center; font: inherit; font-size: 11.5px; font-weight: 600;
  transform-origin: left; animation: gr-grow .8s var(--ease) both;
}
.gcm-seg span { pointer-events: none; line-height: 1; }
.gcm-seg.t { background: var(--gr-blue); color: #fff; }
.gcm-seg.e { background: var(--gr-orange); color: var(--ink); }
.gcm-seg.x { background: var(--gr-extra); color: var(--ink); }
.gcm-seg.cap { background: var(--rule); color: var(--ink-2); }
.gcm-seg:hover { filter: brightness(1.07); }
.gcm-seg:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; z-index: 3; }
.gcm-state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; font-size: 13px; color: var(--ink-2); }
.gcm-state b { font-family: var(--font); font-size: 17px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.gcm-state em { font-style: normal; font-size: 12px; color: var(--ink-3); }
.gcm-state em.warn { color: var(--gr-warn); }
.gcm-state .ok { display: inline-flex; align-items: center; gap: 5px; color: var(--gr-good); font-weight: 600; }
.gcm-state .ok svg { width: 14px; height: 14px; }
/* On a phone each requirement stacks: its name, its credits, then what is
   left — three lines rather than three columns fighting for one. */
@media (max-width: 720px) {
  .gcm { padding: 18px 16px; }
  .gcm-row { grid-template-columns: 1fr; gap: 7px; padding: 12px 0; }
  .gcm-track { order: 2; }
  .gcm-state { order: 3; }
  .gcm-group.multi .gcm-name b { padding-left: 0; }
}

/* --------------------------------------------------------- Year by year */
.gj-schools { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 10px; }
.gj-school {
  display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px;
  border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.gj-school i { flex: none; width: 10px; height: 10px; border-radius: 50%; margin-top: 6px; }
.gj-school i.t { background: var(--gr-blue); }
.gj-school i.e { background: var(--gr-orange); }
.gj-school b { display: block; font-size: 14.5px; font-weight: 600; }
.gj-school span { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }
.gj-bar.t { fill: var(--gr-blue); }
.gj-bar.e { fill: var(--gr-orange); }
.gj-none { font-size: 11px; fill: var(--ink-3); font-style: italic; }
.gj-join { stroke: var(--ink-3); stroke-width: 1; }
.gj-joinlabel { font-size: 10.5px; font-weight: 600; fill: var(--ink-2); }
.gj-line { stroke: var(--ink-3); stroke-width: 2; stroke-linecap: round; }
.gj-bridge { stroke: var(--rule); stroke-width: 1; }
.gj-dot { stroke: var(--paper); stroke-width: 2; }
.gj-dot.t, .gk-dot.t { fill: var(--gr-blue); }
.gj-dot.e, .gk-dot.e { fill: var(--gr-orange); }
.gj-band { font-size: 10.5px; font-weight: 600; fill: var(--ink-3); }
.gr-col, .gj-pt, .gk-pt { outline: none; }
.gr-col:hover .gj-bar { opacity: .85; }
.gj-pt:hover .gj-dot, .gk-pt:hover .gk-dot { stroke: var(--ink); }

/* -------------------------------------------------------------- The marks */
.gk-key { margin-top: 10px; }
.gk-band { fill: transparent; }
.gk-band.alt { fill: #f6f6f4; }
.gk-letter { font-size: 11px; font-weight: 600; fill: var(--ink-3); }
.gk-dot { stroke: var(--paper); stroke-width: 2; }
.gk-label {
  font-size: 11px; font-weight: 600; fill: var(--ink);
  paint-order: stroke; stroke: var(--paper); stroke-width: 3px; stroke-linejoin: round;
}
.gk-gpa { display: flex; align-items: baseline; gap: 10px; margin-top: 6px; }
.gk-gpa b { font-family: var(--font); font-size: 48px; font-weight: 600; letter-spacing: -.04em; line-height: 1; }
.gk-gpa span { font-size: 13px; color: var(--ink-3); }
.gk-verdict { margin-top: 12px; }
.gk-distlabel { margin-top: 16px; }

/* ---------------------------------------------------------------- Gaps */
.gr-gaps { display: flex; flex-direction: column; gap: 14px; margin-top: 12px; }
.gr-gap { padding-top: 14px; border-top: 1px solid var(--hair); }
.gr-gap:first-child { padding-top: 0; border-top: 0; }
.gr-gap-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.gr-gap-head b { font-size: 15px; font-weight: 600; }
.gr-gap-head span { font-size: 13px; color: var(--ink-2); }
.gr-gap-head strong { font-family: var(--font); font-size: 19px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.gr-gap p { display: flex; gap: 8px; align-items: baseline; font-size: 13px; color: var(--ink-2); line-height: 1.5; margin-top: 6px; }
.gr-gap p em {
  flex: none; font-style: normal; font-size: 10.5px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.gr-gap-on span { color: var(--ink); font-weight: 500; }

/* -------------------------------------------------------------- Checks */
.gr-checks {
  display: flex; flex-direction: column; border-radius: var(--r); background: var(--paper);
  box-shadow: 0 0 0 .5px var(--hair); padding: 4px 22px;
}
.gr-check { display: grid; grid-template-columns: auto 1fr; gap: 14px; padding: 15px 0; border-bottom: 1px solid var(--hair); }
.gr-check:last-child { border-bottom: 0; }
.gr-check .ic { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; background: var(--sunk); color: var(--ink-2); }
.gr-check .ic svg { width: 16px; height: 16px; }
.gr-check.ok .ic { background: #e7f5e7; color: var(--gr-good); }
.gr-check.check .ic { background: #fff4dc; color: var(--gr-warn); }
.gr-check em {
  display: block; font-style: normal; font-size: 10.5px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
.gr-check.ok em { color: var(--gr-good); }
.gr-check.check em { color: var(--gr-warn); }
.gr-check b { display: block; font-size: 14.5px; font-weight: 600; margin-top: 2px; letter-spacing: -.01em; }
.gr-check p { font-size: 13px; color: var(--ink-2); line-height: 1.55; margin-top: 3px; }

/* ------------------------------------------------------- Earlier state tests */
.gs-scroll { overflow-x: auto; margin-top: 12px; }
.gs table { width: 100%; min-width: 580px; border-collapse: collapse; font-size: 13px; }
.gs th {
  text-align: left; font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; padding: 8px 8px; border-bottom: 1px solid var(--hair);
}
.gs td { padding: 9px 8px; border-bottom: 1px solid var(--hair); font-variant-numeric: tabular-nums; }
.gs tr:last-child td { border-bottom: 0; }
.gs .num { text-align: right; }
.gs tr.blank td { color: var(--ink-3); }
.gs tr.note td { color: var(--ink-3); font-style: italic; background: var(--canvas); }
.gs-lv { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.gs-lv i { display: inline-flex; gap: 2px; }
.gs-lv u { display: block; width: 6px; height: 11px; border-radius: 2px; background: var(--sunk); box-shadow: inset 0 0 0 .5px var(--rule); }
.gs-lv u.on { background: var(--ink-2); box-shadow: none; }

/* ------------------------------------------------------------ Course record */
.gr-rec { border-radius: 14px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair); overflow: hidden; }
.gr-rec summary {
  display: flex; align-items: baseline; gap: 12px; padding: 15px 20px; cursor: pointer; list-style: none;
}
.gr-rec summary::-webkit-details-marker { display: none; }
.gr-rec summary b { font-size: 12px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase; }
.gr-rec summary span { flex: 1; font-size: 12px; color: var(--ink-3); font-style: italic; }
.gr-rec summary strong { font-family: var(--font); font-size: 21px; font-weight: 600; letter-spacing: -.02em; }
.gr-rec summary strong small { font-size: 13px; font-weight: 500; color: var(--ink-3); letter-spacing: 0; }
.gr-rec[open] summary { box-shadow: inset 0 -1.5px 0 var(--ink); }
.gr-rec-scroll { overflow-x: auto; }
/* Fixed columns, so Credits, % and Grade sit on the same line in every
   subject's table and the eye can run straight down the page. */
.gr-rec table { width: 100%; min-width: 600px; border-collapse: collapse; font-size: 13.5px; table-layout: fixed; }
.gr-rec th:nth-child(1) { width: 76px; }
.gr-rec th:nth-child(2) { width: 104px; }
.gr-rec th:nth-child(3) { width: 128px; }
.gr-rec th:nth-child(5) { width: 76px; }
.gr-rec th:nth-child(6) { width: 70px; }
.gr-rec th:nth-child(7) { width: 78px; }
.gr-rec td.t { overflow-wrap: anywhere; }
.gr-rec th {
  text-align: left; font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; padding: 9px 10px; border-bottom: 1px solid var(--hair);
}
.gr-rec td { padding: 10px 10px; border-bottom: 1px solid var(--hair); font-variant-numeric: tabular-nums; vertical-align: baseline; }
.gr-rec th:first-child, .gr-rec td:first-child { padding-left: 20px; }
.gr-rec th:last-child, .gr-rec td:last-child { padding-right: 20px; }
.gr-rec .num { text-align: right; }
.gr-rec .let { text-align: center; font-weight: 600; }
.gr-rec td.code { font-size: 12.5px; color: var(--ink-3); white-space: nowrap; }
.gr-src { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; color: var(--ink-2); white-space: nowrap; }
.gr-src i { width: 8px; height: 8px; border-radius: 50%; }
.gr-src.t i { background: var(--gr-blue); }
.gr-src.e i { background: var(--gr-orange); }
.gr-flag {
  display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-style: normal;
  font-size: 10.5px; font-weight: 600; background: var(--sunk); color: var(--ink-2); vertical-align: 1px;
}
.gr-rec-foot {
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 11px 20px;
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.gr-rec-foot b { color: var(--ink); font-weight: 600; }
.gr-rec-foot em { font-style: normal; font-weight: 600; }
.gr-rec-foot em.ok { color: var(--gr-good); }
.gr-rec-foot em.left { color: var(--gr-warn); }

/* Motion is decoration here, so anybody who has asked for less gets none. */
@media (prefers-reduced-motion: reduce) {
  .gr *, .gr *::before, .gr *::after { animation: none !important; transition: none !important; }
}

/* ==========================================================================
   The class gradebook.

   A sheet: students down, work across. Everything in it is in service of one
   thing — a teacher reading a column of marks and typing the next one without
   ever losing which row they are on.

   That is why the name column and the header row are frozen rather than
   scrolled, why a cell is an input with no chrome until it is touched, and
   why there is exactly one colour in the whole grid. Marks are the content;
   anything else drawn at the same weight competes with them.
   ========================================================================== */

.gb-pick { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 20px; }
.gb-pickb {
  text-align: left; padding: 9px 14px; border-radius: 11px;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair);
  transition: box-shadow .16s var(--ease), background .16s var(--ease);
}
.gb-pickb b { display: block; font-size: 14px; font-weight: 500; letter-spacing: -.014em; }
.gb-pickb span { display: block; font-size: 11.5px; color: var(--ink-3); }
.gb-pickb:hover { box-shadow: inset 0 0 0 1px var(--rule); }
.gb-pickb.on { background: var(--ink); color: #fff; box-shadow: none; }
.gb-pickb.on span { color: rgba(255,255,255,.62); }

.gb-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-bottom: 14px;
}
.gb-title h2 { font-family: var(--font); font-size: 24px; font-weight: 600; letter-spacing: -.022em; }
.gb-title span { font-size: 13px; color: var(--ink-3); }
.gb-head .admin-acts { margin-top: 0; }

/* --------------------------------------------------------------- Needs you
   What is owed, and nothing else. Three at most: a list of everything that
   could be done is a list nobody reads twice. */
.gb-needs { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
.gb-need {
  display: flex; align-items: baseline; gap: 7px;
  padding: 8px 13px; border-radius: 11px; background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--hair);
  transition: box-shadow .16s var(--ease);
}
.gb-need:hover { box-shadow: inset 0 0 0 1px var(--rule); }
.gb-need b { font-family: var(--font); font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.gb-need span { font-size: 12.5px; color: var(--ink-2); }
.gb-need.late b { color: var(--amber); }
.gb-needs.clear b { font-size: 13px; font-weight: 500; color: var(--ink-3); }
.gb-needmore { font-size: 12.5px; color: var(--ink-3); }

/* ------------------------------------------------------------- The sheet */
.gb-scroll {
  overflow: auto; background: var(--paper); border-radius: var(--r);
  box-shadow: 0 0 0 .5px var(--hair);
  max-height: min(70vh, 720px);
  overscroll-behavior: contain;
}
/* Wide enough for its columns, and never narrower than the box it sits in —
   so a class with two pieces of work still fills the sheet, and one with
   twenty scrolls. The trailing `1fr` is where any slack goes; without it the
   last real column stretches and the grade drifts away from the marks it is
   made of. */
.gb { display: flex; flex-direction: column; width: max-content; min-width: 100%; }
.gb-r {
  display: grid;
  grid-template-columns: 210px repeat(var(--gb-cols), 88px) 96px 1fr;
  align-items: stretch;
  border-bottom: 1px solid var(--hair);
}
/* The slack at the right edge. It is a cell so the grid lines up, and it
   is drawn as nothing so it does not read as a column. */
.gb-c.fill { border-left: 0; }
.gb-r:last-child { border-bottom: 0; }
.gb-r.head {
  position: sticky; top: 0; z-index: 3;
  background: var(--paper); border-bottom: 1px solid var(--rule);
}
.gb-r.foot {
  position: sticky; bottom: 0; z-index: 2;
  background: var(--canvas); border-top: 1px solid var(--rule); border-bottom: 0;
}
.gb-r:not(.head):not(.foot):hover { background: #fafafc; }

.gb-c { min-width: 0; display: flex; align-items: center; }
.gb-c.name {
  position: sticky; left: 0; z-index: 2;
  gap: 9px; padding: 0 14px 0 16px; background: inherit;
  box-shadow: 1px 0 0 var(--hair);
  text-align: left;
}
.gb-r:not(.head):not(.foot) .gb-c.name { background: var(--paper); }
.gb-r:not(.head):not(.foot):hover .gb-c.name { background: #fafafc; }
.gb-r.head .gb-c.name, .gb-r.foot .gb-c.name { background: inherit; }
.gb-nm {
  font-size: 14px; letter-spacing: -.012em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gb-hn {
  font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em;
}
.gb-c.name .admin-av { width: 24px; height: 24px; font-size: 9.5px; flex: none; }

/* The column head. It is a button because a column is selectable — that is
   where the actions that apply to a whole piece of work live. */
.gb-c.col {
  position: relative; flex-direction: column; align-items: flex-start;
  justify-content: flex-end; gap: 1px; padding: 22px 9px 9px;
  border-left: 1px solid var(--hair); text-align: left;
  transition: background .14s var(--ease);
}
.gb-c.col b {
  display: block; width: 100%;
  font-size: 12px; font-weight: 600; letter-spacing: -.01em; line-height: 1.25;
  /* Two lines, then an ellipsis. A column is 88px wide and most titles are
     longer than that; truncating at one line loses the half that
     distinguishes "Unit 5 quiz" from "Unit 6 quiz". */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.gb-c.col span { font-size: 10.5px; color: var(--ink-3); white-space: nowrap; }
.gb-c.col:hover { background: var(--canvas); }
.gb-c.col.on { background: var(--canvas); box-shadow: inset 0 -2px 0 var(--ink); }
.gb-owed {
  position: absolute; top: 6px; left: 9px;
  font-style: normal; font-size: 9.5px; font-weight: 700; line-height: 1;
  padding: 3px 5px; border-radius: 999px;
  background: var(--sunk); color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.gb-owed.late { background: #fdf0dd; color: var(--amber); }

/* ---------------------------------------------------------------- A cell */
.gb-c.cell { position: relative; border-left: 1px solid var(--hair); padding: 0; }
.gb-c.cell input {
  width: 100%; height: 100%; min-height: 40px;
  border: 0; background: none; text-align: center;
  font-family: var(--text); font-size: 14.5px; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; color: var(--ink); padding: 0 4px;
}
.gb-c.cell input:focus {
  outline: none; background: var(--paper);
  box-shadow: inset 0 0 0 2px var(--blue); border-radius: 3px;
}
.gb-c.cell.miss input { color: var(--red); font-weight: 600; }
.gb-c.cell.exc input { color: var(--ink-3); font-style: italic; }
.gb-c.cell.blank.late { background: #fffaf1; }
/* A comment attached to the mark, shown as a corner rather than a badge: it
   is a fact about the cell, not a thing to click. */
.gb-c.cell.noted::after {
  content: ""; position: absolute; top: 3px; right: 3px;
  width: 0; height: 0; border-top: 5px solid var(--blue);
  border-left: 5px solid transparent; opacity: .7;
}
.gb-c.cell.busy input { color: var(--ink-3); }
.gb-c.cell.ok { animation: gbOk .9s var(--ease); }
.gb-c.cell.bad { background: #fdeced; }
@keyframes gbOk { 0% { background: #e7f5ec; } 100% { background: transparent; } }

.gb-c.grade {
  justify-content: flex-end; gap: 7px; padding: 0 16px 0 10px;
  border-left: 1px solid var(--hair);
}
.gb-c.grade b {
  font-family: var(--font); font-size: 15px; font-weight: 600; letter-spacing: -.02em;
}
.gb-c.grade span { font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.gb-c.grade.head { justify-content: flex-end; }
.gb-none { color: var(--ink-3); }
.gb-c.avg {
  justify-content: center; border-left: 1px solid var(--hair);
  padding: 9px 4px; font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.gb-c.avg b { font-weight: 600; }

.gb-hint { margin: 10px 2px 0; font-size: 12px; color: var(--ink-3); }
.gb-hint b { font-weight: 600; color: var(--ink-2); }

/* ------------------------------------------------------------- Inspector
   One bar for whatever is selected. It holds the things that cannot fit in a
   cell — the comment the student will read, the history of the mark, and the
   single bulk action that is worth having. */
.gb-insp {
  display: none; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 14px; padding: 12px 16px; border-radius: 13px;
  background: var(--canvas); box-shadow: inset 0 0 0 .5px var(--hair);
}
.gb-insp.on { display: flex; }
.gb-iwho b { font-size: 14px; font-weight: 600; letter-spacing: -.014em; }
.gb-iwho span { display: block; font-size: 12px; color: var(--ink-3); }
.gb-istate { font-size: 12.5px; color: var(--ink-2); }
.gb-ifb {
  flex: 1; min-width: 220px; font: inherit; font-size: 13.5px;
  padding: 8px 12px; border-radius: 9px;
  border: 1px solid var(--rule); background: var(--paper);
}
.gb-ifb:focus { outline: none; border-color: var(--blue); }
.gb-ibtn {
  font-size: 13px; padding: 7px 13px; border-radius: 9px; white-space: nowrap;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--rule); color: var(--ink);
}
.gb-ibtn:hover { background: #fff; box-shadow: inset 0 0 0 1px var(--ink-3); }
.gb-ibtn.strong { background: var(--ink); color: #fff; box-shadow: none; }
.gb-ibtn:disabled { color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--hair); }

.gb-hist {
  margin-top: 10px; padding: 14px 16px; border-radius: 13px;
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.gb-histh { font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 8px; }
.gb-histl { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.gb-histl li { display: flex; align-items: baseline; gap: 10px; }
.gb-histl b { font-size: 13.5px; font-weight: 600; min-width: 72px; font-variant-numeric: tabular-nums; }
.gb-histl span { font-size: 12px; color: var(--ink-3); }

/* -------------------------------------------------------- One student */
.gb-marks { display: flex; flex-direction: column; gap: 2px; margin-bottom: 22px; }
.gb-mark {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 0; border-bottom: 1px solid var(--hair);
}
.gb-mark .t { flex: 1; min-width: 160px; }
.gb-mark .t b { display: block; font-size: 15px; font-weight: 500; letter-spacing: -.015em; }
.gb-mark .t span { font-size: 12.5px; color: var(--ink-3); }
.gb-mark .fb {
  flex-basis: 100%; font-size: 13.5px; color: var(--ink-2); line-height: 1.5;
  padding: 8px 12px; border-radius: 9px; background: var(--canvas);
}

@media (max-width: 700px) {
  .gb-r { grid-template-columns: 132px repeat(var(--gb-cols), 70px) 80px 1fr; }
  .gb-c.name { padding-left: 10px; }
  .gb-c.name .admin-av { display: none; }
  .gb-scroll { max-height: 62vh; }
}

/* Motion is decoration here too. */
@media (prefers-reduced-motion: reduce) {
  .gb-c.cell.ok { animation: none; }
}

/* A mark in a list of marks. `em` is the shape a fact takes when it is not a
   number — "Not handed in" is as much a mark as 14 / 20 is, and drawing it in
   a lighter grey than the scores beside it would be the same as hiding it. */
.admin-row .mk { font-size: 13.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.admin-row .mk em { font-style: normal; color: var(--ink-3); }
.admin-row .mk.miss em { color: var(--red); font-weight: 500; }

/* ==========================================================================
   The console.

   A left rail holding the whole surface, and the work filling everything to
   the right of it. The structure is the one operations dashboards have
   converged on — Cloudflare's is the clearest — because it is the right answer
   to the problem it solves: somebody who uses eight screens all day should be
   able to see all eight and reach any of them in one movement.

   What is adjusted is the weight of it. A rail read for eight hours needs
   less, not more: no chevron on a row that does not expand, no icon arguing
   with the word next to it, no colour except on the row you are standing on
   and the numbers that changed. The type is one size for everything a person
   navigates by, because two sizes in a list of eight is a hierarchy nobody
   asked for.
   ========================================================================== */

.cn-rail {
  position: fixed; inset: 0 auto 0 0; width: 232px; z-index: 60;
  display: none; flex-direction: column;
  padding: 10px 10px 12px;
  background: var(--paper); border-right: 1px solid var(--hair);
}
body.is-console .cn-rail { display: flex; }

/* There is no top bar in the console. The rail is the navigation, it is flush
   to the edge of the screen, and it runs the full height of it.

   The bar that used to sit above was the student's — Home, Explore, a streak,
   an avatar — and keeping it meant a teacher navigated with two things that
   disagreed about where they were. Going back is now a small control at the
   head of the content, present only when there is somewhere to go back to. */
body.is-console .lx-bar,
body.is-console .lx-subbar,
body.is-console .tt-open,
/* Staff have no streak, no rank and nothing assigned to them. A bar carrying
   all three is a bar built for somebody else. */
body.is-staff .lx-bar,
body.is-staff .lx-subbar,
body.is-staff .tt-open { display: none !important; }

/* The gutter is the fix for the thing that looked broken: `padding-left` used
   to equal the rail's width exactly, so the page's own 22px gutter was
   overwritten and the first character of every heading sat eight pixels from
   the rail's edge. The rail is a wall; content does not lean on it. */
body.is-console .lx-wrap {
  padding-left: calc(232px + 34px);
  padding-right: 34px;
  padding-top: 64px;
  max-width: none;
}
/* Wide enough for a table of thirty students with five columns, and no wider.
   A row whose name is at the far left and whose grade is 1400px away is a row
   nobody reads across. */
body.is-console .admin-body { max-width: 1280px; }

.cn-back, .cn-open { display: none; }
/* Absolute, not fixed. It is a link at the head of a page, not chrome — and
   fixed meant it sat on top of the sixth unit of a course while you read it. */
body.is-console .cn-back {
  position: absolute; top: 20px; left: calc(232px + 34px); z-index: 50;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; color: var(--ink-3);
  padding: 5px 11px 5px 8px; border-radius: 999px;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair);
  transition: color .14s var(--ease), box-shadow .14s var(--ease);
}
body.is-console .cn-back[hidden] { display: none; }
body.is-console .cn-back:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--rule); }
/* The content always starts below where the back control sits, present or
   not, so a screen does not shift when one appears. */

/* The account, at the top. It is the only row in the rail with two lines,
   because it is the only one that is about a person rather than a place. */
.cn-org {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border-radius: 10px; text-align: left;
  transition: background .14s var(--ease);
}
.cn-org:hover { background: var(--canvas); }
.cn-org .av {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
  font-size: 10px; font-weight: 600; letter-spacing: .01em; background: var(--ink-3);
}
.cn-org .t { min-width: 0; }
.cn-org .t b {
  display: block; font-size: 13px; font-weight: 550; letter-spacing: -.012em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cn-org .t span { display: block; font-size: 11px; color: var(--ink-3); }

.cn-find {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; margin: 8px 0 4px; padding: 7px 10px; border-radius: 9px;
  font-size: 13px; color: var(--ink-3);
  box-shadow: inset 0 0 0 1px var(--hair);
  transition: box-shadow .14s var(--ease);
}
.cn-find:hover { box-shadow: inset 0 0 0 1px var(--rule); }
.cn-find kbd {
  font: inherit; font-size: 10.5px; color: var(--ink-3);
  padding: 1px 5px; border-radius: 5px; background: var(--canvas);
}

.cn-nav { flex: 1; overflow: auto; margin-top: 6px; }
.cn-group {
  margin: 16px 10px 5px; font-size: 10.5px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
.cn-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 10px; border-radius: 9px; text-align: left;
  font-size: 13.5px; letter-spacing: -.012em; color: var(--ink-2);
  transition: background .14s var(--ease), color .14s var(--ease);
}
.cn-item .nm { flex: 1; min-width: 0; }
.cn-item:hover { background: var(--canvas); color: var(--ink); }
.cn-item.on { background: var(--canvas); color: var(--ink); font-weight: 550; }
.cn-item.quiet { color: var(--ink-3); }
/* The count. It is the only number in the rail and it only appears when it is
   not zero — a row that permanently reads "0" teaches you to stop looking. */
.cn-item .ct {
  font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-3);
  padding: 1px 6px; border-radius: 999px;
}
.cn-item .ct.on { background: var(--sunk); color: var(--ink-2); }
.cn-foot { border-top: 1px solid var(--hair); padding-top: 8px; margin-top: 8px; }

.cn-scrim { display: none; }

/* ------------------------------------------------------------ The page */
.cn-head { margin-bottom: 22px; }
.cn-eyebrow {
  font-size: 11.5px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 7px;
}
.cn-h1 {
  font-family: var(--font); font-size: clamp(28px, 3.4vw, 38px); font-weight: 600;
  letter-spacing: -.028em; line-height: 1.06;
}
.cn-sub { margin-top: 10px; max-width: 62ch; font-size: 14.5px; color: var(--ink-2); line-height: 1.5; }
.cn-h2 {
  margin: 32px 0 12px; font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.018em;
}

/* The tiles. Numbers, and the word for what they count. There is no chart on
   any of them because nothing behind them is a series — a sparkline drawn
   through one point is a drawing. */
.cn-tiles {
  display: grid; gap: 10px; margin-bottom: 6px;
  /* Capped, not stretched. A number is read at a glance and a glance does not
     get better when the box around it is 250px wide. */
  grid-template-columns: repeat(auto-fit, minmax(140px, 208px));
  justify-content: start;
}
.cn-tile {
  padding: 16px 18px; border-radius: 13px;
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.cn-tile b {
  display: block; font-family: var(--font); font-size: 30px; font-weight: 600;
  letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums;
}
.cn-tile span { display: block; margin-top: 6px; font-size: 12px; color: var(--ink-3); }
.cn-tile.owe b { color: var(--amber); }
.cn-tile.late b { color: var(--red); }
.cn-tile.done b { color: var(--green); }

.cn-verdict {
  margin: 16px 0 4px; padding: 13px 16px; border-radius: 11px;
  font-size: 14px; line-height: 1.5; color: var(--ink);
  background: #fffaf1; box-shadow: inset 0 0 0 .5px #f0e0c4;
}
.cn-verdict.ok { background: #f1f8f3; box-shadow: inset 0 0 0 .5px #d8ecdf; }

/* A row. One shape for every list in the console — a class, a piece of work,
   a report — so that moving between screens is not relearning a layout. */
.cn-rows { display: flex; flex-direction: column; }
/* Each row is its own grid, so `auto` columns sized themselves per row and
   the numbers down a list did not line up — 76% in one row and 84% in the
   next sat forty pixels apart. Fixed columns fix that, and the trailing one
   takes the slack so the content clusters to the left instead of being flung
   at the right edge of a 1280px page. */
.cn-row {
  display: grid;
  grid-template-columns: minmax(180px, 2.2fr) 150px 210px minmax(0, 1.1fr);
  gap: 18px;
  align-items: center; width: 100%; text-align: left;
  padding: var(--row) 4px; border-bottom: 1px solid var(--hair);
  transition: background .13s var(--ease);
}

button.cn-row:hover { background: var(--canvas); }
.cn-row.flat { cursor: default; }
.cn-row .t { min-width: 0; }
.cn-row .t b {
  display: block; font-size: 15px; font-weight: 550; letter-spacing: -.016em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cn-row .t span { display: block; font-size: 12.5px; color: var(--ink-3); }
.cn-row .m { text-align: right; }
.cn-row .m i {
  font-style: normal; font-family: var(--font); font-size: 16px; font-weight: 600;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.cn-row .m span { display: block; font-size: 11px; color: var(--ink-3); }
.cn-row .s { text-align: right; min-width: 0; }
.cn-row .s em {
  font-style: normal; font-size: 12.5px; font-weight: 550; white-space: nowrap;
}
.cn-row .s em.owe { color: var(--amber); }
.cn-row .s em.late { color: var(--red); }
.cn-row .s em.done { color: var(--ink-3); font-weight: 400; }
.cn-row .s .why {
  display: block; font-size: 11.5px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* On the reporting list the reason is the content — "2 pieces of work
   unmarked in Waves and Sound" is the whole point of the row — so it takes
   the slack the other lists leave at the right rather than being ellipsised
   into "2 pieces of work unmark…" beside 250px of nothing. */
.cn-row.report { grid-template-columns: minmax(170px, 1.5fr) 120px minmax(280px, 2fr); }
/* And it reads left. Right-aligned prose goes ragged down the left edge,
   which is where the eye starts every line. */
.cn-row.report .s { text-align: left; }

.cn-block { margin-bottom: 30px; }
.cn-blockhead {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 8px; border-bottom: 1px solid var(--rule);
}
.cn-blockhead h3 { font-size: 16px; font-weight: 600; letter-spacing: -.018em; }
.cn-blockhead span { flex: 1; font-size: 12.5px; color: var(--ink-3); }

.cn-btn {
  font-size: 13px; padding: 7px 13px; border-radius: 9px; white-space: nowrap;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--rule); color: var(--ink);
}
.cn-btn:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
.cn-btn.strong { background: var(--ink); color: #fff; box-shadow: none; }
.cn-btn:disabled { color: var(--ink-3); background: var(--canvas); box-shadow: none; }

/* --------------------------------------------------------- One report */
.cn-report {
  margin: 22px 0; padding: 22px 24px; border-radius: var(--r);
  background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.cn-reporthead { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; }
.cn-reporthead h3 { font-family: var(--font); font-size: 20px; font-weight: 600; letter-spacing: -.022em; }
.cn-reporthead .t span { font-size: 12.5px; color: var(--ink-3); }
.cn-reporthead .g { display: flex; align-items: baseline; gap: 9px; }
.cn-reporthead .g b {
  font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: -.03em;
}
.cn-reporthead .g span { font-size: 14px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.cn-reporthead .g .tr { font-style: normal; font-size: 12.5px; font-weight: 550; color: var(--ink-3); }
.cn-reporthead .g .tr.up { color: var(--green); }
.cn-reporthead .g .tr.down { color: var(--amber); }
.cn-fine { margin-top: 8px; font-size: 12.5px; color: var(--ink-3); line-height: 1.5; }

/* The evidence, sitting above the box the sentence goes in. */
.cn-ev { display: flex; flex-wrap: wrap; gap: 7px; margin: 16px 0 4px; }
.cn-chip {
  font-size: 12px; color: var(--ink-2); padding: 7px 11px; border-radius: 9px;
  background: var(--canvas);
}
.cn-chip b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cn-chip span { display: block; font-size: 10.5px; color: var(--ink-3); }
.cn-chip.quiet b { color: var(--ink-2); }

.cn-comment { margin-top: 14px; }
.cn-lab { display: block; font-size: 12px; font-weight: 600; color: var(--ink-3); margin-bottom: 6px; }
.cn-comment textarea {
  width: 100%; font: inherit; font-size: 14.5px; line-height: 1.5; resize: vertical;
  padding: 11px 13px; border-radius: 11px; border: 1px solid var(--rule);
  background: var(--paper); color: var(--ink);
}
.cn-comment textarea:focus { outline: none; border-color: var(--blue); }
.cn-commentfoot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 8px; }
.cn-commentfoot .cn-fine { margin-top: 0; }

.cn-why { margin-top: 14px; display: flex; flex-direction: column; gap: 5px; }
.cn-why li { font-size: 12.5px; color: var(--ink-3); padding-left: 14px; position: relative; }
.cn-why li::before { content: "·"; position: absolute; left: 4px; }
.cn-why li.flag { color: var(--amber); }

.cn-marks { margin-top: 16px; }
.cn-marks summary {
  cursor: pointer; font-size: 13px; color: var(--ink-2); padding: 6px 0;
  list-style: none;
}
.cn-marks summary::-webkit-details-marker { display: none; }
.cn-marks summary::before { content: "›"; display: inline-block; width: 14px; transition: transform .15s var(--ease); }
.cn-marks[open] summary::before { transform: rotate(90deg); }

/* ------------------------------------------------------------- The finder */
.cn-finderwrap {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: start center;
  padding-top: 14vh; background: rgba(0,0,0,.18);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.cn-finder {
  width: min(520px, 92vw); border-radius: 15px; overflow: hidden;
  background: var(--paper); box-shadow: 0 24px 60px -12px rgba(0,0,0,.28), 0 0 0 .5px var(--hair);
}
.cn-finderin {
  width: 100%; font: inherit; font-size: 16px; padding: 16px 18px;
  border: 0; border-bottom: 1px solid var(--hair); background: none; color: var(--ink);
}
.cn-finderin:focus { outline: none; }
.cn-finderlist { max-height: 50vh; overflow: auto; padding: 6px; }
.cn-finderrow {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 9px 12px; border-radius: 9px; text-align: left;
}
.cn-finderrow b { font-size: 14px; font-weight: 500; letter-spacing: -.014em; }
.cn-finderrow span { font-size: 11.5px; color: var(--ink-3); }
.cn-finderrow.on { background: var(--canvas); }

@media (max-width: 1040px) {
  .cn-row { grid-template-columns: minmax(0, 1fr) 120px 150px; }
}
@media (max-width: 900px) {
  .cn-rail { transform: translateX(-100%); transition: transform .22s var(--ease); }
  body.is-console .cn-rail { display: flex; }
  body.rail-open .cn-rail { transform: none; box-shadow: 0 0 60px rgba(0,0,0,.16); }
  body.is-console .lx-wrap { padding-left: 0; padding-top: 64px; }
  body.is-console .cn-back { left: 58px; top: 16px; }
  /* The rail is a drawer here, so it needs a way in. A 34px control at the
     top-left corner is the whole of what a top bar was doing. */
  body.is-console .cn-open {
    position: fixed; top: 14px; left: 14px; z-index: 58;
    display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
    color: var(--ink-2); background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair);
  }
  body.rail-open .cn-scrim { display: block; position: fixed; inset: 0; z-index: 55; background: rgba(0,0,0,.16); }
  .cn-row { grid-template-columns: minmax(0, 1fr) auto; gap: 12px; }
  .cn-row .m { display: none; }
  .cn-row .s .why { max-width: 22ch; }
}
@media (prefers-reduced-motion: reduce) {
  .cn-rail { transition: none; }
}

/* ==========================================================================
   Console primitives.

   Three shapes — a table, a split view, an inspector — and every screen is
   built from them. That is the point: moving between screens should not be
   relearning a layout, and the fastest interface is the one whose second
   screen you already know how to read.

   Density is a variable rather than a redesign. The same markup at three row
   heights, and the type never shrinks: solving density with 10px text is how
   professional software becomes unreadable by the people who use it most.
   ========================================================================== */

body { --row: 12px; --rowgap: 14px; }
body[data-density="comfortable"] { --row: 16px; --rowgap: 18px; }
body[data-density="dense"]       { --row: 7px;  --rowgap: 10px; }

/* -------------------------------------------------------------- The table */
.cn-tbl {
  margin-top: 14px; background: var(--paper); border-radius: 13px;
  box-shadow: inset 0 0 0 .5px var(--hair); overflow: hidden;
}
.cn-tr {
  display: grid; grid-template-columns: var(--cols); gap: var(--rowgap);
  align-items: center; width: 100%; text-align: left;
  padding: var(--row) 16px; border-bottom: 1px solid var(--hair);
  transition: background .12s var(--ease);
}
.cn-tbody .cn-tr:last-child { border-bottom: 0; }
.cn-tr.head {
  padding-top: 10px; padding-bottom: 10px;
  background: var(--canvas); border-bottom: 1px solid var(--rule);
}
.cn-th {
  font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
.cn-th.r, .cn-td.r { text-align: right; }
.cn-td { min-width: 0; font-size: 13.5px; color: var(--ink-2); letter-spacing: -.01em; }
.cn-td b {
  display: block; font-size: 14px; font-weight: 550; color: var(--ink);
  letter-spacing: -.014em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cn-td.r b { display: inline; }
button.cn-tr:hover { background: var(--canvas); }
button.cn-tr.on { background: #eef5fd; }
button.cn-tr.on::before {
  content: ""; position: absolute; left: 0; width: 2px; height: 100%; background: var(--blue);
}
button.cn-tr { position: relative; }
.cn-tr.flat { cursor: default; }

.cn-who { display: flex; align-items: center; gap: 9px; min-width: 0; }
.cn-who .nm {
  font-size: 14px; font-weight: 550; color: var(--ink); letter-spacing: -.014em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cn-who .admin-av { width: 24px; height: 24px; font-size: 9.5px; flex: none; }
body[data-density="dense"] .cn-who .admin-av { width: 20px; height: 20px; font-size: 9px; }

/* Numbers are the content. They align right, they use tabular figures so a
   column of them is a column, and only two of them are ever coloured. */
.cn-mk {
  font-family: var(--font); font-size: 14.5px; font-weight: 600;
  letter-spacing: -.018em; font-variant-numeric: tabular-nums; color: var(--ink);
}
.cn-mk.bad { color: var(--red); }
.cn-mk.warn { color: var(--amber); }
.cn-pc { margin-left: 5px; font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cn-none { color: var(--ink-3); }
.cn-sub2 { display: block; font-size: 11.5px; color: var(--ink-3); }
.cn-mono { font-size: 12.5px; color: var(--ink-3); }
.cn-tag {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--sunk); color: var(--ink-2);
}
.cn-tag.on { background: #e7f3ea; color: var(--green); }
.cn-change i { font-style: normal; color: var(--ink-3); }
.cn-change b { display: inline; margin-left: 6px; }
.cn-change i + b::before { content: ""; }

/* ---------------------------------------------------------- The split view */
.cn-split { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(300px, 1fr); gap: 18px; align-items: start; }
.cn-splitright { position: sticky; top: calc(var(--bar) + 18px); }
@media (max-width: 1040px) {
  .cn-split { grid-template-columns: 1fr; }
  .cn-splitright { position: static; }
}

.cn-insp {
  padding: 20px; border-radius: 14px; background: var(--paper);
  box-shadow: inset 0 0 0 .5px var(--hair);
}
.cn-insphead { display: flex; align-items: center; gap: 11px; margin-bottom: 16px; }
.cn-insphead .admin-av { width: 34px; height: 34px; font-size: 12px; flex: none; }
.cn-insphead .t { min-width: 0; }
.cn-insphead .t b { display: block; font-size: 16px; font-weight: 600; letter-spacing: -.018em; }
.cn-insphead .t span {
  display: block; font-size: 12px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cn-inspbig { margin-bottom: 4px; }
.cn-inspbig b {
  font-family: var(--font); font-size: 34px; font-weight: 600; letter-spacing: -.032em;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.cn-inspbig span { display: block; margin-top: 5px; font-size: 12px; color: var(--ink-3); }
.cn-insp .cn-tbl { box-shadow: none; border-radius: 0; margin-top: 10px; }
.cn-insp .cn-tr { padding-left: 0; padding-right: 0; }
.cn-insp .cn-tr.head { background: none; }

/* -------------------------------------------------- Filters and the bar */
.cn-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 4px; }
.cn-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.cn-filter {
  font-size: 13px; padding: 6px 12px; border-radius: 999px; color: var(--ink-2);
  box-shadow: inset 0 0 0 1px var(--hair);
  transition: box-shadow .14s var(--ease), background .14s var(--ease);
}
.cn-filter em {
  font-style: normal; margin-left: 6px; font-size: 11.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.cn-filter:hover { box-shadow: inset 0 0 0 1px var(--rule); }
.cn-filter.on { background: var(--ink); color: #fff; box-shadow: none; }
.cn-filter.on em { color: rgba(255,255,255,.6); }
input.cn-search {
  flex: 1; min-width: 180px; max-width: 320px; font: inherit; font-size: 13.5px;
  padding: 7px 13px; border-radius: 9px; border: 1px solid var(--hair); background: var(--paper);
}
input.cn-search:focus { outline: none; border-color: var(--blue); }

.cn-acts { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 2px; }
.cn-rowacts { display: inline-flex; gap: 6px; justify-content: flex-end; }

/* A student's family, on their page in People. */
.cn-family { margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--hair); max-width: 820px; }
.cn-family h2 { font-size: 20px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.cn-family .cn-tbl { margin-top: 12px; }
.cn-family > div > .cn-none { margin-top: 12px; font-size: 13.5px; }
.cn-family-add { margin-top: 18px; padding: 18px; border-radius: 14px; background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair); }
.cn-check { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 13.5px; color: var(--ink); }
.cn-btn.small { font-size: 12px; padding: 5px 10px; }

.cn-empty {
  margin-top: 16px; padding: 34px 28px; border-radius: 14px; text-align: center;
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.cn-empty b { display: block; font-size: 16px; font-weight: 600; letter-spacing: -.018em; }
.cn-empty p {
  margin: 8px auto 0; max-width: 44ch; font-size: 13.5px; color: var(--ink-3); line-height: 1.5;
}
.cn-empty .cn-btn { margin-top: 16px; }

.cn-pref {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  flex-wrap: wrap; margin: 6px 0 20px; padding: 16px 18px; border-radius: 13px;
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.cn-pref .t b { display: block; font-size: 14px; font-weight: 600; letter-spacing: -.014em; }
.cn-pref .t span { display: block; margin-top: 3px; max-width: 52ch; font-size: 12.5px; color: var(--ink-3); }
.cn-seg { display: flex; padding: 2px; border-radius: 9px; background: var(--canvas); }
.cn-segb { font-size: 12.5px; padding: 6px 13px; border-radius: 7px; color: var(--ink-2); }
.cn-segb.on { background: var(--paper); color: var(--ink); font-weight: 550; box-shadow: 0 0 0 .5px var(--hair); }

/* ------------------------------------------------------------ Focus mode
   Marking is the one thing here somebody does for an hour without stopping,
   so it gets a mode with nothing else on the screen. */
body.focus-mode .cn-rail,
body.focus-mode .cn-back,
body.focus-mode .cn-open,
body.focus-mode .cn-head,
body.focus-mode .gb-pick,
body.focus-mode .gb-needs,
body.focus-mode .tt-open { display: none !important; }
body.focus-mode.is-console .lx-wrap { padding-left: 0; padding-top: 18px; }
body.focus-mode .gb-scroll { max-height: calc(100vh - 190px); }

/* ==========================================================================
   What is left of the old console.

   The screens above were rebuilt; the editors underneath them — a course, a
   person, a study set — keep their logic and are re-dressed here rather than
   rewritten, because their behaviour was never the problem. The card grid,
   the tab strip and the list rows are gone; these are the forms.
   ========================================================================== */

body.is-console .admin-form {
  margin-top: 18px; padding: 20px; border-radius: 14px;
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
body.is-console .admin-field > span {
  font-size: 12px; font-weight: 600; letter-spacing: 0; text-transform: none;
  color: var(--ink-3);
}
body.is-console .admin-field input,
body.is-console .admin-field textarea,
body.is-console .admin-field select {
  border-radius: 10px; border-color: var(--hair); font-size: 14px;
}
body.is-console .admin-field input:focus,
body.is-console .admin-field textarea:focus,
body.is-console .admin-field select:focus { border-color: var(--blue); }
body.is-console .admin-acts { gap: 8px; margin-top: 16px; }
body.is-console .admin-acts .lx-btn {
  height: 34px; font-size: 13px; padding: 0 14px; border-radius: 9px;
  background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--rule);
}
body.is-console .admin-acts .lx-btn:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
body.is-console .admin-acts .lx-btn.lg { background: var(--ink); color: #fff; box-shadow: none; }
body.is-console .admin-list { margin-top: 14px; }
body.is-console .admin-row {
  padding: var(--row) 16px; border-radius: 0; border-bottom: 1px solid var(--hair);
}
body.is-console .lx-h1 {
  font-family: var(--font); font-size: clamp(26px, 3vw, 34px); font-weight: 600;
  letter-spacing: -.026em;
}
body.is-console .lx-eyebrow {
  font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-3);
}
body.is-console .lx-lede { max-width: 66ch; font-size: 14.5px; color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .cn-tr, .cn-filter, .cn-btn { transition: none; }
}

/* Work handed in late. A corner rather than a badge — it is a fact about the
   mark, not a thing to click, and the mark is what the eye is here for. */
.gb-c.cell.tardy::before {
  content: ""; position: absolute; bottom: 3px; left: 3px;
  width: 0; height: 0; border-bottom: 5px solid var(--amber);
  border-right: 5px solid transparent; opacity: .8;
}

/* A row you can open. The main part is the button; the remove control stays
   its own target so a mis-aimed click edits rather than deletes. */
.admin-rowmain {
  flex: 1; min-width: 0; text-align: left; display: flex; align-items: center;
  padding: 0; border-radius: 8px;
}
.admin-rowmain:hover .t b { color: var(--blue); }
.admin-edit {
  padding: 4px 0 18px; border-bottom: 1px solid var(--hair); margin-bottom: 4px;
}
.admin-edit .admin-form { margin-top: 10px; }

/* ==========================================================================
   One course.

   A page about a course rather than the row that stores it: the plan, what is
   set, what is written, who is in it. The editor is still there, behind a
   button, because editing is something you do to a course occasionally and
   reading one is something you do every day.
   ========================================================================== */

.cs-lede {
  max-width: 68ch; font-size: 15.5px; line-height: 1.55; color: var(--ink-2);
}

/* The plan. Numbered, because a syllabus is an order and not a set, and the
   number is the thing a teacher says out loud — "we're on four". */
.cs-plan { margin-top: 12px; }
.cs-plan li {
  display: grid; grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 14px; align-items: baseline;
  padding: var(--row) 4px; border-bottom: 1px solid var(--hair);
}
.cs-plan li:last-child { border-bottom: 0; }
.cs-plan .n {
  font-family: var(--font); font-size: 13px; font-weight: 600; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.cs-plan .t b {
  display: block; font-size: 15px; font-weight: 550; letter-spacing: -.016em;
}
.cs-plan .t span {
  display: block; margin-top: 3px; max-width: 74ch;
  font-size: 12.5px; line-height: 1.5; color: var(--ink-3);
}
.cs-plan .g { display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
/* What is written behind a unit. Not a status and not a warning — a fact
   about the curriculum, so it is drawn as quietly as one. */
.cs-tag {
  font-style: normal; font-size: 10.5px; color: var(--ink-2);
  padding: 2px 8px; border-radius: 999px; background: var(--canvas); white-space: nowrap;
}

/* The weights, as bars. A textarea reading "Quizzes = 25" is the storage
   format shown to a person. */
.admin-body .admin-mark-parts { margin-top: 10px; max-width: 620px; }
.admin-body .admin-mark-part { grid-template-columns: 190px 1fr 52px; }

/* The first day. Not a dashboard of zeroes — one sentence and the thing to do. */
.cn-start {
  margin-top: 10px; padding: 34px 32px; border-radius: var(--r);
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.cn-start h2 {
  font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.022em;
}
.cn-start p {
  margin-top: 10px; max-width: 58ch; font-size: 14.5px; line-height: 1.55; color: var(--ink-2);
}
.cn-start .cn-acts { margin-top: 20px; }

/* ==========================================================================
   What a teacher has set.

   First on a student's screen, above everything the app has an opinion about,
   because it is the only part they are actually being marked on. Late first,
   then due, then handed back — and the two states that cost marks are the two
   that are allowed any colour.
   ========================================================================== */

.sw-list {
  margin-top: 14px; border-radius: var(--r); overflow: hidden;
  background: var(--paper); box-shadow: 0 0 0 .5px var(--hair);
}
.sw-row {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) auto auto;
  gap: 14px; align-items: center;
  padding: 13px 18px; border-bottom: 1px solid var(--hair);
}
.sw-row .ic {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--canvas); color: var(--ink-2);
}
.sw-row .ic svg { width: 15px; height: 15px; }
.sw-row .t { min-width: 0; }
.sw-row .sw-go { height: 32px; padding: 0 15px; font-size: 13.5px; border-radius: 999px; }
.sw-row:last-child { border-bottom: 0; }
.sw-row .t b {
  display: block; font-size: 15.5px; font-weight: 550; letter-spacing: -.016em;
}
.sw-row .t span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--ink-3); }
.sw-row .m {
  /* lab.css styles a bare .m as maths; this .m is a status. */
  font-family: var(--font); font-style: normal;
  font-size: 14px; font-weight: 550; white-space: nowrap;
  font-variant-numeric: tabular-nums; color: var(--ink-2);
}
/* Past due and not handed in are the two that cost a student marks, so they
   are the two the eye is allowed to find. Everything else stays quiet. */
.sw-row.late .m { color: var(--amber); }
.sw-row.missing .m { color: var(--red); }
.sw-row.handed .m { color: var(--blue); }
.sw-row.marked .m { color: var(--ink); }
.sw-row.handed .ic, .sw-row.marked .ic { color: var(--blue); }
.sw-row .fb {
  grid-column: 2 / -1; margin-top: 2px; padding: 9px 12px; border-radius: 9px;
  background: var(--canvas); font-size: 13.5px; line-height: 1.5; color: var(--ink-2);
}
@media (max-width: 560px) {
  .sw-row { grid-template-columns: 30px 1fr; gap: 4px 12px; }
  .sw-row .m, .sw-row .sw-go { grid-column: 2; text-align: left; justify-self: start; }
}

/* ==========================================================================
   School and Self-learning — two lanes on Home, never one list.

   School is what is graded: the work teachers set, the courses the school
   put a student in. Self-learning is theirs: never graded, seen by nobody
   else. They sit side by side so a student always knows which is which, and
   the self-learning lane is drawn a step quieter — a sunk surface, no accent.
   ========================================================================== */
.lx-lanes { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 22px; margin-top: 34px; align-items: start; }
.lx-lane { min-width: 0; padding: 24px 24px 22px; border-radius: 22px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair); }
.lx-lane.own { background: var(--canvas); box-shadow: none; }
.lx-lanehead .k { font-size: 11.5px; font-weight: 650; letter-spacing: .08em; text-transform: uppercase; color: var(--blue); }
.lx-lane.own .lx-lanehead .k { color: var(--ink-3); }
.lx-lanehead h2 { margin-top: 4px; font-size: 24px; font-weight: 650; letter-spacing: -.022em; }
.lx-lanehead p { margin-top: 6px; font-size: 14px; line-height: 1.45; color: var(--ink-2); max-width: 46ch; }
.lx-lanesub { margin: 24px 0 8px; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.lx-lanenote { margin: 6px 0; font-size: 13.5px; color: var(--ink-2); }
.lx-lanenone { margin-top: 18px; padding: 16px 18px; border-radius: 14px; background: var(--canvas); }
.lx-lane.own .lx-lanenone { background: var(--paper); }
.lx-lanenone b { font-size: 15px; font-weight: 600; }
.lx-lanenone p { margin-top: 4px; font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }
.lx-lane .sw-list { margin-top: 4px; border-radius: 0; background: transparent; box-shadow: none; border-top: 1px solid var(--hair); }
.lx-lane .sw-row { padding: 12px 2px; }
.lx-lane > .lx-btn { margin-top: 18px; }
.lx-lanelink { display: inline-block; margin-top: 10px; padding: 4px 0; font-size: 13.5px; font-weight: 550; color: var(--blue); background: none; }
.lx-lanelink:hover { text-decoration: underline; }
.lx-crow-list { display: grid; gap: 2px; }
.lx-crow { display: flex; align-items: center; gap: 12px; width: 100%; padding: 9px 8px; border-radius: 12px; text-align: left; transition: background .14s var(--ease); }
.lx-crow:hover { background: var(--canvas); }
.lx-lane.own .lx-crow:hover { background: var(--paper); }
.lx-crow .ic { width: 34px; height: 34px; flex: none; border-radius: 10px; display: grid; place-items: center; background: var(--canvas); color: var(--ink-2); }
.lx-crow .ic svg { width: 18px; height: 18px; }
.lx-crow .t { flex: 1; min-width: 0; }
.lx-crow .t b { display: block; font-size: 14.5px; font-weight: 600; letter-spacing: -.012em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lx-crow .t span { display: block; margin-top: 1px; font-size: 12.5px; color: var(--ink-3); }
.lx-crow .p { width: 64px; height: 4px; flex: none; border-radius: 2px; overflow: hidden; background: var(--sunk); }
.lx-crow .p i { display: block; height: 100%; border-radius: 2px; background: var(--ink-2); }
.lx-crow .pc { width: 38px; flex: none; text-align: right; font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--ink-3); }
.lx-stepcard { display: grid; gap: 4px; margin-top: 20px; padding: 16px 18px; border-radius: 16px; background: var(--canvas); }
.lx-lane.own .lx-stepcard { background: var(--paper); }
.lx-stepcard .k { font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
.lx-stepcard b { font-size: 16px; font-weight: 600; letter-spacing: -.014em; }
.lx-stepcard span { font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }
.lx-stepcard .lx-btn { justify-self: start; margin-top: 10px; }
/* On a course's page: which of the two this course is. */
.lx-kind { display: flex; align-items: center; gap: 14px; margin: 18px 0 26px; padding: 14px 18px; border-radius: 16px; background: var(--canvas); }
.lx-kind b { flex: none; font-size: 14.5px; font-weight: 650; }
.lx-kind.school b { color: var(--blue); }
.lx-kind span { flex: 1; min-width: 0; font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }
/* On a phone the sentence takes a line of its own, under the label and
   button, instead of a column one word wide between them. */
@media (max-width: 560px) {
  .lx-kind { flex-wrap: wrap; gap: 8px 12px; }
  .lx-kind span { order: 3; flex-basis: 100%; }
  .lx-kind .lx-btn, .lx-kind .lx-lanelink { margin-left: auto; }
}
/* The Self-learning page. */
.lx-owngrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 18px; margin-top: 26px; }
.lx-owncard { padding: 20px; border-radius: 20px; background: var(--paper); box-shadow: 0 0 0 .5px var(--hair); }
.lx-owncard .ic { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; }
.lx-owncard .ic svg { width: 20px; height: 20px; }
.lx-owncard h3 { margin-top: 14px; font-size: 17px; font-weight: 600; letter-spacing: -.014em; }
.lx-owncard p { margin-top: 4px; font-size: 13.5px; color: var(--ink-2); }
.lx-owncard .bar { height: 5px; margin-top: 14px; border-radius: 3px; overflow: hidden; background: var(--sunk); }
.lx-owncard .bar i { display: block; height: 100%; border-radius: 3px; background: var(--ink-2); }
.lx-owncard .pc { font-size: 12.5px; color: var(--ink-3); }
.lx-owncard .acts { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
@media (max-width: 980px) { .lx-lanes { grid-template-columns: 1fr; } }

/* The sentence a teacher wrote about the term, on the student's own screen.
   Set as something somebody said, not as a data field. */
.sw-said {
  margin-top: 12px; padding: 18px 20px; border-radius: var(--r);
  background: var(--paper); box-shadow: inset 0 0 0 .5px var(--hair);
}
.sw-said p { font-size: 16px; line-height: 1.55; letter-spacing: -.012em; }

.atb-badge {
  display: inline-flex; align-items: center; height: 18px; padding: 0 5px;
  margin-left: 5px; border-radius: 5px;
  background: var(--blue); color: #fff;
  font-family: "Spline Sans Mono", "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 9.5px; font-weight: 700;
  letter-spacing: .04em; line-height: 1;
  vertical-align: middle;
}

/* ============================================================ Exams ATB
   Apple-level exam centre. Every assessment is a card with a clear
   state: today it is doing, upcoming it waits, past it finished.
   Colour describes state — nothing else. The card says what is
   happening and when; nothing more. */

.lx-exam-tabs {
  display: flex; gap: 4px; margin: 18px 0 22px;
  background: var(--canvas); border-radius: 100px; padding: 3px;
  width: fit-content;
}
.lx-exam-tab {
  height: 32px; padding: 0 16px; border-radius: 100px;
  font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  display: inline-flex; align-items: center; gap: 6px;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.lx-exam-tab:hover { color: var(--ink); background: var(--sunk); }
.lx-exam-tab[aria-current="true"] { color: var(--ink); background: var(--paper); box-shadow: 0 1px 3px rgba(0,0,0,.06); }
.lx-exam-tab .n {
  font-size: 11.5px; font-weight: 600; padding: 1px 6px;
  border-radius: 100px; background: var(--sunk); color: var(--ink-3);
}

.lx-exam-group { margin-bottom: 32px; }
.lx-exam-group-head {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px;
}
.lx-exam-group-head h2 {
  font-family: var(--font); font-size: 17px; font-weight: 600;
  letter-spacing: -.014em;
}
.lx-exam-group-head p {
  font-size: 13px; color: var(--ink-3); font-weight: 400;
}

.lx-exam-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px;
}
.lx-exam-card {
  display: flex; flex-direction: column; text-align: left;
  padding: 22px; border-radius: 18px; background: var(--paper);
  border: 1px solid var(--hair); min-height: 158px;
  transition: transform .2s var(--ease), border-color .2s var(--ease), box-shadow .2s var(--ease);
  cursor: pointer;
}
.lx-exam-card:hover { transform: translateY(-2px); border-color: var(--rule); box-shadow: 0 8px 28px rgba(0,0,0,.06); }
.lx-exam-card:active { transform: translateY(0); }

.lx-exam-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.lx-exam-icon {
  width: 38px; height: 38px; border-radius: 11px; flex: none;
  display: grid; place-items: center;
}
.lx-exam-icon svg { width: 18px; height: 18px; }
.lx-exam-status {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 9px; border-radius: 100px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .01em;
  white-space: nowrap; flex: none;
}
.lx-exam-status .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.lx-exam-status.today { background: #e8f5ee; color: #12915a; }
.lx-exam-status.today .dot { background: #12915a; }
.lx-exam-status.upcoming { background: #e2f0fd; color: #0060c0; }
.lx-exam-status.upcoming .dot { background: #0060c0; }
.lx-exam-status.past { background: var(--canvas); color: var(--ink-3); }
.lx-exam-status.past .dot { background: #c7c7cc; }

.lx-exam-title {
  font-family: var(--font); font-size: 18px; font-weight: 600;
  letter-spacing: -.018em; margin-top: 14px; line-height: 1.22;
}
.lx-exam-sub {
  font-size: 13.5px; color: var(--ink-2); margin-top: 3px;
  letter-spacing: -.01em;
}
.lx-exam-when {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--ink-3); margin-top: 12px;
  font-variant-numeric: tabular-nums;
}
.lx-exam-when svg { width: 12px; height: 12px; flex: none; }
.lx-exam-meta {
  display: flex; gap: 12px; margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--hair);
}
.lx-exam-meta span {
  font-size: 12.5px; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 4px;
}
.lx-exam-meta svg { width: 11px; height: 11px; }
.lx-exam-score {
  font-size: 13px; font-weight: 600; color: var(--ink);
  margin-left: auto;
}
.lx-exam-go {
  margin-top: auto; padding-top: 14px; display: flex; align-items: center; gap: 4px;
  font-size: 13px; font-weight: 500; color: var(--blue);
}
.lx-exam-go svg { width: 13px; height: 13px; transition: transform .18s var(--ease); }
.lx-exam-card:hover .lx-exam-go svg { transform: translateX(3px); }

/* Exam empty state */
.lx-exams-empty {
  margin-top: 40px; padding: 48px 32px; border-radius: 20px; text-align: center;
  background: var(--paper); border: 1px solid var(--hair);
}
.lx-exams-empty .ic {
  width: 56px; height: 56px; border-radius: 16px; margin: 0 auto 18px;
  display: grid; place-items: center; background: var(--canvas); color: var(--ink-2);
}
.lx-exams-empty .ic svg { width: 24px; height: 24px; }
.lx-exams-empty h2 { font-family: var(--font); font-size: 20px; font-weight: 600; letter-spacing: -.016em; }
.lx-exams-empty p { margin-top: 6px; font-size: 14.5px; color: var(--ink-2); max-width: 36ch; margin-inline: auto; line-height: 1.5; }

/* Today hero strip */
.lx-today-strip {
  display: flex; align-items: center; gap: 20px;
  padding: 24px 26px; border-radius: 18px; background: var(--ink); color: #fff;
  margin-bottom: 28px;
}
.lx-today-strip .k { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.5); }
.lx-today-strip h2 { font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.018em; margin-top: 4px; }
.lx-today-strip p { margin-top: 5px; font-size: 14px; color: rgba(255,255,255,.65); max-width: 50ch; line-height: 1.5; }
.lx-today-strip .lx-btn { margin-left: auto; background: #fff; color: var(--ink); flex: none; }
.lx-today-strip .lx-btn:hover { background: #e8e8ea; }

@media (max-width: 734px) {
  .lx-exam-grid { grid-template-columns: 1fr; }
  .lx-exam-tab { padding: 0 12px; }
  .lx-today-strip { flex-direction: column; align-items: flex-start; }
  .lx-today-strip .lx-btn { margin-left: 0; width: 100%; }
}

/* Exam view header */
.lx-exams-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.lx-exams-head .sub { font-size: 14px; color: var(--ink-2); margin-top: 6px; }
.sw-said span { display: block; margin-top: 10px; font-size: 12.5px; color: var(--ink-3); }

/* ============================================================ Assessment Admin
   Assessment platform styles for the administrator console.
   Calm, dense, precise — matching the console design language. */

/* Assessment list rows */
.asm-row {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 18px; border-radius: 12px;
  background: var(--paper); border: 1px solid var(--hair);
  cursor: pointer; text-align: left; width: 100%;
  transition: transform .2s var(--ease), border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.asm-row:hover { transform: translateY(-2px); border-color: var(--rule); box-shadow: 0 8px 28px rgba(0,0,0,.06); }
.asm-row:active { transform: translateY(0); }
.asm-row .asm-accent { width: 4px; height: 36px; border-radius: 2px; flex: none; }
.asm-row .asm-title { font-family: var(--font); font-size: 15px; font-weight: 600; letter-spacing: -.014em; color: var(--ink); }
.asm-row .asm-meta { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
.asm-row .asm-info { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; flex: none; }
.asm-row .asm-state {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 9px; border-radius: 100px;
  font-size: 11px; font-weight: 600; flex: none;
}
.asm-row .asm-state .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.asm-row .asm-version { font-size: 11px; color: var(--ink-3); font-family: "Spline Sans Mono", monospace; flex: none; }

/* Assessment detail stats */
.asm-stats { display: flex; gap: 24px; margin-bottom: 24px; flex-wrap: wrap; }
.asm-stats > div { display: flex; flex-direction: column; }
.asm-stats b { font-size: 18px; font-weight: 700; color: var(--ink); }
.asm-stats span { font-size: 12px; color: var(--ink-3); margin-top: 2px; }

/* Assessment tabs */
.asm-tabs { display: flex; gap: 2px; margin-bottom: 24px; background: var(--canvas); border-radius: 100px; padding: 3px; width: fit-content; }
.asm-tab {
  height: 32px; padding: 0 14px; border-radius: 100px;
  font-size: 13px; font-weight: 500; color: var(--ink-2);
  display: inline-flex; align-items: center; gap: 6px;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.asm-tab:hover { color: var(--ink); background: var(--sunk); }
.asm-tab[aria-current="true"] { color: var(--ink); background: var(--paper); box-shadow: 0 1px 3px rgba(0,0,0,.06); }

/* Assessment detail blocks */
.asm-block { margin-bottom: 24px; }
.asm-blockhead { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.asm-blockhead h3 { font-family: var(--font); font-size: 16px; font-weight: 600; letter-spacing: -.014em; }
.asm-blockhead span { font-size: 12px; color: var(--ink-3); }

/* Timeline */
.asm-timeline-item { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
.asm-timeline-item + .asm-timeline-item { border-top: 1px solid var(--hair); }
.asm-timeline-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.asm-timeline-label { flex: 1; font-size: 13px; color: var(--ink); }
.asm-timeline-date { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* Assessment grid (for stats blocks) */
.asm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
.asm-grid > div { padding: 14px; border-radius: 12px; background: var(--canvas); border: 1px solid var(--hair); }
.asm-grid b { display: block; font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
.asm-grid span { font-size: 14px; font-weight: 500; color: var(--ink); }

/* Skill bar */
.asm-skill-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 10px; background: var(--paper); border: 1px solid var(--hair); }
.asm-skill-name { flex: 1; font-size: 13.5px; color: var(--ink); }
.asm-skill-count { font-size: 12px; color: var(--ink-3); flex: none; }
.asm-skill-bar { width: 60px; height: 6px; border-radius: 3px; background: var(--sunk); overflow: hidden; flex: none; }
.asm-skill-bar > div { height: 100%; border-radius: 3px; }
.asm-skill-pct { font-size: 12px; font-weight: 600; color: var(--ink-3); flex: none; }

/* Assessment studio */
.asm-studio { max-width: 800px; }
.asm-goal-label { font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 8px; }
.asm-goal-textarea {
  width: 100%; min-height: 120px; padding: 16px; border-radius: 14px;
  border: 1px solid var(--hair); background: var(--paper);
  font-size: 14.5px; line-height: 1.5; color: var(--ink);
  resize: vertical; font-family: inherit;
}
.asm-upload {
  padding: 32px; border-radius: 14px; border: 2px dashed var(--hair);
  text-align: center; background: var(--paper); margin-bottom: 24px;
}
.asm-upload-title { font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.asm-upload-sub { font-size: 12.5px; color: var(--ink-3); }

/* Student list in assessment detail */
.asm-student-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 8px; background: var(--canvas); }
.asm-student-av {
  width: 24px; height: 24px; border-radius: 6px; background: var(--sunk);
  display: grid; place-items: center; font-size: 10px; font-weight: 600; color: var(--ink-3); flex: none;
}
.asm-student-name { flex: 1; font-size: 13px; color: var(--ink); }
.asm-student-status { font-size: 11px; font-weight: 500; flex: none; }

/* AI architect panel */
.asm-ai {
  padding: 20px; border-radius: 14px;
  background: linear-gradient(135deg, #0d0d12, #1a1a2e); color: #fff;
  overflow: hidden;
}
.asm-ai-header { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.asm-ai-dot { width: 8px; height: 8px; border-radius: 50%; background: #7c5cfc; }
.asm-ai-title { font-size: 13px; font-weight: 600; }
.asm-ai-body { font-size: 13px; color: rgba(255,255,255,.85); line-height: 1.6; }
.asm-ai-actions { display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
.asm-ai-btn {
  padding: 8px 16px; border-radius: 9px; font-size: 13px; cursor: pointer;
  background: rgba(255,255,255,.1); color: #fff; border: 1px solid rgba(255,255,255,.2);
}
.asm-ai-btn.primary { background: #fff; color: #0d0d12; font-weight: 600; border: none; }

/* Assessment session stats */
.asm-session-stats { display: flex; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.asm-session-stats > div { padding: 10px 16px; border-radius: 10px; background: var(--paper); border: 1px solid var(--hair); }
.asm-session-stats b { font-size: 16px; font-weight: 700; color: var(--ink); }
.asm-session-stats span { font-size: 12px; color: var(--ink-3); }

/* Assessment security row */
.asm-security-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-radius: 8px; background: var(--paper); border: 1px solid var(--hair); }
.asm-security-row + .asm-security-row { margin-top: 6px; }
.asm-security-label { font-size: 13px; color: var(--ink); }
.asm-security-value {
  font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 100px;
  background: var(--sunk); color: var(--ink-2);
}
.asm-security-value.restricted { background: #e8f5ee; color: #12915a; }

/* Assessment version row */
.asm-version-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border-radius: 10px; background: var(--paper); border: 1px solid var(--hair);
}
.asm-version-row.current { box-shadow: inset 3px 0 0 var(--blue); }
.asm-version-num { font-family: "Spline Sans Mono", monospace; font-size: 13px; font-weight: 600; color: var(--ink); flex: none; }
.asm-version-state { flex: 1; font-size: 13px; color: var(--ink-2); }
.asm-version-by { font-size: 12px; color: var(--ink-3); flex: none; }
.asm-version-date { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; flex: none; }

/* Assessment command area */
.asm-cmd { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; flex-wrap: wrap; }
.asm-search {
  padding: 8px 14px; border-radius: 9px; border: 1px solid var(--hair);
  font-size: 13.5px; min-width: 220px; background: var(--paper); color: var(--ink);
}

@media (max-width: 734px) {
  .asm-stats { gap: 16px; }
  .asm-grid { grid-template-columns: 1fr 1fr; }
  .asm-row { flex-wrap: wrap; }
  .asm-row .asm-info { width: 100%; margin-top: 4px; }
}

/* Active tab state for assessment tabs */
.asm-tab-on {
  background: var(--paper) !important;
  color: var(--ink) !important;
  box-shadow: 0 1px 3px rgba(0,0,0,.06) !important;
}

/* Modify panel */
.asm-modify-panel { animation: lx-card-in .2s var(--ease) both; }
.asm-modify-panel input[type="range"] {
  -webkit-appearance: none; appearance: none;
  height: 4px; border-radius: 2px; background: var(--sunk); outline: none;
}
.asm-modify-panel input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 50%; background: var(--blue); cursor: pointer;
}

/* Chat panel */
.asm-chat-panel { animation: lx-card-in .2s var(--ease) both; }
.asm-ask-chip {
  padding: 5px 10px; border-radius: 8px; border: 1px solid var(--hair);
  background: var(--paper); font-size: 12px; color: var(--ink-2);
  cursor: pointer; transition: background .14s var(--ease);
}
.asm-ask-chip:hover { background: var(--sunk); }

/* Preview mode */
  .asm-previewing { position: relative; }
  .asm-previewing::before {
    content: 'PREVIEW MODE';
    position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
    padding: 6px 16px; border-radius: 100px; z-index: 100;
    background: var(--amber); color: #fff; font-size: 11px; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
  }



/* ==========================================================================
   Classes
   The courses a teacher put this student in, and the work set in them. One
   card to a course, with room to breathe: the course and who teaches it, how
   far through it they are, then the work — because that is the order the
   questions come in.
   ========================================================================== */
.lx-classes { display: grid; gap: 22px; margin-top: 30px; }
.lx-class {
  padding: 26px 28px 22px; border-radius: 22px; background: var(--paper);
  border: 1px solid var(--hair);
}
.lx-class-head { display: flex; align-items: center; gap: 16px; }
.lx-class-head .ic {
  flex: none; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 16px;
}
.lx-class-head .ic svg { width: 26px; height: 26px; }
.lx-class-txt { flex: 1; min-width: 0; display: grid; gap: 3px; }
.lx-class-txt h2 {
  margin: 0; font-family: var(--font); font-size: 22px; font-weight: 600; letter-spacing: -.02em; color: var(--ink);
}
.lx-class-who { margin: 0; font-size: 14px; color: var(--ink-2); }
.lx-class-head .lx-btn { flex: none; }
.lx-class-bar { display: flex; align-items: center; gap: 14px; margin-top: 20px; }
.lx-class-pct { flex: none; font-size: 13px; font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.lx-class-bar i { flex: 1; height: 6px; border-radius: 3px; background: var(--sunk); overflow: hidden; }
.lx-class-bar i b { display: block; height: 100%; border-radius: 3px; background: var(--blue); transition: width .5s var(--ease); }
.lx-class-work { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--hair); }
.lx-class-h { margin: 0 0 12px; font-family: var(--font); font-size: 13px; font-weight: 600; color: var(--ink-2); }
.lx-class-none { margin: 0; font-size: 14.5px; color: var(--ink-3); }
.lx-work { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.lx-work-row {
  display: flex; align-items: center; gap: 16px; padding: 12px 14px; border-radius: 14px;
  transition: background .15s var(--ease);
}
.lx-work-row:hover { background: var(--sunk); }
.lx-work-txt { flex: 1; min-width: 0; display: grid; gap: 2px; }
.lx-work-txt b { font-size: 15.5px; font-weight: 500; color: var(--ink); }
.lx-work-txt span { font-size: 13px; color: var(--ink-3); }
.lx-work-txt span:empty { display: none; }
.lx-work-due { flex: none; }
