/*
 * Sikai — student theme.
 *
 * Every rule is nested under .sikai-student. stylesheet_link_tag :app serves
 * every stylesheet in this directory on every page, so an unscoped rule here
 * would restyle the admin, and an unscoped admin rule would restyle this.
 *
 * Identity comes from the Claude Design project "Sikai — Lesson Flow"
 * (imported 2026-08-18), with one departure: the design set copy in Manrope
 * and every number in IBM Plex Mono, and this surface is now ONE family --
 * see --s-font. Blue #185888 on paper #F7F6F4, near-black #17181A reserved for the one
 * payoff surface per screen. It replaces the sky-blue/Habre theme that
 * shipped through Phase 5 -- see .planning/ROADMAP.md, "Design refresh".
 */

.sikai-student {
  /* ---- Palette -------------------------------------------------------
     Six values do all the work. Blue is the only accent a child taps;
     green means "that was right"; gold means "try again" and also carries
     the streak, because both are warm rather than punishing. Red exists in
     the design system for admin-side severity and, until D-A, was absent
     from every student surface without exception (D-02: nothing near a
     wrong answer may read as failure). D-A narrows that, not repeals it: a
     primary child (grades 1-5) still never sees it -- everything below still
     applies to them unchanged. Only the secondary register (grade 6+, a
     student sitting SEE exam practice) gets the design's red, and only for
     one thing: the wrong-answer tone in the Feedback section, behind
     --s-error-tint/--s-error-deep further down and the
     .sikai-student.sikai-student--secondary selector that gates them. */
  /* The brand blue, kept in step with --sk-accent in tokens.css by hand --
     this surface deliberately owns its own copy. See that token for why
     it is the logo's blue rather than the design file's. */
  --s-blue:        #185888;
  --s-blue-deep:   #12466B;
  --s-blue-tint:   #E8F0F6;

  --s-ink:         #17181A;
  --s-ink-2:       #3D4149;
  --s-ink-3:       #5C6069;
  --s-mute:        #71757E;
  --s-mute-2:      #9A9EA6;

  --s-paper:       #F7F6F4;
  --s-canvas:      #EFEEEB;
  --s-surface:     #FFFFFF;
  --s-chalk:       #F2F1EE;

  /* Whatever the page itself is made of, which is not the same question as
     --s-paper. Paper is also a tint used INSIDE white cards (a worked step,
     a stat tile, one half of the missing-figure stripe), so anything that
     had to mean "match the page behind me" -- the body, and the lesson
     flow's sticky head and foot, which have to disappear into it -- read
     --s-paper and got the right answer only because the two happened to
     agree. They stop agreeing at 720px, where the page steps back to canvas
     grey and those in-card tints must not follow it. This token is the half
     that moves; --s-paper is the half that stays. */
  --s-page:        var(--s-paper);

  --s-green:       #147A5A;
  --s-green-tint:  #E6F4EF;

  --s-gold:        #C9A227;
  --s-gold-deep:   #8A6D12;
  --s-gold-tint:   #FBF3DC;

  --s-line:        rgba(23, 24, 26, .08);
  --s-line-strong: rgba(23, 24, 26, .12);
  --s-line-faint:  rgba(23, 24, 26, .06);

  /* A locked lesson is a "not yet", not a failure -- the neutral chalk
     grey, never the gold "try again" pair above and never anything red. */
  --s-locked:      #C4C2BD;
  --s-locked-ink:  #71757E;

  /* ---- Geometry ------------------------------------------------------
     4px spacing grid, 9/14/18/26px radii, straight from the design. */
  --s-r-sm:        9px;
  --s-r:           14px;
  --s-r-lg:        18px;
  --s-r-xl:        26px;
  --s-pill:        999px;
  --s-tap:         48px;
  --s-gap:         12px;
  --s-pad:         16px;

  /* ---- Type ----------------------------------------------------------
     ONE TYPEFACE. Dosis carries every sentence, every number, every
     fraction, every XP value and every micro-label on every screen a child
     sees -- including the sign-in screens in student-auth.css, which used
     to be set in Manrope and so made the child's surface a THIRD face
     rather than a second one.

     It replaces a Dosis/IBM Plex Mono split. What that split bought was
     figures that line up, because a monospace holds a column of numbers in
     line by construction, and it is worth being precise about what is lost:
     Dosis has NO `tnum` feature (verified with fontTools) and its numerals
     are severely proportional -- a "1" is 209 units against a "0" at 521.
     So there is no CSS that can give this surface tabular figures. Anywhere
     a number CHANGES IN PLACE or sits in a column, the box has to be sized
     or centred so the digits cannot shift it -- see .s-xp-tick and
     .s-pin-field. Do not assume a number is safe here because it looks
     right with the value it happens to have today; check it with a 1 in it.

     Dosis rather than Manrope, and only here: rounded terminals and open
     counters read as friendlier to a nine-year-old than Manrope's flatter
     geometry, which stays on the staff and admin screens where "friendly"
     is not the job. Both are variable files, so this costs one request
     either way -- 30 KB against Manrope's 24.

     Baloo 2 second, and it is not a fallback in the usual sense. CSS
     resolves font-family PER GLYPH, so a Latin letter takes Dosis and a
     Devanagari letter falls through to Baloo 2 -- which means a Nepali and
     an English word in one sentence are set in two different faces, with
     visibly different weight and rhythm. That seam is a deliberate,
     accepted trade: Dosis has NO Devanagari at all (verified two ways --
     per-glyph width against two fallbacks, and document.fonts.load, which
     reports 1 face for Latin and 0 for क), so the alternative is not "one
     face everywhere" but "Nepali in whatever the phone happens to have".
     Baloo 2 is drawn by Ek Type for Devanagari and Latin together, so it is
     at least a considered partner rather than an accident of the device.
     Revisit when the language phase makes Nepali the primary script. */
  --s-font: Dosis, "Baloo 2", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --s-text:    15.5px;
  --s-text-sm: 13px;
  --s-text-lg: 18px;
  --s-text-xl: 26px;

  /* ---- Column --------------------------------------------------------
     The one width every part of this surface lines up on, and the gutter
     that column is inset by. Declared here, on the body class, so the
     header bar, the desktop nav, the screen and the tab bar all read the
     same two numbers and cannot drift apart -- the same job --sk-column
     does for the platform shell (see the .sk-shell comment in staff.css).

     Before this, the screen capped at 560/680 while the header capped at
     1080, so on a laptop the wordmark sat 200px to the left of the content
     it was supposed to head, and the tab bar stayed at 560 while the
     content it sits under had already widened to 680.

     The steps are in the media queries at the end of the "Wider viewports"
     section below; 780px is deliberately the platform shell's own column,
     so a child's screen and a staff screen are the same width of page. */
  --s-column: 560px;
  --s-gutter: 16px;

  margin: 0;
  /* 100vh first: WebViews that do not parse dvh drop that declaration and keep
     this one, so the background still fills the screen on older Android. */
  min-height: 100vh;
  min-height: 100dvh;
  font-family: var(--s-font);
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.6;
  color: var(--s-ink);
  background: var(--s-page);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

/* ---- Secondary register (grade 6+, Classroom#secondary?) ---------------
   .sikai-student--secondary sits alongside .sikai-student on <body>, never
   instead of it (layouts/student.html.erb), so every selector here is the
   compound `.sikai-student.sikai-student--secondary`.

   The design calls these "two registers, one shell": a grade 5 child is
   rewarded for effort, a grade 9 student is shown marks and readiness. That
   is a difference in tone and celebration, not in palette -- so unlike the
   old purple/violet split, secondary keeps every colour token and changes
   only what shouts. Canvas goes a shade cooler and the display sizes come
   down, which is the whole of it. */
.sikai-student.sikai-student--secondary {
  --s-paper:   var(--s-canvas);
  --s-text-xl: 23px;
  --s-text-lg: 17px;

  /* Declared here, not on bare .sikai-student, so the two reds do not exist
     at all for a primary child -- a future one-line rule under plain
     .sikai-student that referenced --s-error-* would previously have
     compiled silently and painted red for a seven-year-old; now the
     variables themselves are undefined outside this compound selector and
     such a rule would resolve to nothing. Only ever used under
     .sikai-student--secondary -- see the D-A note in the feedback section. */
  --s-error-tint:  #FBEDEB;
  --s-error-deep:  #8E2B20;
}

/* ---- Shell ------------------------------------------------------------ */

/* The top inset rides on whatever is actually topmost, which changes at 720px:
   below it the deskbar is display:none and this <main> is the first thing on
   screen, above it the deskbar is (and carries the inset instead, below). The
   native shells draw no chrome of their own and the layout sets
   viewport-fit=cover, so without this the first line of every screen sits
   under the notch. A padding shorthand's third value is the bottom -- putting
   a -top inset there pads the screen underneath itself, which is the bug this
   replaces. */
.sikai-student .s-screen {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--s-column);
  margin: 0 auto;
  padding: calc(20px + env(safe-area-inset-top)) var(--s-gutter) 32px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Room for the fixed tab bar, which overlaps the end of the scroll. Only
   pages that render it get the padding -- the sign-in screen has no tab bar
   and would otherwise sit 76px off the bottom of a short phone. */
.sikai-student:has(.s-tabs) .s-screen {
  padding-bottom: 96px;
}

.sikai-student * {
  box-sizing: border-box;
}

/* flash.css caps its container at 1024px for the whole product, which on this
   surface is wider than every other thing on the page -- a "PIN is wrong"
   banner that starts 130px to the left of the field it is about. It sits on
   the column with the rest of the screen instead. Same rule, same reason, in
   parents.css. */
.sikai-student .flash-container {
  max-width: var(--s-column);
  padding-inline: var(--s-gutter);
}

/* ---- Undoing application.css's unscoped element rules -------------------
   application.css styles bare `h1..h6` and `a` with no scope at all, and
   :app serves every stylesheet in this directory on every page. A directly
   applied rule beats an inherited value no matter how specific the
   inheriting selector is, so `h1..h6 { color: var(--color-text-primary) }`
   painted this theme's headings slate-900 -- including the ones sitting on
   the near-black hero, where they went invisible. Its `a:hover {
   text-decoration: underline }` likewise underlined every tile and tab on
   hover.

   `inherit` rather than a token: a heading should take the colour of
   whatever surface it is on, which is what makes one .s-hero rule enough to
   turn its whole contents white. Components that want a specific colour
   (.s-worked__title, .s-hero__eyebrow) still set one and still win on
   specificity. */
.sikai-student h1,
.sikai-student h2,
.sikai-student h3,
.sikai-student h4,
.sikai-student h5,
.sikai-student h6 {
  color: inherit;
}

.sikai-student a,
.sikai-student a:hover {
  color: inherit;
  text-decoration: none;
}

/* The browser's own `[hidden] { display: none }` is a plain attribute
   selector, so ANY class rule here that sets `display` silently defeats it.
   That is not a nicety: the self-check reveal (.s-reveal, display:flex) and
   the commit row (.s-self-check__commit) are `hidden` until the child asks
   for the answer, and without this they render the answer and the solution
   underneath the question they have not attempted yet. Same for the PIN
   keypad and the worked example's steps.

   !important because the alternative is remembering to re-assert
   `display:none` on every future component that happens to be both flex and
   hideable, and the failure mode is a child being shown the answer. */
.sikai-student [hidden] {
  display: none !important;
}

/* One visible focus treatment for every interactive thing on the screen, so
   a keyboard user never has to guess which element the browser considers
   focused. */
.sikai-student a:focus-visible,
.sikai-student button:focus-visible,
.sikai-student input:focus-visible,
.sikai-student [tabindex]:focus-visible {
  outline: 2px solid var(--s-blue);
  outline-offset: 2px;
  border-radius: var(--s-r-sm);
}

/* tabindex="-1" marks a landing zone, not a control: quiz_controller moves
   focus to the "Topic done!" heading and to the feedback line so a screen
   reader announces them after a frame swap. Those elements are unreachable
   by Tab, so there is no keyboard position to indicate -- and Chrome does
   match :focus-visible on programmatic focus, which drew a 2px blue box
   around the completion heading. Focus still moves; it just stops shouting. */
.sikai-student [tabindex="-1"]:focus,
.sikai-student [tabindex="-1"]:focus-visible {
  outline: none;
}

/* ---- Type ------------------------------------------------------------- */

.sikai-student h1 {
  margin: 0;
  font-size: var(--s-text-xl);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.025em;
  color: var(--s-ink);
}

.sikai-student h2 {
  margin: 0;
  font-size: var(--s-text-lg);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.015em;
}

.sikai-student p {
  margin: 0;
}

/* The design's eyebrow: mono, uppercase, widely tracked, small enough that it
   labels the thing below without competing with it. Used for every section
   heading that is a category rather than a sentence. */
.sikai-student .s-section-title {
  margin: 0;
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-muted {
  font-size: var(--s-text-sm);
  color: var(--s-mute);
}

.sikai-student .s-empty {
  font-size: var(--s-text-sm);
  color: var(--s-mute);
}

.sikai-student .s-label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-link {
  display: inline-block;
  min-height: var(--s-tap);
  padding: 14px 0;
  background: none;
  border: 0;
  font-family: inherit;
  font-size: var(--s-text-sm);
  font-weight: 700;
  color: var(--s-blue);
  text-decoration: none;
  cursor: pointer;
}

.sikai-student .s-link:hover {
  color: var(--s-blue-deep);
  text-decoration: underline;
}

/* ---- Surfaces --------------------------------------------------------- */

.sikai-student .s-card,
.sikai-student .s-panel {
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  padding: 18px;
}

.sikai-student .s-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* A titled block: the mono eyebrow and the thing it labels, tighter together
   than .s-screen's own 20px rhythm so the pair reads as one unit. */
.sikai-student .s-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sikai-student .s-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.sikai-student .s-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sikai-student .s-nav {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* .s-screen's own 20px rhythm stops at its direct children, and the practice
   and check screens put their whole body inside one <turbo-frame> -- so
   everything from the question counter down to the "Back to ..." link sat in
   a single unspaced block. The frame carries the rhythm on instead. */
.sikai-student turbo-frame {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* The reaction and the running points total are replaced together as one
   node (see learn/practices/_feedback), so they need their own tighter
   spacing rather than the frame's. */
.sikai-student .s-feedback-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ---- Buttons ----------------------------------------------------------
   Filled blue is the one thing to do next; there is never more than one on
   a screen. Everything else is an outline or a plain link, so "the blue
   one" stays a reliable instruction for a child who cannot yet read the
   label quickly. */

.sikai-student .s-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--s-tap);
  padding: 14px 22px;
  border: 0;
  border-radius: var(--s-r);
  background: var(--s-blue);
  color: #fff;
  font-family: var(--s-font);
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, transform .15s ease;
}

.sikai-student .s-button:hover {
  background: var(--s-blue-deep);
}

.sikai-student .s-button:active {
  transform: translateY(1px);
}

.sikai-student .s-button[disabled] {
  background: var(--s-chalk);
  color: var(--s-mute-2);
  cursor: default;
  transform: none;
}

.sikai-student .s-button--back,
.sikai-student .s-button--secondary,
.sikai-student .s-button--ghost {
  background: var(--s-surface);
  border: 1px solid var(--s-line-strong);
  color: var(--s-ink);
}

.sikai-student .s-button--back:hover,
.sikai-student .s-button--secondary:hover,
.sikai-student .s-button--ghost:hover {
  background: var(--s-chalk);
}

.sikai-student .s-button--hero {
  padding: 17px 28px;
  font-size: 16px;
}

/* ---- Tiles ------------------------------------------------------------
   One row per thing a child can open. The whole tile is the tap target, and
   it stays 48px tall even when the meta line is empty. */

.sikai-student .s-tile {
  display: flex;
  align-items: center;
  min-height: var(--s-tap);
  padding: 15px 16px;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}

.sikai-student a.s-tile:hover {
  border-color: rgba(24, 88, 136, .35);
}

.sikai-student a.s-tile:active {
  transform: translateY(1px);
}

.sikai-student .s-tile__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.sikai-student .s-tile__title {
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--s-ink);
}

.sikai-student .s-tile__meta {
  font-family: var(--s-font);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

/* ---- Subject cards -----------------------------------------------------
   The design's `subjectsFull`. Shared by /learn/subjects and, at a smaller
   size, the home grid (.s-subject--compact). */

.sikai-student .s-subject {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: var(--s-pad);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  background: var(--s-surface);
  text-decoration: none;
}

.sikai-student .s-subject__top {
  display: flex;
  align-items: center;
  gap: 11px;
}

.sikai-student .s-subject__chip {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 12px;
  background: var(--s-blue-tint);
  color: var(--s-blue);
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 700;
}

.sikai-student .s-subject__name {
  flex: 1;
  min-width: 0;
  font-family: var(--s-font);
  font-size: 14px;
  font-weight: 700;
  color: var(--s-ink);
}

.sikai-student .s-subject__pct {
  font-family: var(--s-font);
  font-size: 14px;
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-subject__meta {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--s-font);
  font-size: 11.5px;
  font-weight: 500;
  color: var(--s-mute);
}

.sikai-student .s-subject__next {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The shared progress track. Used by subject cards, chapter rows and the
   goal card, so all three read the same height and radius.

   Named .s-progress rather than the plan's .s-bar: .sikai-student .s-bar
   and .s-bar__fill already exist above (see "Progress: bars"), styling the
   progress screen's label+track+value mastery rows as a CSS grid. That
   selector, redefined here as a plain block track, would have landed later
   in the cascade and silently overridden the mastery rows' layout instead
   of adding a new component -- so this track gets its own name. */
.sikai-student .s-progress {
  display: block;
  overflow: hidden;
  width: 100%;
  height: 8px;
  border-radius: 4px;
  background: var(--s-chalk);
}

.sikai-student .s-progress__fill {
  display: block;
  height: 100%;
  background: var(--s-blue);
  transform-origin: left;
  animation: s-fill .6s ease both;
}

.sikai-student .s-progress__fill--done {
  background: var(--s-green);
}

/* ---- Continue ---------------------------------------------------------
   The one card on the home screen that is allowed to look like the answer
   to "what now?" -- blue-tinted rather than white, so it separates from the
   subject grid below without needing a second filled button. */

.sikai-student .s-continue {
  display: flex;
  flex-direction: column;
}

.sikai-student .s-continue__label {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-continue__clear {
  font-size: var(--s-text-sm);
  color: var(--s-ink-3);
}

.sikai-student .s-continue__clear b {
  display: block;
  margin-bottom: 4px;
  font-size: var(--s-text);
  font-weight: 700;
  color: var(--s-ink);
}

/* ---- Hero (progress screen) -------------------------------------------
   The near-black panel. One per screen, reserved for the moment that is the
   point of the screen -- here, the running total a child came to see. */

.sikai-student .s-hero {
  background: var(--s-ink);
  border: 0;
  border-radius: var(--s-r-xl);
  padding: 24px;
  color: #fff;
}

.sikai-student .s-hero__eyebrow {
  margin: 0;
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}

.sikai-student .s-hero__stats {
  display: flex;
  gap: 32px;
}

.sikai-student .s-hero__stat {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sikai-student .s-hero__value {
  font-family: var(--s-font);
  font-size: 40px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.03em;
  color: #fff;
}

.sikai-student .s-hero__label {
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}

.sikai-student .s-hero__empty {
  font-size: var(--s-text-sm);
  color: rgba(255, 255, 255, .66);
}

/* ---- Questions --------------------------------------------------------- */

.sikai-student .s-question {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sikai-student .s-question__prompt {
  font-size: var(--s-text-lg);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -.015em;
  color: var(--s-ink);
}

.sikai-student .s-choices {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sikai-student .s-choice {
  display: flex;
  align-items: center;
  min-height: var(--s-tap);
  padding: 14px 16px;
  background: var(--s-surface);
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r);
  font-family: var(--s-font);
  font-size: var(--s-text);
  font-weight: 600;
  text-align: left;
  color: var(--s-ink);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}

.sikai-student .s-choice:hover:not([disabled]) {
  border-color: var(--s-blue);
  background: var(--s-blue-tint);
}

/* Right: green fill, and the only place a tick appears in the quiz.
   Wrong: gold, and the button stays live -- the retry is the feedback
   (D-02). No red, no strike, nothing that reads as a mark against the
   child. */
.sikai-student .s-choice.is-correct {
  border-color: var(--s-green);
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-choice.is-try {
  border-color: var(--s-gold);
  background: var(--s-gold-tint);
  color: var(--s-gold-deep);
}

.sikai-student .s-choice[disabled] {
  cursor: default;
}

.sikai-student .s-numeric-form,
.sikai-student .s-task-form,
.sikai-student .s-self-check {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-numeric-input,
.sikai-student .s-numeric-form input[type="text"],
.sikai-student .s-self-check input[type="text"] {
  width: 100%;
  min-height: var(--s-tap);
  padding: 13px 16px;
  background: var(--s-surface);
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r);
  font-family: var(--s-font);
  font-size: 17px;
  font-weight: 500;
  color: var(--s-ink);
}

.sikai-student .s-numeric-input:focus,
.sikai-student .s-numeric-form input[type="text"]:focus,
.sikai-student .s-self-check input[type="text"]:focus {
  border-color: var(--s-blue);
  outline: none;
}

.sikai-student .s-numeric-input.is-correct {
  border-color: var(--s-green);
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-numeric-input.is-try {
  border-color: var(--s-gold);
  background: var(--s-gold-tint);
  color: var(--s-gold-deep);
}

/* ---- Self check -------------------------------------------------------- */

.sikai-student .s-self-check__commit {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-self-check__buttons {
  display: flex;
  gap: 8px;
}

.sikai-student .s-self-check__buttons .s-button {
  flex: 1;
}

.sikai-student .s-reveal {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  background: var(--s-chalk);
  border-radius: var(--s-r);
}

.sikai-student .s-reveal__row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--s-text);
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-reveal__label {
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-reveal__solution {
  font-size: var(--s-text-sm);
  font-weight: 500;
  line-height: 1.65;
  color: var(--s-ink-3);
}

/* ---- Feedback ---------------------------------------------------------
   What used to be Habre's speech bubble. The companion is retired with the
   sky-blue theme, but the thing it carried -- one short sentence reacting to
   the answer just given -- is the most important line on the quiz screen, so
   it keeps its own component rather than becoming ordinary body copy.

   D-A narrows D-02, not repeals it: "right" is always green, and "retry" is
   gold and marked with a repeat arrow, not a cross -- do it again, never you
   failed -- for every primary child (grades 1-5), full stop. The one
   exception is scoped to a single selector at the bottom of this section:
   under .sikai-student.sikai-student--secondary, a wrong answer takes the
   design's red instead of gold. spec/requests/learn/secondary_theme_spec.rb
   holds both halves of that split. */

.sikai-student .s-feedback {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--s-r);
  background: var(--s-chalk);
  animation: s-rise .25s ease both;
}

.sikai-student .s-feedback__mark {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--s-r-sm);
  background: var(--s-surface);
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 600;
  color: var(--s-mute);
}

/* Wraps the optional title and the message beneath it -- the flex child that
   used to be .s-feedback__text directly. flex: 1 carries over from that
   rule for the same reason it was there: without it a short title like "Not
   quite" leaves this block hugging the mark instead of spanning the row. */
.sikai-student .s-feedback__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 4px;
}

.sikai-student .s-feedback__title {
  margin: 0;
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
}

.sikai-student .s-feedback__text {
  font-size: var(--s-text);
  font-weight: 600;
  line-height: 1.5;
  color: var(--s-ink-2);
  opacity: .8;
}

.sikai-student .s-feedback--right {
  background: var(--s-green-tint);
}

.sikai-student .s-feedback--right .s-feedback__mark {
  color: var(--s-green);
}

.sikai-student .s-feedback--right .s-feedback__text {
  color: var(--s-green);
}

.sikai-student .s-feedback--retry {
  background: var(--s-gold-tint);
}

.sikai-student .s-feedback--retry .s-feedback__mark {
  color: var(--s-gold-deep);
}

.sikai-student .s-feedback--retry .s-feedback__text {
  color: var(--s-gold-deep);
}

/* The quiet tier (D-26): a number, not a party. */
.sikai-student .s-xp-tick {
  font-family: var(--s-font);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-flow__xp {
  flex: none;
  padding: 5px 10px;
  border-radius: var(--s-pill);
  background: var(--s-chalk);
  font-family: var(--s-font);
  font-size: 10px;
  font-weight: 600;
  color: var(--s-mute);
}

/* D-A. D-02 banned red on every child-facing surface; it is narrowed rather
   than lifted. Grades 1-5 keep the gold "try again" pair -- a wrong answer at
   nine years old must not read as failure. The secondary register, which the
   design writes as a different product voice for a student sitting SEE
   practice, gets the design's own red. The rule now lives in one selector
   instead of a blanket ban, and spec/requests/learn/secondary_theme_spec.rb
   holds both halves. */
.sikai-student.sikai-student--secondary .s-feedback--retry {
  background: var(--s-error-tint);
  color: var(--s-error-deep);
}

/* The container's own `color` above is inherited by .s-feedback__title (it
   carries none of its own), but .s-feedback__mark and .s-feedback__text
   each already carry an unconditional `.s-feedback--retry .s-feedback__*`
   gold-deep rule a few lines up -- a direct declaration on an element always
   wins over an inherited one, no matter how specific the ancestor's rule is,
   so without these two the icon and message would stay gold on a red field
   under the secondary register. */
.sikai-student.sikai-student--secondary .s-feedback--retry .s-feedback__mark,
.sikai-student.sikai-student--secondary .s-feedback--retry .s-feedback__text {
  color: var(--s-error-deep);
}

/* ---- Explanation, worked examples, experiments ------------------------- */

.sikai-student .s-explanation {
  font-size: var(--s-text);
  line-height: 1.7;
  color: var(--s-ink-2);
}

.sikai-student .s-worked {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: var(--s-pad);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  background: var(--s-surface);
}

/* Still used by learn/deep_lessons/_material (the AI "closer look" preview),
   which renders its own worked examples through this same controller and
   these same classes but is out of this task's scope. */
.sikai-student .s-worked__title {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-worked__prompt {
  margin: 0;
  font-family: var(--s-font);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--s-ink);
}

.sikai-student .s-worked__steps {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sikai-student .s-worked__step {
  padding: 13px 14px;
  border-radius: 13px;
  background: var(--s-paper);
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--s-ink);
  animation: s-rise .25s ease both;
}

/* The design highlights the newest step so a child's eye lands on what just
   arrived rather than re-reading from the top. */
.sikai-student .s-worked__step.is-latest {
  background: var(--s-blue-tint);
}

.sikai-student .s-worked__step--answer {
  font-family: var(--s-font);
  color: var(--s-green);
}

.sikai-student .s-worked__more {
  width: 100%;
  min-height: var(--s-tap);
  padding: 13px;
  border: none;
  border-radius: 13px;
  background: var(--s-ink);
  color: var(--s-surface);
  font-family: var(--s-font);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.sikai-student .s-worked__more.is-reset {
  border: 1px solid var(--s-line-strong);
  background: var(--s-surface);
  color: var(--s-ink-3);
}

/* Still used by learn/deep_lessons/_material -- see the .s-worked__title
   comment above. */
.sikai-student .s-worked__answer {
  padding: 12px 14px;
  border-radius: var(--s-r-sm);
  background: var(--s-green-tint);
  font-family: var(--s-font);
  font-size: var(--s-text);
  font-weight: 600;
  color: var(--s-green);
}

.sikai-student .s-experiment {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  padding: 18px;
}

.sikai-student .s-experiment__title {
  font-size: var(--s-text-lg);
  font-weight: 700;
  letter-spacing: -.015em;
}

.sikai-student .s-experiment__heading {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-experiment__materials,
.sikai-student .s-experiment__steps {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding-left: 20px;
  font-size: var(--s-text-sm);
  line-height: 1.6;
  color: var(--s-ink-2);
}

.sikai-student .s-experiment__result {
  padding: 12px 14px;
  border-radius: var(--s-r-sm);
  background: var(--s-blue-tint);
  font-size: var(--s-text-sm);
  line-height: 1.6;
  color: var(--s-ink-2);
}

.sikai-student .s-experiment__result-label,
.sikai-student .s-experiment__safety-label {
  display: block;
  margin-bottom: 4px;
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

/* Safety is the one student-facing place a warning colour is right: it is
   about a hot plate or a blade, not about an answer. Gold, not red -- the
   design reserves red for irreversible admin actions. */
.sikai-student .s-experiment__safety {
  padding: 12px 14px;
  border-radius: var(--s-r-sm);
  background: var(--s-gold-tint);
  font-size: var(--s-text-sm);
  line-height: 1.6;
  color: var(--s-gold-deep);
}

.sikai-student .s-experiment__safety .s-experiment__safety-label {
  color: var(--s-gold-deep);
}

/* ---- Figures ----------------------------------------------------------- */

.sikai-student .s-figures {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-figure {
  margin: 0;
  padding: 14px;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
}

.sikai-student .s-figure__img,
.sikai-student .s-figure svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}

.sikai-student .s-figure__caption {
  margin-top: 10px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--s-mute);
}

/* A figure drawn from numbers rather than served from disk (figures_helper).
   It is the same card, so it gets no separate treatment beyond a little more
   breathing room around the drawing. */
.sikai-student .s-figure--drawn {
  padding: 18px 14px;
}

.sikai-student .s-figure__missing {
  padding: 24px 14px;
  border-radius: var(--s-r-sm);
  background: repeating-linear-gradient(135deg, var(--s-canvas) 0 9px, var(--s-paper) 9px 18px);
  font-family: var(--s-font);
  font-size: 11px;
  color: var(--s-mute-2);
  text-align: center;
}

/* ---- Done / the reward moment -----------------------------------------
   The design shows rewards once, at the end, on the near-black panel. This
   is the payoff surface for the whole loop, so it is the only place the
   student app goes dark. */

.sikai-student .s-done {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sikai-student .s-done__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 112px;
  border-radius: var(--s-r-xl);
  background: var(--s-ink);
}

/* The tick that replaces the mascot: one mark, drawn in the accent, big
   enough to be the thing you see first. A bare disc read as a loading dot,
   so it carries the tick itself. */
.sikai-student .s-done__stage::after {
  content: "✓";
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--s-pill);
  background: var(--s-blue);
  box-shadow: 0 0 0 10px rgba(24, 88, 136, .18);
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  animation: s-pop .45s cubic-bezier(.2, .9, .3, 1.2) both;
}

.sikai-student .s-done__heading {
  margin: 0;
  font-size: var(--s-text-xl);
  font-weight: 800;
  letter-spacing: -.025em;
}

.sikai-student .s-done__subtitle {
  font-size: var(--s-text-sm);
  color: var(--s-mute);
}

.sikai-student .s-done__next {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px;
  background: var(--s-blue-tint);
  border-radius: var(--s-r-lg);
}

.sikai-student .s-done__next-label {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-done__next b {
  font-size: var(--s-text-lg);
  font-weight: 700;
  letter-spacing: -.015em;
}

/* Three plain counts, no score and no percentage (D-04). */
.sikai-student .s-tally {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.sikai-student .s-tally__item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 14px;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
}

.sikai-student .s-tally__item b {
  font-family: var(--s-font);
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--s-ink);
}

.sikai-student .s-tally__item span {
  font-family: var(--s-font);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

/* ---- Confetti ---------------------------------------------------------
   Kept from the previous theme -- the burst is the right instinct, the old
   colours were not. Recoloured to the design palette and still gated: the
   secondary register never renders it (D-26), and reduced-motion switches it
   off below. */

.sikai-student .s-confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.sikai-student .s-confetti i {
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  opacity: 0;
  animation: s-burst .9s ease-out both;
}

.sikai-student .s-confetti i:nth-child(1) { left: 22%; animation-delay: .02s; }
.sikai-student .s-confetti i:nth-child(2) { left: 40%; animation-delay: .06s; }
.sikai-student .s-confetti i:nth-child(3) { left: 55%; animation-delay: .04s; }
.sikai-student .s-confetti i:nth-child(4) { left: 68%; animation-delay: .09s; }
.sikai-student .s-confetti i:nth-child(5) { left: 80%; animation-delay: .01s; }

@keyframes s-burst {
  0%   { transform: translate(0, 0) rotate(0); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) rotate(var(--r)); opacity: 0; }
}

@keyframes s-pop {
  0%   { transform: scale(.82); opacity: 0; }
  60%  { transform: scale(1.04); }
  100% { transform: scale(1); opacity: 1; }
}

@keyframes s-rise {
  0%   { transform: translateY(10px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

/* ---- Progress: bars ---------------------------------------------------- */

.sikai-student .s-bars {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sikai-student .s-bar {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 12px;
  align-items: center;
}

.sikai-student .s-bar__label {
  grid-row: 1;
  grid-column: 1;
  font-size: var(--s-text-sm);
  font-weight: 700;
  color: var(--s-ink);
}

/* Explicit placement, not auto-flow. The markup order is label, track, value,
   and the track spans both columns -- so auto-placement pushed the value onto
   a third row of its own, leaving the percentage stranded under the bar
   instead of sitting opposite its label. */
.sikai-student .s-bar__value {
  grid-row: 1;
  grid-column: 2;
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  text-align: right;
  color: var(--s-mute);
}

.sikai-student .s-bar__track {
  grid-row: 2;
  grid-column: 1 / -1;
  height: 8px;
  border-radius: var(--s-pill);
  background: var(--s-chalk);
  overflow: hidden;
}

.sikai-student .s-bar__fill {
  display: block;
  height: 100%;
  border-radius: var(--s-pill);
  background: var(--s-blue);
  transform-origin: left;
  animation: s-fill .6s cubic-bezier(.2, .8, .3, 1) both;
}

@keyframes s-fill {
  0%   { transform: scaleX(0); }
  100% { transform: scaleX(1); }
}

/* ---- Progress: badges -------------------------------------------------- */

.sikai-student .s-badges {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sikai-student .s-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 10px;
  background: var(--s-paper);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r);
  text-align: center;
}

/* Sized for both: font-size still drives the seeded emoji that a badge with
   no drawn glyph falls back to (see Learn::BadgesHelper#badge_glyph), and the
   flex box centres the SVG that every current badge uses instead. */
.sikai-student .s-badge__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  font-size: 24px;
  line-height: 1;
  color: var(--s-blue);
}

.sikai-student .s-badge--locked .s-badge__icon {
  color: var(--s-locked-ink);
}

.sikai-student .s-badge__name {
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--s-ink);
}

.sikai-student .s-badge__hint {
  font-size: 10px;
  line-height: 1.4;
  color: var(--s-mute);
}

/* Silhouettes, not hidden (D-18): a locked badge is what makes a badge worth
   wanting before it exists. */
.sikai-student .s-badge--locked {
  background: none;
  border: 1.5px dashed var(--s-line-strong);
}

.sikai-student .s-badge--locked .s-badge__icon {
  filter: grayscale(1);
  opacity: .35;
}

.sikai-student .s-badge--locked .s-badge__name {
  color: var(--s-locked-ink);
}

/* ---- Progress: leaderboard --------------------------------------------- */

.sikai-student .s-board {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.sikai-student .s-board__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--s-line-faint);
}

.sikai-student .s-board__row:last-child {
  border-bottom: 0;
}

.sikai-student .s-board__rank {
  flex: none;
  width: 26px;
  font-size: 16px;
  text-align: center;
}

.sikai-student .s-board__face {
  display: flex;
  flex: none;
}

.sikai-student .s-board__name {
  flex: 1;
  min-width: 0;
  font-size: var(--s-text-sm);
  font-weight: 600;
  color: var(--s-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sikai-student .s-board__points {
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-board__mine {
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: var(--s-r-sm);
  background: var(--s-blue-tint);
  font-size: var(--s-text-sm);
  font-weight: 600;
  color: var(--s-blue);
}

/* ---- Progress: lesson rows and mastery bands --------------------------- */

.sikai-student .s-list__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--s-line-faint);
}

.sikai-student .s-list__row:last-child {
  border-bottom: 0;
}

.sikai-student .s-list__title {
  flex: 1;
  min-width: 0;
  font-size: var(--s-text-sm);
  font-weight: 600;
}

.sikai-student .s-band {
  flex: none;
  padding: 5px 10px;
  border-radius: var(--s-pill);
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.sikai-student .s-band--got_it {
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-band--getting_there {
  background: var(--s-blue-tint);
  color: var(--s-blue);
}

.sikai-student .s-band--keep_going {
  background: var(--s-gold-tint);
  color: var(--s-gold-deep);
}

/* ---- Sign in: keypad --------------------------------------------------- */

.sikai-student .s-pin-field {
  width: 100%;
  min-height: var(--s-tap);
  padding: 13px 16px;
  background: var(--s-surface);
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r);
  font-family: var(--s-font);
  font-size: 18px;
  font-weight: 500;
  color: var(--s-ink);
}

.sikai-student .s-pin-field:focus {
  border-color: var(--s-blue);
  outline: none;
}

.sikai-student .s-dots {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin: 24px 0;
}

.sikai-student .s-dot {
  width: 14px;
  height: 14px;
  border-radius: var(--s-pill);
  border: 1.5px solid var(--s-line-strong);
  background: transparent;
  transition: background-color .12s ease, border-color .12s ease;
}

.sikai-student .s-dot.s-on {
  background: var(--s-blue);
  border-color: var(--s-blue);
}

.sikai-student .s-keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.sikai-student .s-key {
  min-height: 62px;
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  background: var(--s-surface);
  font-family: var(--s-font);
  font-size: 24px;
  font-weight: 500;
  color: var(--s-ink);
  cursor: pointer;
  transition: background-color .1s ease;
}

.sikai-student .s-key:active {
  background: var(--s-blue-tint);
}

.sikai-student .s-key-quiet {
  background: transparent;
  border-color: transparent;
  color: var(--s-mute);
}

/* ---- Badge toast ------------------------------------------------------- */

.sikai-student .s-badge-toasts {
  position: fixed;
  left: 50%;
  bottom: 96px;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(420px, calc(100vw - 32px));
  transform: translateX(-50%);
  pointer-events: none;
}

.sikai-student .s-badge-toast {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--s-r-lg);
  background: var(--s-ink);
  color: #fff;
  box-shadow: 0 12px 32px rgba(23, 24, 26, .22);
  animation: s-rise .35s ease both;
}

.sikai-student .s-badge-toast__icon {
  font-size: 24px;
  line-height: 1;
}

.sikai-student .s-badge-toast__text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.sikai-student .s-badge-toast__text strong {
  font-size: 14px;
  font-weight: 700;
}

.sikai-student .s-badge-toast__text small {
  font-size: 11.5px;
  line-height: 1.4;
  color: rgba(255, 255, 255, .66);
}

/* ---- Deep lessons ------------------------------------------------------ */

.sikai-student .s-deep__heading {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-deep__words {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.sikai-student .s-deep__words li,
.sikai-student .s-deep__words span {
  padding: 6px 11px;
  border-radius: var(--s-pill);
  background: var(--s-chalk);
  font-family: var(--s-font);
  font-size: 11px;
  font-weight: 500;
  color: var(--s-ink-3);
}

.sikai-student .s-deep__questions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding-left: 20px;
  font-size: var(--s-text-sm);
  line-height: 1.65;
  color: var(--s-ink-2);
}

.sikai-student .s-deep-offer {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--s-blue-tint);
  border-color: rgba(24, 88, 136, .25);
  font-size: var(--s-text-sm);
  color: var(--s-ink-2);
}

/* ---- Empty curriculum -------------------------------------------------- */

.sikai-student .s-empty-curriculum {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sikai-student .s-empty-curriculum__title {
  font-size: var(--s-text-lg);
  font-weight: 700;
  letter-spacing: -.015em;
}

/* ---- Screen headers ----------------------------------------------------
   The design gives each screen its own header rather than one global bar:
   `hdr` on home (learn/shared/_head_home), `hdrPlain` on every list
   (_head_plain), `hdrFlow` in the lesson flow (_head_flow). They share
   this geometry so the three cannot drift apart. */

.sikai-student .s-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0 8px;
}

.sikai-student .s-head__back {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background: var(--s-chalk);
  color: var(--s-ink);
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
}

.sikai-student .s-head__where {
  flex: 1;
  min-width: 0;
}

.sikai-student .s-head__scope {
  margin: 0;
  font-family: var(--s-font);
  font-size: 10.5px;
  font-weight: 500;
  color: var(--s-mute-2);
}

.sikai-student .s-head__title {
  margin: 3px 0 0;
  font-family: var(--s-font);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--s-ink);
}

.sikai-student .s-head__meter {
  flex: none;
  padding: 7px 11px;
  border-radius: var(--s-pill);
  background: var(--s-blue-tint);
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  color: var(--s-blue);
}

/* The browser register's brand bar. Hidden on a phone: the design draws no
   banner there, and the desktop mock puts the wordmark beside the nav. */
.sikai-student .s-deskbar {
  display: none;
}

/* ---- Tab bar ----------------------------------------------------------
   The design's phone shell keeps three destinations permanently reachable.
   The app had none, which is why half the screens in learn/ carry a
   hand-placed "Back to ..." link and a comment explaining that without it a
   child is stranded. Those links stay -- they name where they go, which a
   generic tab cannot -- but the floor is now a tab bar rather than a
   dead end. Rendered only for a signed-in child (layouts/student.html.erb). */

.sikai-student .s-tabs {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 30;
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
  background: rgba(247, 246, 244, .92);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--s-line);
}

/* Tracks .s-screen's own max-width so the tabs sit under the content column
   rather than stretching to the full width of a tablet. --s-column rather
   than a repeated 560px: the column steps up at 640px and this used to be
   left behind at the phone width. */
.sikai-student .s-tabs__inner {
  display: flex;
  gap: 4px;
  width: 100%;
  max-width: var(--s-column);
  margin: 0 auto;
}

.sikai-student .s-tab {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: var(--s-tap);
  padding: 8px 4px;
  border-radius: var(--s-r);
  color: var(--s-mute);
  text-decoration: none;
}

/* The mark is now a glyph, not a filled square. It keeps the class name
   because aria-current already hangs off it below, and it keeps `opacity`
   rather than a second colour so the inactive state is one property in one
   place -- the SVG paints itself from currentColor. */
.sikai-student .s-tab__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: .55;
}

.sikai-student .s-tab__label {
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.sikai-student .s-tab[aria-current="page"] {
  color: var(--s-blue);
}

.sikai-student .s-tab[aria-current="page"] .s-tab__mark {
  opacity: 1;
}

/* The desktop form of the tab bar above -- same four destinations, from
   the same StudentNavigationHelper list (see learn/shared/_topnav), just
   drawn as a header bar instead of a fixed floor. Phone and tablet: the
   tab bar is the navigation, so the top nav is not drawn at all. Moved
   here from student-auth.css, which is the four sign-in screens' file --
   the top nav is shell, every signed-in screen carries it, so it belongs
   beside the tab bar it stands in for. */
.sikai-student .s-topnav {
  display: none;
}

/* ---- Wider viewports --------------------------------------------------
   The design's own note: every screen reflows rather than being
   letterboxed. The shell widens, the grid gains a column, nothing
   restructures.

   Three steps, and only the column and the gutter move at each: every
   piece of chrome reads those two, so widening the page is one edit rather
   than four that can disagree. The last step lands on 780px, which is the
   platform shell's --sk-column exactly -- a laptop shows a child's screen
   and a staff screen at the same measure. */

@media (min-width: 640px) {
  .sikai-student {
    --s-column: 680px;
    --s-gutter: 24px;
    --s-text-xl: 32px;
  }

  .sikai-student .s-screen {
    padding: calc(32px + env(safe-area-inset-top)) var(--s-gutter) 40px;
  }

  /* The subject grid deliberately does NOT gain a column here. Two-up is the
     design's own phone layout and it stays two-up at every width; the tiles
     widen instead. This used to step to three, which is the restructuring
     parents.css argues against in its own words -- "nothing restructures and
     nothing goes multi-column" -- and it turned a short list of subjects into
     something that read as a dashboard rather than as the next thing to open.
     DESIGN-02. */
}

/* ---- The reading register ----------------------------------------------
   The page steps back, at the same 720px step parents.css uses and for the
   reason stated there: the phone column has already run out of page before a
   portrait tablet does, and a 780px strip running the full height of a
   1440px screen is not a design, it is a screenshot.

   This used to sit at 960px while the shell stayed a flat panel at every
   width; DESIGN-02 moved it down so the shell change and the navigation
   swap happened together, which is what parents.css does and what makes the
   two surfaces read as one product.

   The two have since been separated again -- not to different widths, which
   is what DESIGN-02 was right to rule out, but to different *questions*.
   How much room is there is a width question and stays here. Which nav fits
   the hands holding it is an input question and lives in the pointer query
   below. A tablet answers the first like a laptop and the second like a
   phone, and only asking both gets it right. Kept apart from the 1024px
   step further down for the reason stated there. */
@media (min-width: 720px) {
  /* The page stops being the screen. On a phone the near-white paper IS the
     surface a child reads on, so it stays; from here up it steps back to the
     canvas grey and the white cards on it become cards rather than a flat
     white-on-white list. Straight from parents.css's own note. */
  .sikai-student {
    --s-page: var(--s-canvas);
  }

  /* The column stops being an invisible measure and becomes a thing with an
     edge: paper, ruled down both sides, running the full height of the page
     with the canvas either side of it. Below 720px there is no canvas to sit
     on -- the column IS the screen -- so it gets none of this.

     Two sides, not four, and no radius. A rounded sheet floating in the
     middle would have to end somewhere, and the lesson flow's sticky head
     (position: sticky, top: 0) pins to the top of the VIEWPORT, so on any
     screen taller than its content it would pin above the sheet it belongs
     to and read as a loose strip. Ruling only the sides sidesteps that: the
     column has no top or bottom to escape from, and the head stays inside
     the two rules at every scroll position.

     --s-page is redeclared here rather than left at the canvas the body
     took, because from this element down "the page" means this column. That
     is what carries the sticky head and the sticky foot's fade with it, and
     why they match the paper instead of showing as strips on it. */
  .sikai-student {
    display: flex;
    flex-direction: column;
  }

  .sikai-student .s-screen {
    --s-page: var(--s-paper);
    flex: 1;
    background: var(--s-page);
    border-inline: 1px solid var(--s-line);
  }

  /* Deliberately NOT multi-column. parents.css argues the same for the same
     reason -- "a parent screen is a short list of children and a wallet, and
     it does not want two columns at any width" -- and a child's screen is a
     short list of subjects under one thing to pick up next. DESIGN-01 made
     this grid two-up on desktop; it read as a dashboard rather than as the
     one next thing to do, so DESIGN-02 put it back. The tiles simply widen. */
  .sikai-student .s-stats {
    gap: 12px;
  }
}

/* ---- The navigation register ------------------------------------------
   Which nav a child gets is a question about their thumbs, not about their
   screen, so it is asked with (pointer: fine) and not with a width alone.

   These rules used to sit in the 720px block above, and DESIGN-02's own
   note there conceded the cost: "a portrait tablet now gets the top nav
   rather than the bottom tab bar -- deliberate: at that width the bar is a
   phone affordance stretched thin." The concession was made about laptops
   and an iPad fell into it by 48px. A bar is not a phone affordance, it is
   a touch affordance: on a tablet held in two hands the thumbs rest at the
   bottom edge, which is exactly where the tab bar already is and exactly
   where a top nav is not. Stretched thin was the wrong diagnosis -- the bar
   is centred and capped by --s-column like everything else, so it never
   stretches at all.

   Width still decides everything above: the page steps back to canvas, the
   measure widens at 1024px, the cards become cards. A tablet gets all of
   that. It keeps the tab bar because it is a touch device, and a laptop
   with a touchscreen still reports pointer: fine and still gets the top
   nav, because its primary input is a trackpad.

   This is also what makes the Hotwire Native builds come out right without
   a second code path: an iPad WKWebView reports pointer: coarse, so the
   child inside the app gets the tab bar rather than a laptop's top nav.
   ApplicationHelper#turbo_native_app? is left alone and still unused -- a
   user-agent test would answer the wrong question here, since what matters
   is what is touching the glass and not what is wrapping the web view. */
@media (min-width: 720px) and (pointer: fine) {
  .sikai-student .s-deskbar {
    display: block;
    border-bottom: 1px solid var(--s-line);
    background: var(--s-surface);
  }

  /* From here up the deskbar is the topmost thing on screen, so it takes the
     top inset over from .s-screen -- and .s-screen gives it back, or a notched
     tablet in portrait (834pt, above this step) would inset twice. The bar's
     background has to reach the top edge to read as a bar, which is why the
     inset sits on the inner element rather than on .s-deskbar itself. */
  .sikai-student .s-deskbar__inner {
    display: flex;
    align-items: center;
    gap: 20px;
    width: 100%;
    max-width: var(--s-column);
    margin: 0 auto;
    padding: calc(10px + env(safe-area-inset-top)) var(--s-gutter) 10px;
  }

  .sikai-student .s-screen {
    padding-top: 32px;
  }

  /* The lockup, not the word: mark then drawn wordmark, the same pair every
     other surface carries. The bar is --s-surface, so the mark needs no chip
     of its own the way the dark staff header does. */
  .sikai-student .s-deskbar__brand {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .sikai-student .s-deskbar__mark {
    flex: none;
    width: 27px;
    height: 22px;
    background: url("/assets/sikai-mark-64ad84a4.png") center / contain no-repeat;
  }

  .sikai-student .s-deskbar__word {
    height: 16px;
    width: auto;
    display: block;
  }

  /* The platform's pill nav, not a dark bar. sa/_nav (.sk-tabs in staff.css)
     established this shape for the super-admin surface -- white field,
     centred pills, the current one filled with the accent tint -- and a
     child's laptop screen reading as the same product as a staff one is
     worth more than a second navigation idiom.

     It also retires the last two --sk-* references in this file: the dark
     bar was the only thing here still reaching into tokens.css's layer
     instead of this stylesheet's own. */
  .sikai-student .s-topnav {
    display: block;
  }

  .sikai-student .s-topnav__inner {
    display: flex;
    justify-content: center;
    gap: 6px;
    max-width: var(--s-column);
    margin: 0 auto;
    padding: 0 var(--s-gutter);
  }

  .sikai-student .s-topnav__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 0 14px;
    border-radius: 11px;
    color: var(--s-mute);
    font-family: var(--s-font);
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
  }

  /* The glyph carries the same dimmed/full treatment the phone's tab bar
     gives it, so one destination looks like itself in both forms. */
  .sikai-student .s-topnav__mark {
    display: flex;
    align-items: center;
    opacity: .55;
  }

  .sikai-student .s-topnav__link:hover {
    background: var(--s-chalk);
    color: var(--s-ink);
  }

  .sikai-student .s-topnav__link[aria-current="page"] {
    background: var(--s-blue-tint);
    color: var(--s-blue);
  }

  .sikai-student .s-topnav__link[aria-current="page"] .s-topnav__mark {
    opacity: 1;
  }

  /* The design's browser register: the same screens reflowed, never
     letterboxed. The tab bar goes because .s-deskbar's top nav has already
     taken its four destinations -- both render from
     StudentNavigationHelper's one list, so neither can lose a destination
     the other keeps. */
  .sikai-student .s-tabs {
    display: none;
  }

  .sikai-student:has(.s-tabs) .s-screen {
    padding-bottom: 32px;
  }

  /* The lesson flow's sticky footer is lifted clear of the fixed tab bar
     everywhere (.sikai-student:has(.s-tabs) .s-flow__foot, further down
     this file, specificity 0,3,0) -- but the tab bar is hidden in this same
     block, so where this query matches there is nothing left to clear.
     Reverts to bottom: 0. It has to travel with the tab bar and not with
     the width: a tablet keeps the bar, so it must keep the 60px lift too,
     or its one CTA sits under the tabs.
     Moved from student-auth.css (Task 15 Step 0), where :has(.s-topnav)
     bought this selector 0,4,0 -- one class-selector above the base rule's
     0,3,0, so it wins regardless of where either rule sits in the
     cascade. That still has to hold here: this rule now sits BEFORE the
     base rule in this same file (720px block above, base rule further
     down), so at equal specificity source order would hand the win to the
     later, unconditional rule -- the wrong one -- reintroducing the 60px
     float this rule exists to undo. Dropping :has(.s-topnav) breaks
     desktop, not just a defunct workaround: it is always satisfied below
     720px too (both nav forms always render together), so it changes
     nothing there. */
  .sikai-student:has(.s-tabs):has(.s-topnav) .s-flow__foot {
    bottom: 0;
  }
}

/* The reading measure widens here, well after the 720px query above that
   swaps the tab bar for the top nav and steps the page back to grey. Two
   separate jobs, kept apart on purpose: 720px is where the phone column
   stops fitting the page, and 1024px is where the line length can grow
   without the measure getting hard to read. Moving both at once would make
   two things change at the same moment for no reason a reader could see. */
@media (min-width: 1024px) {
  .sikai-student {
    --s-column: 780px;
  }
}

/* ---- Lesson flow -------------------------------------------------------
   The design's vFlow: a head carrying the chapter and a five-segment
   progress bar, one step, and one control at the foot. Transcribed from the
   design source rather than approximated -- where a value looks arbitrary
   (a 4px bar, a 22px reward radius, a 54px payoff number) it is arbitrary
   there too.

   The head and the foot are sticky rather than fixed. Fixed would need the
   body to scroll under them, and this surface already has a fixed tab bar at
   the bottom; two fixed layers on a 4.5" screen leave a child reading a
   topic through a letterbox. Sticky keeps them in the normal flow, so the
   step scrolls past the head and the CTA settles above the tabs. */

.sikai-student .s-flow {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.sikai-student .s-flow__head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px 0 12px;
  margin: -20px 0 0;
  /* Opaque so the step scrolls under it rather than through it, and --s-page
     rather than --s-paper so it is opaque in the page's own colour at every
     width -- on canvas grey the paper value showed as a near-white strip
     across the top of every lesson, which is the one thing a sticky head
     must never be. */
  background: var(--s-page);
}

.sikai-student .s-flow__nav {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sikai-student .s-flow__back {
  flex: none;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  background: var(--s-chalk);
  color: var(--s-ink);
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
}

.sikai-student .s-flow__back:hover {
  background: #E7E6E2;
}

.sikai-student .s-flow__where {
  flex: 1;
  min-width: 0;
  text-align: center;
}

.sikai-student .s-flow__unit {
  margin: 0;
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-mute-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sikai-student .s-flow__chapter {
  margin: 3px 0 0;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--s-ink);
}

.sikai-student .s-flow__bars {
  display: flex;
  gap: 5px;
}

.sikai-student .s-flow__bar {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: #E9E8E4;
  transition: background .3s ease;
}

.sikai-student .s-flow__bar.is-on {
  background: var(--s-blue);
}

.sikai-student .s-flow__step {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.sikai-student .s-flow__title {
  margin: 0;
  font-size: var(--s-text-xl);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--s-ink);
}

/* A question's stem is a shade smaller than a screen title: it is the thing
   to read, but it sits above four choices that also need room. */
.sikai-student .s-flow__q {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--s-ink);
}

.sikai-student .s-flow__eyebrow {
  margin: 0;
  font-family: var(--s-font);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-flow__qhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.sikai-student .s-flow__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sikai-student .s-chip {
  padding: 6px 11px;
  border-radius: var(--s-pill);
  font-size: 12px;
  font-weight: 600;
}

.sikai-student .s-chip--subject {
  background: var(--s-blue-tint);
  color: var(--s-blue);
}

.sikai-student .s-chip--quiet {
  background: var(--s-chalk);
  font-family: var(--s-font);
  color: var(--s-mute);
}

/* "What's in this topic" on the intro. */
.sikai-student .s-flow__list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.sikai-student .s-flow__list-title {
  margin: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

.sikai-student .s-flow__steps {
  display: flex;
  flex-direction: column;
  gap: 13px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: s-flow-step;
}

.sikai-student .s-flow__steps li {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 14px;
  line-height: 1.4;
  counter-increment: s-flow-step;
}

/* Flex-centred, not `line-height: <box height>; text-align: center`.
   That pair centres a glyph only when the face's ascent and descent are
   balanced around it -- true of the IBM Plex Mono these boxes used to be
   set in, and not a property any replacement face is obliged to share.
   Flex centres the box whatever the metrics inside it. */
.sikai-student .s-flow__n {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--s-chalk);
  font-family: var(--s-font);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  color: var(--s-ink);
}

.sikai-student .s-flow__n::before {
  content: counter(s-flow-step);
}

/* The intro's promise. Ink, because it is the one payoff surface on that
   screen -- the same rule the reward card follows two steps later. */
.sikai-student .s-flow__reward-note {
  display: flex;
  gap: 11px;
  padding: 14px 16px;
  border-radius: var(--s-r-lg);
  background: var(--s-blue-tint);
}

.sikai-student .s-flow__reward-note p {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--s-ink-2);
}

.sikai-student .s-flow__reward-mark {
  flex: none;
  width: 5px;
  align-self: stretch;
  border-radius: 3px;
  background: var(--s-blue);
}

/* ---- Lesson flow: the reward step -------------------------------------- */

.sikai-student .s-flow__reward {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 26px 22px;
  border-radius: 22px;
  background: var(--s-ink);
  text-align: center;
}

.sikai-student .s-flow__reward-label {
  margin: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}

.sikai-student .s-flow__reward-xp {
  margin: 0;
  font-family: var(--s-font);
  font-size: 54px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.02em;
  color: #fff;
}

.sikai-student .s-flow__reward-unit {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s-blue);
}

.sikai-student .s-flow__reward-tiles {
  display: flex;
  gap: 8px;
  width: 100%;
  margin-top: 12px;
}

.sikai-student .s-flow__tile {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 11px;
  border-radius: 13px;
  background: rgba(255, 255, 255, .07);
}

.sikai-student .s-flow__tile b {
  font-family: var(--s-font);
  font-size: 18px;
  font-weight: 600;
  line-height: 1;
  color: #fff;
}

.sikai-student .s-flow__tile span {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}

/* One dark surface per screen. learn/shared/finished draws its celebration on
   a 112px ink stage of its own, which is right on the end-of-lesson check
   where nothing else is dark -- but on the reward step the ink card above it
   is already the payoff, and two stacked black blocks read as a mistake. The
   tick and the burst keep their place; only the slab behind them goes. */
.sikai-student .s-flow__step .s-done__stage {
  height: 88px;
  background: transparent;
}

.sikai-student .s-flow__badge {
  display: flex;
  align-items: center;
  gap: 14px;
}

.sikai-student .s-flow__badge-icon {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 15px;
  background: var(--s-blue-tint);
  position: relative;
}

.sikai-student .s-flow__badge-icon::after {
  content: "";
  position: absolute;
  inset: 15px;
  border-radius: 6px;
  background: var(--s-blue);
  transform: rotate(45deg);
}

.sikai-student .s-flow__badge-copy {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.sikai-student .s-flow__badge-copy b {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--s-ink);
}

/* The design brings the three cards in on a stagger rather than all at once:
   the number lands, then the badge, then where the child now stands in the
   class. One reading order, expressed in time. Covered by the blanket
   reduced-motion rule at the end of this file. */
.sikai-student .s-flow__reward {
  animation: s-pop .4s ease both;
}

.sikai-student .s-flow__badge {
  animation: s-pop .4s .12s ease both;
}

.sikai-student .s-flow__badge-icon {
  animation: s-halo 1.6s .5s ease-out 2;
}

.sikai-student .s-flow__step .s-board {
  animation: s-pop .4s .2s ease both;
}

/* ---- Lesson flow: the path map ----------------------------------------- */

.sikai-student .s-path {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 20px 18px;
  list-style: none;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
}

.sikai-student .s-path__row {
  display: flex;
  gap: 14px;
  align-items: center;
}

/* The connecting line between two rows, drawn off the mark rather than as a
   row of its own so the list stays one <li> per topic. */
.sikai-student .s-path__row + .s-path__row .s-path__mark::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 2px;
  height: 18px;
  transform: translateX(-50%);
  background: #E9E8E4;
}

.sikai-student .s-path__mark {
  position: relative;
  flex: none;
  width: 34px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sikai-student .s-path__mark::after {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #E9E8E4;
  border: 2px solid var(--s-locked);
  box-sizing: border-box;
}

.sikai-student .s-path__row--done .s-path__mark::after,
.sikai-student .s-path__row--done + .s-path__row .s-path__mark::before {
  background: var(--s-green);
  border-color: var(--s-green);
}

.sikai-student .s-path__row--current .s-path__mark::after {
  width: 18px;
  height: 18px;
  background: var(--s-blue);
  border-color: var(--s-blue);
}

/* The one to open next: ringed rather than filled, so it reads as waiting
   for the child rather than as somewhere they already are. */
.sikai-student .s-path__row--next .s-path__mark::after {
  background: var(--s-blue-tint);
  border-color: var(--s-blue);
}

.sikai-student .s-path__row--next .s-path__state {
  color: var(--s-blue);
}

.sikai-student .s-path__link {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 0;
  text-decoration: none;
}

.sikai-student .s-path__name {
  font-size: 14px;
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-path__row--current .s-path__name {
  font-size: 15px;
  font-weight: 700;
}

.sikai-student .s-path__state {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--s-mute-2);
}

.sikai-student .s-path__row--current .s-path__state {
  color: var(--s-blue);
}

.sikai-student .s-path__row--done .s-path__state {
  color: var(--s-green);
}

/* The design draws the connector as a coloured run between two marks: green
   behind you, blue at the one that is open, grey ahead. It is drawn on the
   rail rather than the row so a row's own height cannot stretch it. */
.sikai-student .s-path__rail {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  align-self: stretch;
}

.sikai-student .s-path__row--current .s-path__mark {
  animation: s-halo 1.8s ease-out infinite;
}

/* ---- Lesson flow: the hint -------------------------------------------- */

/* A <details>, so it opens with no JavaScript at all. The design's hint block
   is the same blue rail as the intro's promise: free, and never a
   telling-off (D-02). */
.sikai-student .s-hint {
  padding: 13px 15px;
  border-radius: var(--s-r);
  background: var(--s-blue-tint);
}

.sikai-student .s-hint__toggle {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--s-blue);
  cursor: pointer;
}

.sikai-student .s-hint__body {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--s-ink-2);
}

/* ---- Lesson flow: the tutor --------------------------------------------- */

/* Lives inside .s-hint's blue tint (see _panel.html.erb), so a divider
   stands in for a border and a background of its own -- either would make
   the tutor read as a second card competing with the hint instead of a
   continuation of it. */
.sikai-student .s-tutor {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--s-line);
}

.sikai-student .s-tutor__turns {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Side carries the distinction before colour does -- a six-year-old reads
   "which edge" faster than a label, the same left/right split any chat
   surface uses. Colour backs it up: the child's own turn keeps the blue
   this whole design already uses for "yours to act on", the tutor's turn
   sits on plain surface so it never competes with that blue. */
.sikai-student .s-tutor__turn {
  max-width: 88%;
  padding: 10px 13px;
  border-radius: var(--s-r-sm);
}

.sikai-student .s-tutor__turn--child {
  align-self: flex-end;
  background: var(--s-blue);
  color: #fff;
}

.sikai-student .s-tutor__turn--tutor {
  align-self: flex-start;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  color: var(--s-ink);
}

.sikai-student .s-tutor__who {
  margin: 0 0 2px;
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.sikai-student .s-tutor__turn--child .s-tutor__who {
  color: rgba(255, 255, 255, .75);
}

.sikai-student .s-tutor__turn--tutor .s-tutor__who {
  color: var(--s-mute-2);
}

.sikai-student .s-tutor__body {
  margin: 0;
  font-size: var(--s-text-sm);
  line-height: 1.45;
}

/* Blue, not green: green already means "that was right" here (D-02), and a
   free question is not a verdict on an answer. Blue is what the hint above
   already uses for "free" (see the comment on .s-hint), so this reuses that
   meaning rather than inventing a second one. */
.sikai-student .s-tutor__free {
  margin: 4px 0 0;
  font-family: var(--s-font);
  font-size: 10px;
  font-weight: 600;
  color: var(--s-blue);
}

/* ---- Openers a child can tap -------------------------------------------
   Shown only while the conversation is empty (learn/tutors/_form). Wrapping
   rather than scrolling: three short chips fit two lines on a 360px phone,
   and a horizontal scroller would hide the third behind an edge a child has
   no reason to suspect is there. */

.sikai-student .s-tutor__samples {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

.sikai-student .s-tutor__samples-lede {
  flex: 0 0 100%;
  margin: 0 0 2px;
  font-family: var(--s-font);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

/* Quieter than .s-tutor__send by design: these are a way in, not the action.
   The send button stays the only filled control in the panel, so a child who
   has typed something still has one obvious next tap. */
.sikai-student .s-tutor__sample {
  min-height: 34px;
  padding: 7px 12px;
  border: 1px solid var(--s-line-strong);
  border-radius: 999px;
  background: var(--s-surface);
  font-family: var(--s-font);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--s-ink-2);
  text-align: left;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}

.sikai-student .s-tutor__sample:hover {
  background: var(--s-blue-tint);
  border-color: var(--s-blue);
  color: var(--s-blue);
}

/* Focus is drawn, not left to the UA default: the chips sit on a white card
   inside another card, where a thin default ring disappears. */
.sikai-student .s-tutor__sample:focus-visible {
  outline: 2px solid var(--s-blue);
  outline-offset: 2px;
}

.sikai-student .s-tutor__form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.sikai-student .s-tutor__input {
  width: 100%;
  min-height: var(--s-tap);
  padding: 12px 14px;
  background: var(--s-surface);
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r);
  font-family: var(--s-font);
  font-size: var(--s-text-sm);
  color: var(--s-ink);
  resize: none;
}

.sikai-student .s-tutor__input:focus {
  border-color: var(--s-blue);
  outline: none;
}

.sikai-student .s-tutor__send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--s-tap);
  padding: 14px 18px;
  border: 0;
  border-radius: var(--s-r);
  background: var(--s-blue);
  color: #fff;
  font-family: var(--s-font);
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  transition: background-color .15s ease;
}

.sikai-student .s-tutor__send:hover {
  background: var(--s-blue-deep);
}

.sikai-student .s-tutor__thinking {
  margin: 12px 0 0;
  font-size: var(--s-text-sm);
  color: var(--s-mute);
  text-align: center;
}

/* Renders in the same slot the panel above would take (see _question.html.erb),
   on the same blue tint, so it stays a divider and two lines of type rather
   than a card of its own -- the wall is a "not right now", not an error, and
   D-02 rules out anything here reading as one. */
.sikai-student .s-tutor__wall {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--s-line);
}

.sikai-student .s-tutor__wall-title {
  margin: 0;
  font-size: var(--s-text-sm);
  font-weight: 700;
  color: var(--s-ink);
}

.sikai-student .s-tutor__wall-body {
  margin: 6px 0 0;
  font-size: var(--s-text-sm);
  line-height: 1.5;
  color: var(--s-ink-2);
}

/* ---- Lesson flow: the footer control ----------------------------------- */

.sikai-student .s-flow__foot {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding: 12px 0 8px;
  background: linear-gradient(to bottom, transparent, var(--s-page) 22%);
}

/* Sticky sticks to the bottom of the viewport, and the tab bar is fixed over
   that same edge -- so without this the one control on the screen scrolls
   under the tabs and cannot be pressed. Lifted clear by the bar's own height
   (its 6px padding, the 48px tap target inside it, and the safe-area inset a
   notched phone adds underneath), computed rather than a round number so the
   two cannot drift apart. */
.sikai-student:has(.s-tabs) .s-flow__foot {
  bottom: calc(60px + env(safe-area-inset-bottom));
}

.sikai-student .s-flow__cta {
  display: block;
  width: 100%;
  min-height: var(--s-tap);
  padding: 17px;
  border: 0;
  border-radius: 16px;
  background: var(--s-blue);
  color: #fff;
  font-family: var(--s-font);
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background .2s ease;
}

.sikai-student .s-flow__cta:hover {
  background: var(--s-blue-deep);
  color: #fff;
}

/* Not red, not a warning -- just off. A child who has not answered yet has
   done nothing wrong (D-02). */
.sikai-student .s-flow__cta:disabled {
  background: #E4E3DF;
  color: #A6A4A0;
  cursor: not-allowed;
}

.sikai-student .s-flow__cta:disabled:hover {
  background: #E4E3DF;
}

/* On a phone the one control on the screen is the width of the screen, and
   that is correct -- it is the whole point of the flow. On the 780px desktop
   column it stops being a button and becomes a bar, which is exactly the
   "stretched phone" read this surface is trying to lose. Capped and centred
   on the same axis as .s-flow__where above it, and only at the desktop step:
   a tablet is still held and still wants the thumb-width control. */
@media (min-width: 1024px) {
  .sikai-student .s-flow__cta {
    max-width: 340px;
    margin-inline: auto;
  }
}

/* ---- Reduced motion ---------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .sikai-student *,
  .sikai-student *::before,
  .sikai-student *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }

  .sikai-student .s-confetti {
    display: none;
  }
}

/* ---- Level meter and day bar --------------------------------------------
   The account screen's XP-into-level meter and the home screen's today
   header (Task 7 / Task 9 of the levels-coins-and-map plan). Here rather
   than student-auth.css: that file is the four sign-in screens', and these
   are learn-screen readouts belonging with the rest of the learn loop this
   file already carries. Loading after student-auth.css alphabetically also
   means nothing here can lose a cascade tie to it. */

/* --s-chalk, not the --sk-fill-3 this carried before: it is a progress
   track, and every other track on this surface (.s-progress, .s-bar) is
   already chalk. Two values apart on screen, one fewer idea in the file. */
.sikai-student .s-meter {
  height: 10px;
  border-radius: 999px;
  background: var(--s-chalk);
  overflow: hidden;
}

.sikai-student .s-meter__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--s-blue);
}

/* ---- Shop (Task 8) -------------------------------------------------------
   Each shop row is one button_to form, so the whole row is the tap target
   rather than just the price. Overrides .s-button's centred label with
   space-between so the item name and its cost sit at opposite edges of the
   same 48px target; .s-button[disabled] already covers the unaffordable
   look with no red involved. */

.sikai-student .s-shop-item {
  width: 100%;
  justify-content: space-between;
  gap: 12px;
}

/* ---- Wardrobe: what a child is wearing -----------------------------------
   The wardrobe (Task 7). A hero avatar with every owned item pre-drawn and
   `hidden` when unworn, plus tappable chips grouped by slot. .s-wardrobe__cell
   is a <form> (button_to wraps its button in one), so it is the grid item and
   the button inside it fills it.

   Named __cell/__chip rather than .s-chip: .s-chip is the topic intro's pill
   (see above), and a wardrobe chip that inherits its padding is coupled to a
   component it has nothing to do with. */

.sikai-student .s-wardrobe__hero {
  display: flex;
  justify-content: center;
  padding: 4px 0 10px;
}

.sikai-student .s-wardrobe__status { min-height: 1.2em; margin: 0 0 4px; }

.sikai-student .s-wardrobe__heading {
  margin: 13px 0 7px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--s-mute);
}

.sikai-student .s-wardrobe__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sikai-student .s-wardrobe__cell { margin: 0; }

.sikai-student .s-wardrobe__chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  width: 100%;
  min-height: var(--s-tap);
  padding: 9px 4px 7px;
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r-sm);
  background: var(--s-surface);
  color: var(--s-ink-3);
  font: inherit;
}

.sikai-student .s-wardrobe__chip--on {
  border-width: 2.5px;
  border-color: var(--s-blue);
  background: var(--s-blue-tint);
  color: var(--s-blue);
  padding: 8px 3px 6px;
}

.sikai-student .s-wardrobe__name { font-size: 10.5px; font-weight: 600; text-align: center; }
.sikai-student .s-wardrobe__chip--on .s-wardrobe__name { font-weight: 700; }

/* The hero's layers are toggled with the `hidden` attribute. The HTML UA
   stylesheet's [hidden] rule is not something to rely on for elements in the
   SVG namespace, so say it here rather than discover it in a browser. */
.sikai-student .s-wardrobe [hidden] { display: none; }

/* ---- Home --------------------------------------------------------------
   The design's four blocks: the goal card, the continue card, the subject
   grid and the badge strip. Replaces .s-strip and .s-daybar, which stacked
   the same numbers as a run of text.

   The badge strip card is .s-badgestrip, not the plan's .s-badges: the
   "Progress: badges" section above already owns .sikai-student .s-badges
   for the rewards screen's <ul> grid of full badge tiles, a different shape
   for a different element. Appending a second .s-badges rule down here
   would win the cascade (same specificity, later in the file) and silently
   turn that grid into this card's flex column -- the same failure mode the
   .s-bar/.s-progress note above warns about, just one collision the plan
   itself didn't catch this time. */

/* The tinted rounded box, the letter and its type all moved into
   shared/_avatar.html.erb, which paints them as SVG so that one partial can
   render on the student, teacher and parent surfaces alike. What is left here
   is only the 42px slot in the header's flex row. */
.sikai-student .s-avatar {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
}

.sikai-student .s-head__name {
  margin: 1px 0 0;
  font-family: var(--s-font);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--s-ink);
}

.sikai-student .s-streak {
  display: flex;
  flex: none;
  align-items: center;
  gap: 7px;
  padding: 8px 11px;
  border-radius: var(--s-pill);
  background: var(--s-ink);
}

.sikai-student .s-streak__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--s-gold);
}

.sikai-student .s-streak__count {
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  color: var(--s-surface);
}

/* Said, not shown. staff.css has its own copy of this under .sk-*; this
   surface needs one of its own because every rule here is scoped under
   .sikai-student and neither stylesheet may reach into the other. */
.sikai-student .s-hidden {
  position: absolute;
  overflow: hidden;
  width: 1px;
  height: 1px;
  clip-path: inset(50%);
  white-space: nowrap;
}

.sikai-student .s-goal,
.sikai-student .s-badgestrip {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-goal__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.sikai-student .s-goal__count {
  margin: 0;
  font-family: var(--s-font);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-stats {
  display: flex;
  gap: 8px;
}

.sikai-student .s-stat {
  flex: 1;
  padding: 11px 12px;
  border-radius: 13px;
  background: var(--s-paper);
}

.sikai-student .s-stat__value {
  margin: 0;
  font-family: var(--s-font);
  font-size: 17px;
  font-weight: 600;
  color: var(--s-ink);
}

.sikai-student .s-stat__value--coin {
  color: var(--s-gold);
}

/* The stat tiles' marks: one per tile, above the figure. Set on the muted
   label colour rather than the ink, because the number is what a child reads
   and a glyph that competes with it has taken the tile over. */
.sikai-student .s-stat__mark {
  display: block;
  margin-bottom: 6px;
  color: var(--s-mute-2);
}

/* Gold on the coins tile only. Coins are the one currency here that is not
   XP, and colour is how the design already says so. */
.sikai-student .s-stat__mark--coin {
  color: var(--s-gold);
}

/* The shop's price: glyph and figure as one unit, so the pair wraps together
   rather than leaving a coin stranded at the end of a line. */
.sikai-student .s-cost {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--s-gold-deep);
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.sikai-student .s-stat__label {
  margin: 4px 0 0;
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--s-mute-2);
}

/* After .s-stat__label above, not before it: identical specificity (0,2,0)
   means whichever comes last wins, and placed first this rule was overridden
   by the muted colour and the tile simply was not gold. */
.sikai-student .s-stat__label--coin,
.sikai-student .s-tile__meta.s-stat__label--coin {
  color: var(--s-gold-deep);
}

/* The one blue field on the screen, and the one thing the design expects a
   returning child to tap. */
.sikai-student .s-continue__card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px;
  border-radius: var(--s-r-lg);
  background: var(--s-blue);
  text-decoration: none;
}

.sikai-student .s-continue__card:hover {
  background: var(--s-blue-deep);
}

.sikai-student .s-continue__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.sikai-student .s-continue__label {
  font-family: var(--s-font);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .6);
}

.sikai-student .s-continue__arrow {
  font-size: 15px;
  font-weight: 600;
  color: var(--s-surface);
}

.sikai-student .s-continue__title {
  font-family: var(--s-font);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--s-surface);
}

.sikai-student .s-continue__meta {
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, .72);
}

.sikai-student .s-continue__track {
  display: block;
  overflow: hidden;
  width: 100%;
  height: 6px;
  margin-top: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .22);
}

.sikai-student .s-continue__fill {
  display: block;
  height: 100%;
  background: var(--s-surface);
}

.sikai-student .s-section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.sikai-student .s-section__more {
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 700;
  color: var(--s-blue);
  text-decoration: none;
}

.sikai-student .s-badgestrip__row {
  display: flex;
  gap: 9px;
}

.sikai-student .s-badgestrip__slot {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: var(--s-chalk);
}

/* An empty slot is what is still to earn, so it stays a plain tile. A filled
   one carries the badge's own glyph in the accent. */
.sikai-student .s-badgestrip__slot.is-on {
  background: var(--s-blue-tint);
  color: var(--s-blue);
}


.sikai-student .s-badgestrip__rest {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  border: 1.5px dashed var(--s-line-strong);
  border-radius: 14px;
  font-family: var(--s-font);
  font-size: 11px;
  font-weight: 600;
  color: var(--s-mute-2);
}

.sikai-student .s-tile--subject {
  display: flex;
  align-items: center;
  gap: 11px;
}

.sikai-student .s-tile__chip {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--s-blue-tint);
  color: var(--s-blue);
  font-family: var(--s-font);
  font-size: 13px;
  font-weight: 700;
}

/* ---- Chapter rows ------------------------------------------------------
   The design's `subjectChapters`. Four states plus locked; the tag copy and
   colours are Appendix A.2 of the DESIGN-01 spec. */

.sikai-student .s-summary {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-summary__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.sikai-student .s-summary__side {
  margin: 0;
  font-family: var(--s-font);
  font-size: 11px;
  font-weight: 600;
  color: var(--s-mute);
}

.sikai-student .s-summary__note {
  margin: 0;
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--s-mute);
}

.sikai-student .s-chapter {
  display: flex;
  flex-direction: column;
  gap: 11px;
  padding: 15px;
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  background: var(--s-surface);
  text-decoration: none;
}

.sikai-student .s-chapter--now {
  border-color: rgba(24, 88, 136, .35);
}

/* Not opacity: a blanket fade over the whole row multiplies down onto
   .s-chapter__meta too, and that line is lesson_unlock_hint(...) -- the
   sentence _lesson.html.erb exists to render because "'locked' on its own is
   not something a nine-year-old can act on." Faded to ~1.65:1 it was
   unreadable and the row was back to a bare LOCKED tag regardless. Dimmed
   instead with the same --s-chalk/--s-locked-ink pair used for a locked
   badge (.s-badge--locked .s-badge__name), which keeps every line of text
   at a real contrast ratio. */
.sikai-student .s-chapter--locked {
  background: var(--s-chalk);
  border-color: transparent;
}

.sikai-student .s-chapter--locked .s-chapter__name,
.sikai-student .s-chapter--locked .s-chapter__meta {
  color: var(--s-locked-ink);
}

.sikai-student .s-chapter__top {
  display: flex;
  align-items: center;
  gap: 13px;
}

.sikai-student .s-chapter__num {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  background: var(--s-chalk);
  color: var(--s-mute-2);
  font-family: var(--s-font);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
}

.sikai-student .s-chapter--done .s-chapter__num {
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-chapter--now .s-chapter__num {
  background: var(--s-blue);
  color: var(--s-surface);
}

.sikai-student .s-chapter__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.sikai-student .s-chapter__name {
  font-family: var(--s-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--s-ink);
}

.sikai-student .s-chapter--now .s-chapter__name {
  font-weight: 700;
}

.sikai-student .s-chapter__meta {
  font-family: var(--s-font);
  font-size: 10.5px;
  font-weight: 500;
  color: var(--s-mute-2);
}

.sikai-student .s-chapter__tag {
  flex: none;
  padding: 5px 9px;
  border-radius: var(--s-pill);
  background: var(--s-chalk);
  color: var(--s-mute-2);
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  line-height: 1.4;
}

.sikai-student .s-chapter--done .s-chapter__tag {
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-chapter--now .s-chapter__tag {
  background: var(--s-blue-tint);
  color: var(--s-blue);
}

/* ---- Topic rows --------------------------------------------------------
   The design's `topicList`, minus its `locked` state (D-D). The mark is a
   filled dot that becomes a rotated square once the topic is done, and
   pulses on the one the child should open next. */

.sikai-student .s-topic {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 15px;
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
  background: var(--s-surface);
  text-decoration: none;
}

.sikai-student .s-topic--now {
  border-color: rgba(24, 88, 136, .35);
}

.sikai-student .s-topic__mark {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--s-locked);
}

.sikai-student .s-topic__mark::after {
  content: "";
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--s-surface);
}

.sikai-student .s-topic--done .s-topic__mark {
  background: var(--s-green);
}

.sikai-student .s-topic--done .s-topic__mark::after {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  transform: rotate(45deg);
}

.sikai-student .s-topic--now .s-topic__mark {
  background: var(--s-blue);
  animation: s-halo 1.9s ease-out infinite;
}

.sikai-student .s-topic__mark--check {
  background: var(--s-chalk);
}

.sikai-student .s-topic__mark--check::after {
  width: 12px;
  height: 12px;
  border: 2.5px solid var(--s-ink);
  border-radius: 3px;
  background: none;
}

.sikai-student .s-topic__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.sikai-student .s-topic__name {
  font-family: var(--s-font);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--s-ink);
}

.sikai-student .s-topic--now .s-topic__name {
  font-weight: 700;
}

.sikai-student .s-topic__meta {
  font-family: var(--s-font);
  font-size: 10.5px;
  font-weight: 500;
  color: var(--s-mute-2);
}

.sikai-student .s-topic__tag {
  flex: none;
  padding: 5px 9px;
  border-radius: var(--s-pill);
  background: var(--s-chalk);
  color: var(--s-mute-2);
  font-family: var(--s-font);
  font-size: 9px;
  font-weight: 600;
  line-height: 1.4;
}

.sikai-student .s-topic--done .s-topic__tag {
  background: var(--s-green-tint);
  color: var(--s-green);
}

.sikai-student .s-topic--now .s-topic__tag,
.sikai-student .s-topic__tag--open {
  background: var(--s-blue-tint);
  color: var(--s-blue);
}

/* The only keyframe the design uses that this stylesheet did not already
   have -- s-pop, s-rise and s-fill were added with the 2026-08-18 refresh
   and already match. Covered by the blanket reduced-motion rule below. */
@keyframes s-halo {
  0%   { box-shadow: 0 0 0 0 rgba(24, 88, 136, .28); }
  100% { box-shadow: 0 0 0 16px rgba(24, 88, 136, 0); }
}

/* ---- Daily recall (RECALL-01) -------------------------------------------
   The home card (learn/home/_recall) and the walk's own "done, now the
   round" beat (learn/daily_tasks/show, the @done branch) are two views of
   the same short journey -- a five-question walk into a sixty-second round
   -- so they share this one block rather than each inventing a card
   vocabulary of their own. Same reasoning as .s-flow's reuse across the
   topic screens above. */

.sikai-student .s-recall {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sikai-student .s-recall__dots {
  display: flex;
  gap: 8px;
}

/* Paired buttons, same shape as .s-self-check__buttons: equal width, side
   by side, so neither reads as the only way off the screen. */
.sikai-student .s-recall__buttons {
  display: flex;
  gap: 8px;
}

.sikai-student .s-recall__buttons .s-button {
  flex: 1;
}

/* ---- Speed round (RECALL-01) ---------------------------------------------
   The one timed screen in the product. Every question ships with the page
   (see rounds/show's own comment on why), so nothing here waits on a
   network round-trip mid-round -- the clock is the only thing moving.

   speed_round_controller.js builds each .s-round__choice button itself from
   the question payload rather than the view rendering them, so this styles
   the class the controller writes rather than markup that carries it. */

.sikai-student .s-round {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.sikai-student .s-round__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: var(--s-surface);
  border: 1px solid var(--s-line);
  border-radius: var(--s-r-lg);
}

.sikai-student .s-round__clock {
  font-family: var(--s-font);
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--s-ink);
}

.sikai-student .s-round__score {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--s-font);
  font-size: 15px;
  font-weight: 600;
  color: var(--s-green);
}

.sikai-student .s-round__prompt {
  font-size: var(--s-text-lg);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -.015em;
  text-align: center;
  color: var(--s-ink);
}

/* A grid, not .s-choices' vertical list: Recall::RoundPool::FAST_TYPES is
   only mcq and true_false, so every round question has short options that
   read better two-up than stacked -- and two-up keeps every choice within a
   thumb's reach of the centre at 360px, where a five-item vertical list
   would run past the fold mid-round. */
.sikai-student .s-round__choices {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.sikai-student .s-round__choice {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 64px;
  padding: 12px;
  background: var(--s-surface);
  border: 1.5px solid var(--s-line-strong);
  border-radius: var(--s-r);
  font-family: var(--s-font);
  font-size: var(--s-text);
  font-weight: 700;
  text-align: center;
  color: var(--s-ink);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, transform .15s ease;
}

.sikai-student .s-round__choice:hover {
  border-color: var(--s-blue);
  background: var(--s-blue-tint);
}

.sikai-student .s-round__choice:active {
  transform: translateY(1px);
}

/* Paired with .s-card in the view for the bordered white surface; this adds
   only the centred, stacked layout the end-of-round panel needs on top. */
.sikai-student .s-round__over {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}

/* The deskbar wordmark links to /learn. */
.sikai-student .s-deskbar__brand { color: inherit; text-decoration: none; }
.sikai-student .s-deskbar__brand:focus-visible { outline: 2px solid var(--sk-accent);
                                                 outline-offset: 3px; border-radius: 6px; }

/* Work a teacher set, on the child's home screen (TEACH-02). Deliberately
   plainer than a subject card: this is a list to work down, not a thing to
   choose between, and it sits above Today's goal where the eye already
   lands. --s-chalk rather than tokens.css's --sk-fill-1: every other list
   row and track on this surface already reads off the local --s-* aliases
   (see the --s-meter comment above -- "one fewer idea in the file"), and
   --sk-fill-1 shares --s-paper's value, which is this screen's own page
   background -- a row filled with it would be invisible against the page. */
/* No margin-bottom here: .s-section (the parent, one per assignment now) is
   already a flex column with its own 10px gap, so a row-level margin on top
   of that gap doubled the space between rows to 18px -- the brief's snippet
   assumed a plain block parent, not this file's flex .s-section. */
.sikai-student .s-assigned__row { display: flex; align-items: center; gap: 12px;
                                  padding: 12px 14px; border-radius: 14px;
                                  text-decoration: none; background: var(--s-chalk); }
.sikai-student .s-assigned__mark { flex: none; width: 22px; height: 22px;
                                   border-radius: 8px; display: flex;
                                   align-items: center; justify-content: center;
                                   background: var(--s-surface);
                                   font: 700 12px/1 var(--s-font);
                                   color: var(--s-blue); }
.sikai-student .s-assigned__title { font: 600 14px/1.3 var(--s-font);
                                    color: var(--s-ink); }
.sikai-student .s-assigned__row[data-done="true"] .s-assigned__title { opacity: .55; }
