/* ==========================================================================
   ns-ui.css  ·  Neurosmack Coach UI
   Tokens, one breakpoint scale, chrome gating and shared components.
   Load AFTER theme-neumorphic.css and style.css (from ThemeHeadHTML()).
   Every class is prefixed ns- so it cannot collide with per-handler inline CSS.
   Spec: docs/ui-revamp/02-components.md
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */
:root {
  /* surfaces */
  --ns-bg: #eef1f6;
  --ns-surface: #ffffff;
  --ns-surface-soft: #f4f6fa;
  --ns-surface-selected: #f2f6fc;
  --ns-ink-panel: #2d3b52;          /* dark "Next up" card, active nav pill */
  /* text (all pass 4.5:1 on --ns-bg and --ns-surface) */
  --ns-text: #2d3b52;
  --ns-text-2: #43506a;
  --ns-text-muted: #566176;
  --ns-text-on-dark: #ffffff;
  --ns-text-on-dark-2: #dbe3f0;
  /* lines */
  --ns-border: #d5dce8;
  --ns-border-strong: #c3cddd;
  --ns-border-dashed: #9aa8bd;
  --ns-divider: #e3e8f0;
  /* brand */
  --ns-primary: #3d6db3;            /* fills under white text */
  --ns-primary-ink: #23487e;        /* text on tint */
  --ns-primary-tint: #e3ebf7;
  --ns-link: #2f5c9e;
  --ns-warm: #e79a80;               /* accent marks only, never under text */
  /* concept states: ALWAYS pair with a text label, never colour alone */
  --ns-state-mastered: #3a8f70;
  --ns-state-progress: #e2b866;
  --ns-state-review: #c9483f;
  --ns-state-new: #c3ccda;
  --ns-ok-bg: #dcebe5;   --ns-ok-ink: #1f5c46;
  --ns-bad-bg: #f7e1df;  --ns-bad-ink: #8a2a23;
  --ns-warn-bg: #fbf3e0; --ns-warn-ink: #6b4d12;   /* amber: --ns-state-progress is a fill, never text */
  /* type */
  --ns-font-display: 'Bebas Neue', 'Oswald', 'Inter', sans-serif;
  --ns-font-body: 'Inter', 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
  /* shape and space */
  --ns-r-sm: 10px; --ns-r-md: 12px; --ns-r-lg: 14px; --ns-r-xl: 18px; --ns-r-2xl: 22px;
  --ns-s-1: 4px; --ns-s-2: 8px; --ns-s-3: 12px; --ns-s-4: 16px; --ns-s-5: 20px; --ns-s-6: 24px; --ns-s-8: 32px; --ns-s-10: 40px; --ns-s-12: 48px;
  --ns-hit: 44px;                   /* minimum touch target */
  --ns-shadow-float: 0 10px 30px rgba(45, 59, 82, 0.14);
  --ns-shadow-dialog: 0 30px 80px rgba(20, 30, 50, 0.35);
  --ns-header-h: 76px;
  --ns-tabbar-h: 72px;
}

/* ---------- 2. Breakpoints ----------------------------------------------
   The ONLY widths new code may use. Replaces the 18 ad-hoc values.
     sm  ≤ 600px   phone
     md  ≤ 900px   large phone / small tablet: mobile chrome (tab bar) below this
     lg  ≤ 1200px  tablet / small laptop: side rails drop under main column
   CSS custom properties cannot be used inside @media, so copy the numbers.
   ------------------------------------------------------------------------ */

/* ---------- 3. Chrome ------------------------------------------------------
   No live users, so there is no flag or side-by-side mode: SharedAppHeaderHTML()
   and SharedAppFooterHTML() in page_chrome.go are rewritten to emit .ns-header and
   .ns-tabbar directly (PR 2). Until a page is converted its inline CSS still styles
   its body; the rules below only make sure the new chrome sits correctly on it.
   ------------------------------------------------------------------------ */
body { padding-bottom: 0; }
.ns-tabbar { display: none; }
.ns-header__nav { display: flex; }
@media (max-width: 900px) {
  .ns-tabbar { display: flex; }
  .ns-header__nav { display: none; }
  body { padding-bottom: calc(var(--ns-tabbar-h) + env(safe-area-inset-bottom, 0px)); }
}
body.ns-coach { background: var(--ns-bg); color: var(--ns-text); font-family: var(--ns-font-body); }
/* Coach pages still load the legacy dark sheet (style.css). In the default theme its bare h1/h2
   rules paint pale or gradient-clipped ink, and .container a dark panel, onto the light page.
   :where() keeps these at element weight: they beat style.css by source order and lose to any
   page rule that names a class (a heading inside a dark overlay sets its own ink). */
:where(body.ns-coach) h1, :where(body.ns-coach) h2 { color: var(--ns-text); background: none; -webkit-text-fill-color: currentColor; text-shadow: none; }
:where(body.ns-coach) h2 { border-bottom-color: var(--ns-divider); }
:where(body.ns-coach) .container { background: transparent; border-color: transparent; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
/* The hidden attribute always wins, whatever display a class sets (dialog scrims, wizard panels). */
[hidden] { display: none !important; }   /* add to <body> of each converted page */

/* ---------- 4. Header ---------------------------------------------------- */
.ns-header { display: flex; position: sticky; top: 0; z-index: 50; height: var(--ns-header-h); box-sizing: border-box; padding: 0 var(--ns-s-12); padding-top: var(--app-safe-top, 0px); align-items: center; gap: var(--ns-s-8); background: var(--ns-surface); border-bottom: 1px solid var(--ns-border); }
.ns-header__brand { font-family: var(--ns-font-display); font-size: 30px; letter-spacing: 0.04em; line-height: 1; color: var(--ns-text); text-decoration: none; }
.ns-header__nav { gap: var(--ns-s-1); } /* display lives in the breakpoint block above: hidden at <=900px, where the tab bar takes over */
.ns-header__link { display: flex; align-items: center; height: var(--ns-hit); padding: 0 var(--ns-s-4); border-radius: 22px; color: var(--ns-text-2); font-weight: 500; font-size: 15px; text-decoration: none; }
.ns-header__link[aria-current="page"] { background: var(--ns-ink-panel); color: var(--ns-text-on-dark); font-weight: 600; }
.ns-header__actions { margin-left: auto; display: flex; align-items: center; gap: var(--ns-s-2); }
.ns-avatar { width: var(--ns-hit); height: var(--ns-hit); border-radius: 50%; border: none; background: var(--ns-primary); color: #fff; font-weight: 700; font-size: 15px; display: flex; align-items: center; justify-content: center; text-decoration: none; }
@media (max-width: 900px) { .ns-header { height: 60px; padding: 0 var(--ns-s-2) 0 var(--ns-s-4); gap: var(--ns-s-2); } .ns-header__brand { font-size: 26px; flex-grow: 1; } .ns-header .ns-btn__label { display: none; } }

/* ---------- 5. Mobile tab bar ------------------------------------------- */
.ns-tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; height: var(--ns-tabbar-h); padding-bottom: env(safe-area-inset-bottom, 0px); background: var(--ns-surface); border-top: 1px solid var(--ns-border); align-items: stretch; }
.ns-tabbar__item { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--ns-s-1); padding: 0 4px; box-sizing: border-box; color: var(--ns-text-2); font-size: 11px; font-weight: 500; text-decoration: none; text-align: center; }
.ns-tabbar__item > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ns-tabbar__item[aria-current="page"] { color: var(--ns-primary-ink); font-weight: 700; }

/* ---------- 6. Page scaffolding ----------------------------------------- */
.ns-page { padding: var(--ns-s-8) var(--ns-s-12); display: flex; align-items: flex-start; gap: var(--ns-s-10); justify-content: center; }
.ns-page__main { width: 100%; max-width: 760px; display: flex; flex-direction: column; gap: var(--ns-s-5); min-width: 0; }
.ns-page__main--wide { max-width: 1080px; }
.ns-page__rail { width: 320px; flex-shrink: 0; display: flex; flex-direction: column; gap: var(--ns-s-5); }
@media (max-width: 1200px) { .ns-page { flex-direction: column; align-items: center; } .ns-page__rail { width: 100%; max-width: 760px; } }
@media (max-width: 600px) { .ns-page { padding: var(--ns-s-4); gap: var(--ns-s-4); } }
.ns-h1 { margin: 0; font-family: var(--ns-font-display); font-weight: 400; font-size: 44px; letter-spacing: 0.02em; line-height: 1; }
@media (max-width: 600px) { .ns-h1 { font-size: 34px; } }
.ns-eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ns-text-muted); }
.ns-sub { font-size: 14px; color: var(--ns-text-2); }
.ns-crumb { display: flex; gap: var(--ns-s-2); font-size: 13px; color: var(--ns-text-2); }
.ns-crumb a { color: var(--ns-link); }

/* ---------- 7. Buttons ---------------------------------------------------
   One primary per view. Never icon-only without aria-label. No hover-only labels.
   Do NOT reintroduce the global `button{width:100%}` mobile rule for ns- buttons. */
.ns-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--ns-s-2); min-height: var(--ns-hit); padding: 0 var(--ns-s-5); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); color: var(--ns-text); font-family: inherit; font-weight: 600; font-size: 15px; text-decoration: none; cursor: pointer; width: auto; }
.ns-btn--primary { background: var(--ns-primary); border-color: var(--ns-primary); color: #fff; }
.ns-btn--soft { background: var(--ns-primary-tint); border-color: var(--ns-primary-tint); color: var(--ns-primary-ink); }
.ns-btn--quiet { background: transparent; border-color: transparent; color: var(--ns-primary-ink); }
.ns-btn--lg { min-height: 48px; }
.ns-btn--xl { min-height: 56px; padding: 0 var(--ns-s-8); border-radius: var(--ns-r-lg); font-size: 16px; font-weight: 700; }
.ns-btn--icon { width: var(--ns-hit); padding: 0; }
/* The legacy theme sheet styles every anchor and every button (html[data-theme="neumorphic"] a,
   ... button) and those selectors outrank a single class, so .ns-btn lost its colours to it:
   as a link the primary button came out blue on blue (contrast 1.26), and as a button it kept
   white text but lost its blue fill to the legacy grey (1.13). Re-assert fill, border and text
   inside the Coach chrome, where .ns-btn is always the button. Order matters here: these carry
   equal specificity, so each variant follows the base. */
body.ns-coach .ns-btn { background: var(--ns-surface); border-color: var(--ns-border-strong); color: var(--ns-text); }
body.ns-coach .ns-btn--primary { background: var(--ns-primary); border-color: var(--ns-primary); color: #fff; }
body.ns-coach .ns-btn--soft { background: var(--ns-primary-tint); border-color: var(--ns-primary-tint); color: var(--ns-primary-ink); }
body.ns-coach .ns-btn--quiet { background: transparent; border-color: transparent; color: var(--ns-primary-ink); }
/* Same contest as .ns-btn above: the legacy sheet styles every bare button, and it styles
   button::after too -- a hover sheen that lands on this one as a white streak across a 24px
   circle. Both outrank a single class, so re-assert here and drop the sheen. */
body.ns-coach .ns-why { background: var(--ns-surface); border: 1px solid var(--ns-border-strong); color: var(--ns-text-2); box-shadow: none; }
body.ns-coach .ns-why:hover, body.ns-coach .ns-why:focus-visible { background: var(--ns-ink-panel); border-color: var(--ns-ink-panel); color: #fff; }
body.ns-coach .ns-why::after { content: none; }
.ns-btn:focus-visible, .ns-header__link:focus-visible, .ns-tabbar__item:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }
.ns-btn[disabled], .ns-btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

/* ---------- 8. Cards ----------------------------------------------------- */
.ns-card { padding: var(--ns-s-5); border-radius: var(--ns-r-xl); background: var(--ns-surface); border: 1px solid var(--ns-border); display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-card[hidden] { display: none; }
.ns-card--lg { padding: var(--ns-s-8); gap: var(--ns-s-4); }
.ns-card--soft { background: var(--ns-surface-soft); border-radius: var(--ns-r-md); }
.ns-card--next { background: var(--ns-ink-panel); border-color: var(--ns-ink-panel); color: var(--ns-text-on-dark); flex-direction: row; align-items: center; gap: var(--ns-s-6); padding: 28px; }
.ns-card--next .ns-eyebrow { color: #c9d4e6; }
.ns-card--next .ns-sub { color: var(--ns-text-on-dark-2); }
.ns-card--next .ns-btn { background: #fff; border-color: #fff; color: var(--ns-primary-ink); }
.ns-slot { display: flex; align-items: center; justify-content: center; gap: var(--ns-s-2); min-height: 64px; border-radius: var(--ns-r-lg); border: 2px dashed var(--ns-border-dashed); color: var(--ns-primary-ink); font-weight: 600; font-size: 15px; text-decoration: none; }
@media (max-width: 600px) { .ns-card--next { flex-direction: column; align-items: stretch; } }

/* ---------- 9. Concept strip and rows ------------------------------------
   One block per concept, in chapter order. Always followed by .ns-strip__counts text. */
.ns-strip { display: flex; gap: 3px; flex-grow: 1; }
.ns-strip__seg { flex: 1 1 0; height: 12px; border-radius: 4px; background: var(--ns-state-new); }
.ns-strip--sm .ns-strip__seg { height: 10px; }
.ns-strip__seg[data-state="mastered"] { background: var(--ns-state-mastered); }
.ns-strip__seg[data-state="progress"] { background: var(--ns-state-progress); }
.ns-strip__seg[data-state="review"]   { background: var(--ns-state-review); }
.ns-strip__seg[data-current="true"]   { outline: 3px solid var(--ns-ink-panel); outline-offset: 2px; }
.ns-strip__counts { font-size: 12px; color: var(--ns-text-2); flex-shrink: 0; }
.ns-concepts { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ns-s-2); }
@media (max-width: 900px) { .ns-concepts { grid-template-columns: minmax(0, 1fr); } }
.ns-concept { display: flex; flex-direction: column; padding: 8px 8px 8px 14px; border-radius: var(--ns-r-md); background: var(--ns-surface-soft); border: 1px solid var(--ns-border); }
.ns-concept__row { display: flex; align-items: center; gap: var(--ns-s-3); }
.ns-concept__body { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ns-concept__name { font-weight: 600; font-size: 14px; }
.ns-concept__meta { font-size: 12px; color: var(--ns-text-2); }
.ns-concept__action { display: flex; align-items: center; justify-content: center; min-height: var(--ns-hit); min-width: 56px; font-size: 14px; font-weight: 600; color: var(--ns-link); }
.ns-concept__more { display: inline-flex; align-items: center; justify-content: center; width: var(--ns-hit); min-height: var(--ns-hit); padding: 0; border: 0; border-radius: var(--ns-r-sm); background: transparent; color: var(--ns-text-2); cursor: pointer; }
.ns-concept__more:hover, .ns-concept__more:focus-visible { background: var(--ns-surface); color: var(--ns-text); }
.ns-concept__more svg { transition: transform 0.15s ease; }
.ns-concept__more[aria-expanded="true"] svg { transform: rotate(180deg); }
.ns-concept__detail { display: flex; flex-direction: column; gap: var(--ns-s-2); padding: var(--ns-s-2) 6px var(--ns-s-2) 0; border-top: 1px solid var(--ns-border); margin-top: 6px; }
.ns-concept__detail[hidden] { display: none; }
.ns-concept__text { margin: 0; font-size: 14px; line-height: 1.5; white-space: pre-wrap; }
.ns-concept__detail-actions { display: flex; }
.ns-pips { display: flex; gap: 3px; flex-shrink: 0; }
.ns-pips__pip { width: 10px; height: 10px; border-radius: 3px; background: #d7deea; }
.ns-pips__pip[data-on="true"] { background: var(--ns-state-progress); }
.ns-pips[data-state="mastered"] .ns-pips__pip[data-on="true"] { background: var(--ns-state-mastered); }
.ns-pips[data-state="review"] .ns-pips__pip[data-on="true"] { background: var(--ns-state-review); }

/* ---------- 10. Chapter path -------------------------------------------- */
.ns-path { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 14px; }
.ns-path__item { display: flex; gap: var(--ns-s-5); align-items: flex-start; }
.ns-path__num { width: 44px; height: 44px; border-radius: 50%; background: var(--ns-surface); border: 3px solid #b4c0d3; font-weight: 700; font-size: 15px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ns-path__item[data-state="active"] .ns-path__num { border-color: var(--ns-primary); }
.ns-chapter { flex-grow: 1; min-width: 0; padding: 18px 20px; border-radius: var(--ns-r-lg); }
.ns-chapter__head { display: flex; align-items: center; gap: var(--ns-s-4); }
.ns-chapter__titles { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ns-chapter__title { font-weight: 700; font-size: 17px; }
.ns-chapter__row { display: flex; align-items: center; gap: 14px; }
.ns-disclosure { display: inline-flex; align-items: center; gap: 6px; min-height: var(--ns-hit); padding: 0 var(--ns-s-3); border-radius: var(--ns-r-sm); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); font: inherit; font-size: 14px; font-weight: 600; color: var(--ns-text); cursor: pointer; width: auto; }
.ns-disclosure[aria-expanded="true"] svg { transform: rotate(180deg); }
@media (max-width: 600px) { .ns-path__num { display: none; } .ns-chapter__head { flex-wrap: wrap; } }

/* ---------- 11. Steps, tabs, segmented ---------------------------------- */
.ns-steps { margin: 0; padding: 0; list-style: none; display: flex; gap: 6px; }
.ns-steps__step { display: flex; align-items: center; gap: var(--ns-s-2); height: 36px; padding: 0 14px; border-radius: 18px; background: var(--ns-bg); color: var(--ns-text-2); font-size: 13px; font-weight: 600; }
.ns-steps__step[data-state="done"] { background: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-steps__step[aria-current="step"] { background: var(--ns-ink-panel); color: #fff; }
@media (max-width: 900px) { .ns-steps__step:not([aria-current="step"]) .ns-steps__label { display: none; } }
.ns-tabs { display: flex; gap: 28px; border-bottom: 1px solid var(--ns-border); overflow-x: auto; }
.ns-tabs__tab { display: flex; align-items: center; height: var(--ns-hit); font-size: 15px; font-weight: 500; color: var(--ns-text-2); text-decoration: none; border-bottom: 3px solid transparent; white-space: nowrap; }
.ns-tabs__tab[aria-current="page"] { font-weight: 700; color: var(--ns-primary-ink); border-bottom-color: var(--ns-primary); }
.ns-plan { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; counter-reset: ns-plan; }
.ns-plan__step { display: flex; align-items: center; gap: var(--ns-s-4); padding: 16px 20px; border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); }
.ns-plan__num { width: 36px; height: 36px; border-radius: 50%; border: 2px solid #b4c0d3; font-weight: 700; font-size: 14px; color: var(--ns-text-2); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ns-plan__num::before { counter-increment: ns-plan; content: counter(ns-plan); }
.ns-plan__step[data-state="done"] .ns-plan__num { background: var(--ns-ok-bg); border-color: var(--ns-state-mastered); color: var(--ns-ok-ink); }

/* ---------- 12. Forms and choices --------------------------------------- */
.ns-field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 600; }
.ns-input, .ns-textarea { min-height: var(--ns-hit); padding: 0 12px; border-radius: var(--ns-r-sm); border: 1px solid var(--ns-border-strong); font: inherit; font-size: 15px; font-weight: 400; color: var(--ns-text); background: var(--ns-surface); }
.ns-textarea { padding: 12px; resize: vertical; }
.ns-choice { display: flex; flex-direction: column; gap: 6px; padding: 18px; border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); text-align: left; font: inherit; color: var(--ns-text); cursor: pointer; width: auto; }
.ns-choice[aria-pressed="true"], .ns-choice:has(input:checked) { background: var(--ns-surface-selected); border: 2px solid var(--ns-primary); }
.ns-option { display: flex; align-items: center; gap: var(--ns-s-3); min-height: 52px; padding: 0 var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); font-size: 15px; }
.ns-option:has(input:checked) { background: var(--ns-surface-selected); border: 2px solid var(--ns-primary); }
.ns-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.ns-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ns-s-4); }
.ns-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ns-s-3); }
@media (max-width: 900px) { .ns-grid-3, .ns-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .ns-grid-2, .ns-grid-3, .ns-grid-4 { grid-template-columns: minmax(0, 1fr); } }

/* ---------- 13. Dialog, side panel, toast, feedback --------------------- */
.ns-scrim { position: fixed; inset: 0; z-index: 100; background: rgba(45, 59, 82, 0.45); display: flex; align-items: center; justify-content: center; padding: var(--ns-s-4); }
.ns-dialog { width: 100%; max-width: 920px; max-height: calc(100vh - 32px); overflow-y: auto; box-sizing: border-box; padding: var(--ns-s-8); border-radius: var(--ns-r-2xl); background: var(--ns-surface); box-shadow: var(--ns-shadow-dialog); display: flex; flex-direction: column; gap: 18px; }
.ns-panel { position: fixed; top: 0; right: 0; bottom: 0; z-index: 110; width: 480px; max-width: 100vw; box-sizing: border-box; padding: var(--ns-s-6); background: var(--ns-surface); border-left: 1px solid var(--ns-border); display: flex; flex-direction: column; gap: var(--ns-s-4); overflow-y: auto; }
.ns-toast { position: fixed; right: var(--ns-s-8); bottom: var(--ns-s-8); z-index: 120; width: 360px; max-width: calc(100vw - 32px); padding: 16px 18px; border-radius: var(--ns-r-lg); background: var(--ns-ink-panel); color: #fff; box-shadow: 0 16px 40px rgba(20, 30, 50, 0.3); }
@media (max-width: 900px) { .ns-toast { bottom: calc(var(--ns-tabbar-h) + 16px); right: 16px; } .ns-dialog { padding: var(--ns-s-5); } }
.ns-tag { padding: 4px 10px; border-radius: 8px; font-size: 12px; font-weight: 700; }
.ns-tag--ok { background: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-tag--bad { background: var(--ns-bad-bg); color: var(--ns-bad-ink); }
.ns-tag--info { background: var(--ns-primary-tint); color: var(--ns-primary-ink); }
.ns-meter { height: 8px; border-radius: 4px; background: var(--ns-divider); overflow: hidden; }
.ns-meter__fill { height: 100%; background: var(--ns-state-mastered); }

/* ---------- 14. Focus chrome (session, wizards, daily five) ------------- */
.ns-focusbar { position: sticky; top: 0; z-index: 50; height: var(--ns-header-h); box-sizing: border-box; padding: 0 var(--ns-s-8); display: flex; align-items: center; gap: var(--ns-s-5); background: var(--ns-surface); border-bottom: 1px solid var(--ns-border); }
.ns-focusbar .ns-steps { margin: 0 auto; }
body.ns-focus .ns-header, body.ns-focus .ns-tabbar { display: none; }
body.ns-focus { padding-bottom: 0; }
body.ns-focus .ns-page { display: block; padding: 0; }
.ns-reader { min-height: 240px; border-radius: var(--ns-r-xl); background: #1f2a3c; color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; }
.ns-reader__word { font-size: clamp(32px, 6vw, 56px); font-weight: 600; }
.ns-reader__mark { width: 2px; height: 18px; background: var(--ns-warm); }

/* ---------- 15. Motion --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) { .ns-disclosure svg, .ns-concept__more svg, .ns-btn { transition: none; } }

/* ---------- 16. Header menus (+ New, account) ---------------------------- */
.ns-menu-wrap { position: relative; display: flex; }
.ns-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 60; min-width: 220px; max-width: calc(100vw - 32px); padding: 6px; border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); box-shadow: var(--ns-shadow-float); display: flex; flex-direction: column; }
.ns-menu[hidden] { display: none; }
.ns-menu--right { left: auto; right: 0; }
.ns-menu__title { padding: 8px 12px 4px; font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ns-text-muted); }
.ns-menu__item { display: flex; align-items: center; min-height: var(--ns-hit); padding: 0 12px; border-radius: var(--ns-r-sm); border: none; background: transparent; color: var(--ns-text); font: inherit; font-size: 15px; font-weight: 500; text-align: left; text-decoration: none; cursor: pointer; width: 100%; box-sizing: border-box; }
.ns-menu__item:hover, .ns-menu__item:focus-visible { background: var(--ns-surface-soft); outline: none; }
.ns-menu__item:focus-visible { box-shadow: inset 0 0 0 2px var(--ns-primary); }
.ns-menu__item[hidden] { display: none; }
@media (max-width: 900px) { .ns-menu { left: auto; right: 0; } }
/* Membership badge beside the avatar, filled from /api/header/summary. At phone width the
   header row (brand, + New, Search, Ask tutor, avatar) already spans the viewport, so the
   badge is hidden there and the same label shows as a row in the account menu instead. */
.ns-plan-badge { display: inline-flex; align-items: center; align-self: center; margin-right: var(--ns-s-2); height: 26px; padding: 0 10px; border-radius: 13px; background: var(--ns-primary-tint); color: var(--ns-primary-ink); font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; }
.ns-plan-badge[hidden] { display: none; }
/* Account menu AI credits row: label + balance on the left, Buy more on the right. */
.ns-menu__stat { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); min-height: var(--ns-hit); padding: 6px 12px; }
.ns-menu__stat[hidden] { display: none; }
.ns-menu__stat-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ns-menu__stat-label { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ns-text-muted); }
.ns-menu__stat-value { font-size: 15px; font-weight: 600; color: var(--ns-text); white-space: nowrap; }
.ns-menu .ns-menu__stat-btn { min-height: 34px; padding: 0 var(--ns-s-3); font-size: 13px; flex-shrink: 0; }
.ns-menu .ns-menu__stat-btn[hidden] { display: none; }
.ns-menu__sep { height: 1px; margin: 4px 6px; background: var(--ns-border); }
.ns-menu__stat--phone { display: none; }
@media (max-width: 600px) { .ns-plan-badge { display: none; } .ns-menu__stat--phone { display: flex; } }
/* The header reserves the device status bar (--app-safe-top from SharedAppHeaderCSS). */
.ns-header { height: calc(var(--ns-header-h) + var(--app-safe-top, 0px)); }
@media (max-width: 900px) { .ns-header { height: calc(60px + var(--app-safe-top, 0px)); } }

/* ---------- 17. Library ------------------------------------------------- */
.ns-titlerow { display: flex; align-items: center; gap: var(--ns-s-4); flex-wrap: wrap; }
.ns-titlerow__text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.ns-classcard { padding: var(--ns-s-4); gap: var(--ns-s-3); }
.ns-classcard__art { height: 120px; border-radius: var(--ns-r-md); background: #dfe6f1; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--ns-text-muted); overflow: hidden; }
.ns-classcard__art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ns-classcard__name { font-weight: 700; font-size: 17px; overflow-wrap: anywhere; }
.ns-classcard__strip { display: flex; gap: 2px; }
.ns-classcard__actions { display: flex; gap: var(--ns-s-2); margin-top: auto; }
.ns-classcard__actions .ns-btn--soft { flex-grow: 1; }
.ns-slot--card { flex-direction: column; text-align: center; padding: var(--ns-s-4); border-radius: var(--ns-r-xl); min-height: 200px; }
.ns-slot__hint { font-size: 13px; font-weight: 400; color: var(--ns-text-2); }
.ns-grid-4 > .ns-card, .ns-grid-4 > .ns-slot { min-width: 0; }
.ns-empty { text-align: center; padding: var(--ns-s-10) var(--ns-s-4); color: var(--ns-text-2); display: flex; flex-direction: column; gap: var(--ns-s-3); align-items: center; }
.ns-quietlink { font-size: 14px; color: var(--ns-link); }
.ns-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- 18. Material entry (New class, Add chapter) ------------------ */
.ns-choice__label { font-weight: 700; font-size: 15px; }
.ns-choice__hint { font-size: 13px; color: var(--ns-text-2); }
.ns-source { display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-source__panel[hidden] { display: none; }
.ns-dropzone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--ns-s-2); min-height: 140px; padding: var(--ns-s-5); border-radius: var(--ns-r-lg); border: 2px dashed var(--ns-border-dashed); background: var(--ns-surface-soft); cursor: pointer; text-align: center; }
.ns-dropzone[data-active="true"] { border-color: var(--ns-primary); background: var(--ns-surface-selected); }
.ns-dropzone__title { font-weight: 600; }
.ns-filelist { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.ns-filelist__item { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); padding: 6px 12px; border-radius: var(--ns-r-sm); background: var(--ns-surface-soft); font-size: 14px; overflow-wrap: anywhere; }
.ns-recorder { display: flex; flex-direction: column; gap: var(--ns-s-3); padding: var(--ns-s-5); border-radius: var(--ns-r-lg); background: var(--ns-surface-soft); border: 1px solid var(--ns-border); }
.ns-recorder__time { font-family: var(--ns-font-display); font-size: 40px; line-height: 1; }
.ns-recorder__actions { display: flex; gap: var(--ns-s-2); flex-wrap: wrap; }

/* The recorder overlay: full screen on every width, because Stop has to be findable. Its
   modes (idle · recording · review) decide which controls exist, so exactly one primary
   button shows at a time. */
.ns-recorder-overlay { position: fixed; inset: 0; z-index: 130; display: flex; align-items: center; justify-content: center; padding: var(--ns-s-4); background: rgba(20, 30, 50, 0.72); }
.ns-recorder-overlay__panel { box-sizing: border-box; width: 100%; max-width: 460px; max-height: calc(100vh - 32px); overflow-y: auto; padding: var(--ns-s-6); border-radius: var(--ns-r-2xl); background: var(--ns-ink-panel); color: var(--ns-text-on-dark); box-shadow: var(--ns-shadow-dialog); display: flex; flex-direction: column; align-items: center; gap: var(--ns-s-4); text-align: center; }
.ns-recorder-overlay__panel:focus { outline: none; }
/* The legacy sheets style bare elements -- html[data-theme="neumorphic"] h2, button, input --
   and those outrank a single class, while body.ns-coach re-asserts the page's light button
   colours. Both are wrong on a dark panel: the title came out ink on ink, the buttons came
   back white with a neumorphic shadow and the slider sat in a white inset box. These rules
   outrank both, and the base comes before the variant because they weigh the same. */
body.ns-coach .ns-recorder__title { color: var(--ns-text-on-dark); border-bottom: none; }
body.ns-coach .ns-recorder-overlay__panel .ns-btn { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.4); color: var(--ns-text-on-dark); box-shadow: none; }
body.ns-coach .ns-recorder-overlay__panel .ns-btn--primary { background: var(--ns-primary); border-color: var(--ns-primary); color: #fff; box-shadow: none; }
body.ns-coach .ns-sensitivity__input { background: transparent; border: none; box-shadow: none; }
body.ns-coach .ns-sensitivity__input:focus { box-shadow: none; outline: 3px solid var(--ns-primary-tint); outline-offset: 2px; }
.ns-recorder__badge { display: flex; align-items: center; gap: var(--ns-s-2); font-size: 13px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ns-text-on-dark-2); }
.ns-recorder__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--ns-state-review); animation: ns-rec-pulse 1.2s infinite; }
.ns-recorder__title { margin: 0; font-family: var(--ns-font-display); font-size: 28px; font-weight: 400; }
.ns-recorder__clock { font-family: var(--ns-font-display); font-size: 56px; line-height: 1; font-variant-numeric: tabular-nums; }
.ns-recorder__note { min-height: 20px; font-size: 14px; line-height: 1.45; color: var(--ns-text-on-dark-2); }
.ns-recorder-overlay .ns-recorder__actions { justify-content: center; width: 100%; }
.ns-recorder-overlay .ns-recorder__actions .ns-btn--xl { width: 100%; }
/* The meter: eight bars, each scaled by the --ns-level the analyser writes on it. */
.ns-level { display: flex; align-items: center; justify-content: center; gap: var(--ns-s-2); width: 100%; height: 64px; }
.ns-level__bar { width: 10px; height: 48px; border-radius: 999px; background: linear-gradient(180deg, var(--ns-state-progress) 0%, var(--ns-state-mastered) 100%); transform: scaleY(var(--ns-level, 0.18)); opacity: calc(0.45 + var(--ns-level, 0.18) * 0.55); transition: transform 0.08s linear, opacity 0.08s linear; }
.ns-sensitivity { box-sizing: border-box; width: 100%; display: flex; flex-direction: column; gap: var(--ns-s-2); padding: var(--ns-s-3) var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid rgba(255, 255, 255, 0.18); background: rgba(255, 255, 255, 0.06); }
.ns-sensitivity__head { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); font-size: 14px; font-weight: 700; }
.ns-sensitivity__value { font-variant-numeric: tabular-nums; color: var(--ns-text-on-dark-2); }
.ns-sensitivity__input { width: 100%; min-height: var(--ns-hit); accent-color: var(--ns-state-progress); }
.ns-sensitivity__scale { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--ns-text-on-dark-2); }
/* Mode gating: every control is in the markup, the mode says which belong to this moment. */
.ns-recorder-overlay .ns-recorder__badge,
.ns-recorder-overlay [data-ns-rec-stop],
.ns-recorder-overlay [data-ns-rec-use],
.ns-recorder-overlay [data-ns-rec-again],
.ns-recorder-overlay [data-ns-rec-discard] { display: none; }
.ns-recorder-overlay[data-mode="recording"] .ns-recorder__badge { display: flex; }
.ns-recorder-overlay[data-mode="recording"] [data-ns-rec-stop] { display: inline-flex; }
.ns-recorder-overlay[data-mode="recording"] [data-ns-rec-start],
.ns-recorder-overlay[data-mode="recording"] [data-ns-rec-pick],
.ns-recorder-overlay[data-mode="recording"] [data-ns-rec-close] { display: none; }
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-use],
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-again],
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-discard] { display: inline-flex; }
.ns-recorder-overlay[data-mode="review"] .ns-level,
.ns-recorder-overlay[data-mode="review"] .ns-sensitivity,
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-start],
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-pick],
.ns-recorder-overlay[data-mode="review"] [data-ns-rec-close] { display: none; }
@keyframes ns-rec-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) {
  .ns-recorder__dot { animation: none; }
  .ns-level__bar { transition: none; }
}
@media (max-width: 600px) {
  .ns-recorder-overlay__panel { max-width: none; padding: var(--ns-s-5) var(--ns-s-4); gap: var(--ns-s-3); }
  .ns-recorder__clock { font-size: 44px; }
  .ns-level { height: 48px; }
  .ns-level__bar { height: 38px; }
}
.ns-terms { display: flex; flex-direction: column; gap: var(--ns-s-3); margin: 0; }
.ns-terms__item { padding: var(--ns-s-4); border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); }
.ns-terms__term { margin: 0 0 4px; font-weight: 600; }
.ns-terms__def { margin: 0; color: var(--ns-text-muted); }
.ns-concepts-step { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-concepts-step__bar { display: flex; align-items: center; gap: var(--ns-s-2); flex-wrap: wrap; }
.ns-concepts-step__bar .ns-sub { flex-grow: 1; }
.ns-concept-list { display: flex; flex-direction: column; gap: var(--ns-s-5); }
.ns-concept-group { display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-concept-group__title { margin: 0; font-size: 16px; font-weight: 600; }
.ns-concept-group__desc { margin: 0; }
.ns-concept-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 900px) { .ns-concept-grid { grid-template-columns: minmax(0, 1fr); } }
.ns-option--concept { min-height: 56px; padding: 10px 14px; align-items: flex-start; cursor: pointer; }
.ns-option--concept input { margin-top: 4px; width: 20px; height: 20px; flex-shrink: 0; }
.ns-option__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ns-option__title { font-weight: 600; font-size: 15px; }
.ns-option__desc { font-size: 13px; color: var(--ns-text-2); }
.ns-concepts-step__addrow { display: flex; gap: var(--ns-s-2); }
.ns-concepts-step__addrow .ns-input { flex-grow: 1; min-width: 0; }
/* The divergence round's explainer, shown in the concept step before the round opens. */
.ns-divergence-intro { display: flex; flex-direction: column; gap: var(--ns-s-3); font-size: 15px; line-height: 1.5; }
.ns-divergence-intro p { margin: 0; }
.ns-divergence-intro__title { margin: 0; font-size: 18px; font-weight: 700; }
.ns-divergence-intro__list { margin: 0; padding-left: var(--ns-s-5); display: flex; flex-direction: column; gap: var(--ns-s-2); color: var(--ns-text-2); }
.ns-divergence-intro__list strong { color: var(--ns-text); }
.ns-divergence-intro__actions { display: flex; flex-wrap: wrap; gap: var(--ns-s-2); }
.ns-wizard { display: flex; flex-direction: column; gap: var(--ns-s-5); }
.ns-wizard__step { display: flex; flex-direction: column; gap: var(--ns-s-5); }
.ns-wizard__step[hidden] { display: none; }
.ns-wizard__footer { display: flex; align-items: center; gap: var(--ns-s-3); flex-wrap: wrap; padding-top: var(--ns-s-3); border-top: 1px solid var(--ns-divider); }
.ns-wizard__footer .ns-sub { flex-grow: 1; }
.ns-error { color: var(--ns-bad-ink); font-size: 14px; font-weight: 600; }
.ns-error:empty { display: none; }
.ns-catalog { display: flex; flex-direction: column; gap: 6px; max-height: 280px; overflow-y: auto; }
.ns-catalog__item { display: flex; flex-direction: column; gap: 2px; min-height: var(--ns-hit); padding: 8px 12px; border-radius: var(--ns-r-sm); border: 1px solid var(--ns-border); background: var(--ns-surface); font: inherit; text-align: left; cursor: pointer; }
.ns-catalog__item[aria-pressed="true"] { border: 2px solid var(--ns-primary); background: var(--ns-surface-selected); }
.ns-catalog__meta { font-size: 12px; color: var(--ns-text-2); }
.ns-toast__title { font-weight: 700; margin-bottom: 4px; }
.ns-toast__body { font-size: 14px; color: var(--ns-text-on-dark-2); }
.ns-toast__actions { display: flex; gap: var(--ns-s-2); margin-top: 10px; }
.ns-toast .ns-btn--quiet { color: #fff; }
.ns-toast[hidden] { display: none; }
.ns-dialog__head { display: flex; align-items: flex-start; gap: var(--ns-s-4); }
.ns-dialog__head .ns-h1 { font-size: 34px; }
.ns-dialog__titles { flex-grow: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }

/* ---------- 19. Today ----------------------------------------------------- */
.ns-next__body { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.ns-next__title { font-weight: 700; font-size: 22px; overflow-wrap: anywhere; }
.ns-card--next .ns-strip__counts { color: var(--ns-text-on-dark-2); }
.ns-plan__step { align-items: flex-start; }
.ns-plan__step[data-state="done"] .ns-plan__num { background: var(--ns-ok-bg); border-color: var(--ns-state-mastered); color: var(--ns-ok-ink); }
.ns-plan__body { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.ns-plan__head { display: flex; align-items: baseline; gap: var(--ns-s-3); flex-wrap: wrap; }
.ns-plan__meta { font-size: 13px; color: var(--ns-text-muted); }
.ns-plan__row { display: flex; align-items: center; gap: var(--ns-s-4); }
.ns-plan__row[data-state="done"] .ns-plan__title { color: var(--ns-text-muted); }
.ns-plan__text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ns-plan__title { font-weight: 600; font-size: 16px; }
.ns-plan__cards { display: flex; flex-direction: column; gap: 10px; }
.ns-plan__cards:empty { display: none; }
.ns-plan__card { gap: 8px; }
.ns-plan__card--done { opacity: 0.7; }
.ns-actions { display: flex; gap: var(--ns-s-2); flex-wrap: wrap; }
.ns-row { display: flex; align-items: center; gap: var(--ns-s-2); flex-wrap: wrap; }
.ns-fine { font-size: 13px; color: var(--ns-text-2); }
.ns-fine a { color: var(--ns-link); }
.ns-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.ns-chip { min-height: 36px; padding: 0 14px; border-radius: 18px; border: 1px solid var(--ns-border-strong); background: var(--ns-surface); color: var(--ns-text); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer; width: auto; }
.ns-chip[aria-pressed="true"] { background: var(--ns-ink-panel); border-color: var(--ns-ink-panel); color: #fff; }
.ns-hardstop { text-align: center; padding: var(--ns-s-3) 0; }
/* The check-in card asks for health data one question at a time, so each question carries a
   "?" that opens the reason for asking it. It sits inside the question's label on a row that
   wraps, so the 24px it draws costs that row 24px -- between roughly 480 and 560 the sleep
   row wraps one step earlier than it used to. That is the trade taken: 24px is the smallest
   the circle goes and still be a tap target, and at phone widths the row wrapped already. */
.ns-why { flex: none; width: 24px; height: 24px; min-height: 0; margin-left: 4px; padding: 0; border-radius: 50%; border: 1px solid var(--ns-border-strong); background: var(--ns-surface); color: var(--ns-text-2); font: inherit; font-size: 12px; font-weight: 700; line-height: 1; cursor: pointer; vertical-align: middle; }
.ns-why:hover, .ns-why:focus-visible { background: var(--ns-ink-panel); border-color: var(--ns-ink-panel); color: #fff; }
.ns-dialog--sm { max-width: 520px; }
.ns-dialog--sm .ns-dialog__head .ns-h1 { font-size: 24px; }
.ns-why__grade { align-self: flex-start; padding: 4px 10px; border-radius: 8px; background: var(--ns-bg); border: 1px solid var(--ns-border); font-size: 12px; font-weight: 700; color: var(--ns-text-2); }
.ns-why__grade:empty { display: none; }
.ns-dialog--sm:focus { outline: none; }
.ns-why__body { margin: 4px 0 0; font-size: 14px; line-height: 1.55; color: var(--ns-text); }
.ns-why__sources { padding-top: 10px; border-top: 1px solid var(--ns-divider); font-size: 13px; color: var(--ns-text-2); }
.ns-why__sources:empty { display: none; }
.ns-why__source { margin-bottom: 3px; }
.ns-linklist { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.ns-linklist__item { display: flex; flex-direction: column; gap: 2px; min-height: 56px; padding: 10px 0; justify-content: center; border-bottom: 1px solid var(--ns-divider); color: var(--ns-text); font-weight: 600; text-decoration: none; }
.ns-linklist li:last-child .ns-linklist__item { border-bottom: none; }
.ns-linklist__item .ns-sub { font-weight: 400; }
@media (max-width: 600px) { .ns-plan__row { flex-wrap: wrap; } .ns-plan__step { padding: 14px 16px; } }

/* ---------- 20. Class page --------------------------------------------- */
.ns-classmeter { display: flex; flex-direction: column; gap: 8px; }
.ns-legend { display: flex; align-items: center; gap: var(--ns-s-4); flex-wrap: wrap; font-size: 13px; color: var(--ns-text-2); }
.ns-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.ns-legend__swatch { width: 14px; height: 10px; border-radius: 3px; background: var(--ns-state-new); }
.ns-legend__swatch[data-state="mastered"] { background: var(--ns-state-mastered); }
.ns-legend__swatch[data-state="progress"] { background: var(--ns-state-progress); }
.ns-legend__swatch[data-state="review"] { background: var(--ns-state-review); }
.ns-legend__note { color: var(--ns-text-muted); }
.ns-slot--wide { width: 100%; border-radius: var(--ns-r-lg); font: inherit; font-weight: 600; font-size: 15px; color: var(--ns-primary-ink); background: transparent; cursor: pointer; flex-wrap: wrap; padding: var(--ns-s-3) var(--ns-s-4); }
.ns-slot--wide .ns-slot__hint { width: 100%; text-align: center; }
.ns-chapter__tools { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-chapter__tools .ns-crumb { flex-wrap: wrap; }
.ns-path__item[data-state="failed"] .ns-path__num { border-color: var(--ns-state-review); }
.ns-meter--busy .ns-meter__fill { width: 40%; animation: ns-busy 1.4s ease-in-out infinite alternate; }
@keyframes ns-busy { from { margin-left: 0; } to { margin-left: 60%; } }
@media (prefers-reduced-motion: reduce) { .ns-meter--busy .ns-meter__fill { animation: none; width: 100%; opacity: 0.5; } }
.ns-linklist__button { width: 100%; border: none; background: transparent; font: inherit; font-weight: 600; color: var(--ns-text); text-align: left; cursor: pointer; }
.ns-crumb__button { border: none; background: transparent; padding: 0; font: inherit; color: var(--ns-link); cursor: pointer; }
.ns-concepts__add { grid-column: 1 / -1; }
.ns-danger { color: var(--ns-bad-ink); }
.ns-mobile-only { display: none; }
@media (max-width: 1200px) { .ns-mobile-only { display: block; } .ns-desktop-only { display: none; } }
.ns-mobile-only summary { list-style: none; }
.ns-mobile-only summary::-webkit-details-marker { display: none; }

/* ---------- 21. Review, Mind tools, Search --------------------------------- */
.ns-answer { padding: var(--ns-s-4); border-radius: var(--ns-r-md); background: var(--ns-surface-soft); border: 1px solid var(--ns-border); font-size: 16px; line-height: 1.5; }
.ns-grades { border: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-grades legend { padding: 0; margin-bottom: var(--ns-s-2); }
.ns-bars { display: flex; gap: 6px; align-items: flex-end; height: 140px; }
.ns-bars__col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; }
.ns-bars__value { font-size: 12px; font-weight: 600; color: var(--ns-text-2); }
.ns-bars__bar { flex-grow: 1; width: 100%; display: flex; align-items: flex-end; background: var(--ns-surface-soft); border-radius: 6px; overflow: hidden; }
.ns-bars__fill { width: 100%; background: var(--ns-primary); border-radius: 6px 6px 0 0; min-height: 2px; }
.ns-bars__label { font-size: 11px; color: var(--ns-text-muted); }
.ns-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.ns-table th, .ns-table td { text-align: left; padding: 8px 6px; border-bottom: 1px solid var(--ns-divider); }
.ns-table th { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ns-text-muted); }
.ns-toolgroup { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-toolcard { text-decoration: none; color: var(--ns-text); gap: 6px; min-height: 96px; }
.ns-toolcard__title { font-weight: 700; font-size: 16px; }
.ns-toolcard:hover { border-color: var(--ns-primary); }
.ns-searchform { display: flex; gap: var(--ns-s-2); }
.ns-searchform .ns-input { flex-grow: 1; min-width: 0; }
.ns-crumb--page { padding: var(--ns-s-3) var(--ns-s-12) 0; }
@media (max-width: 600px) { .ns-crumb--page { padding: var(--ns-s-3) var(--ns-s-4) 0; } }

/* ---------- 22. Session start ---------------------------------------------- */
.ns-spinner { width: 28px; height: 28px; border-radius: 50%; border: 3px solid var(--ns-border); border-top-color: var(--ns-primary); animation: ns-spin 0.9s linear infinite; flex-shrink: 0; }
@keyframes ns-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ns-spinner { animation: none; border-top-color: var(--ns-border); } }
.ns-spinner[hidden] { display: none; }

/* ---------- 23. Focus pages: Daily five, Flashcards, Onboarding ------------ */
.ns-focus__main { width: 100%; max-width: 860px; margin: 0 auto; box-sizing: border-box; padding: var(--ns-s-8) var(--ns-s-6); display: flex; flex-direction: column; gap: var(--ns-s-5); }
.ns-focus__main--wide { max-width: 1040px; }
@media (max-width: 600px) { .ns-focus__main { padding: var(--ns-s-5) var(--ns-s-4); gap: var(--ns-s-4); } }
.ns-focusbar__actions { display: flex; gap: var(--ns-s-2); margin-left: auto; }
@media (max-width: 900px) { .ns-focusbar .ns-btn__label { display: none; } .ns-focusbar { padding: 0 var(--ns-s-3); gap: var(--ns-s-2); } }
.ns-blocks { display: flex; gap: 6px; }
.ns-blocks__block { flex: 1 1 0; height: 10px; border-radius: 4px; background: #c3ccda; }
.ns-blocks__block[data-state="done"] { background: var(--ns-state-mastered); }
.ns-blocks__block[data-state="current"] { background: var(--ns-primary); }
.ns-blocks__block[data-state="missed"] { background: var(--ns-state-review); }
.ns-focuscard { display: flex; gap: var(--ns-s-7); }
.ns-focuscard__body { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-focuscard__title { font-size: 28px; font-weight: 700; line-height: 1.2; }
.ns-focuscard__text { font-size: 18px; line-height: 1.65; white-space: pre-wrap; }
.ns-focuscard__media { width: 260px; max-height: 320px; flex-shrink: 0; border-radius: var(--ns-r-md); background: var(--ns-surface-soft); object-fit: contain; }
@media (max-width: 900px) { .ns-focuscard { flex-direction: column; } .ns-focuscard__media { width: 100%; } }
.ns-focuscard__actions { display: flex; gap: var(--ns-s-3); flex-wrap: wrap; margin-top: auto; padding-top: var(--ns-s-2); }
.ns-status { padding: var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); font-size: 15px; line-height: 1.5; }
.ns-status--ok { border-color: var(--ns-state-mastered); background: var(--ns-ok-bg, #e8f5ee); }
.ns-status--bad { border-color: var(--ns-state-review); background: var(--ns-bad-bg, #fbeaea); }
.ns-segmented { display: inline-flex; padding: 3px; border-radius: var(--ns-r-md); background: var(--ns-surface-soft); border: 1px solid var(--ns-border); }
.ns-segmented__btn { display: inline-flex; align-items: center; height: 38px; padding: 0 var(--ns-s-4); border-radius: 9px; border: none; background: transparent; font: inherit; font-size: 14px; font-weight: 600; color: var(--ns-text-2); text-decoration: none; cursor: pointer; }
.ns-segmented__btn[aria-current="page"], .ns-segmented__btn[aria-pressed="true"] { background: var(--ns-surface); color: var(--ns-text); box-shadow: 0 1px 2px rgba(45, 59, 82, 0.12); }
.ns-flashcard { min-height: 320px; justify-content: center; text-align: center; align-items: center; }
.ns-flashcard .ns-focuscard__title { font-size: 32px; }
.ns-flashcard .ns-answer { text-align: left; width: 100%; box-sizing: border-box; }
.ns-flashcard:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }
.ns-grades--row { flex-direction: row; }
.ns-grades--row .ns-btn { flex: 1 1 0; }
.ns-kbd { display: inline-block; min-width: 18px; padding: 0 5px; border-radius: 5px; border: 1px solid var(--ns-border-strong); background: var(--ns-surface); font-size: 12px; font-family: inherit; color: var(--ns-text-2); }
.ns-media-list { display: grid; gap: var(--ns-s-3); }
.ns-media-list > * { padding: var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); }
.ns-video { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: var(--ns-r-md); background: #0f172a; }
.ns-reader-scrim { position: fixed; inset: 0; z-index: 12000; display: flex; align-items: center; justify-content: center; padding: var(--ns-s-6); background: rgba(45, 59, 82, 0.96); }
.ns-reader-scrim .ns-reader { min-width: min(92vw, 900px); }
.ns-reader-scrim__close { position: absolute; top: 18px; right: 18px; }

/* ---------- 24. Progress tabs, KPIs, mastery rows --------------------------- */
.ns-kpi { display: flex; flex-direction: column; gap: 4px; padding: var(--ns-s-4); border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); min-width: 0; }
.ns-kpi__value { font-size: 28px; font-weight: 700; line-height: 1.1; }
@media (max-width: 900px) { .ns-grid-4.ns-grid-4--kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ns-mastery { display: flex; flex-direction: column; }
.ns-mastery__row { display: flex; align-items: center; gap: var(--ns-s-4); min-height: 56px; padding: 10px 0; border-bottom: 1px solid var(--ns-divider); color: var(--ns-text); text-decoration: none; }
.ns-mastery__row:last-child { border-bottom: none; }
.ns-mastery__titles { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ns-mastery__name { font-weight: 600; }
.ns-mastery__strip { flex: 1 1 0; min-width: 160px; }
@media (max-width: 600px) { .ns-mastery__row { flex-wrap: wrap; } .ns-mastery__strip { flex-basis: 100%; } }
.ns-awards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--ns-s-3); }
.ns-award { display: flex; flex-direction: column; gap: 4px; padding: var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface); }
.ns-award[data-locked="true"] { opacity: 0.6; }
.ns-award__name { font-weight: 700; }

/* ---------- 25. Account ---------------------------------------------------- */
.ns-rows { display: flex; flex-direction: column; border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); overflow: hidden; }
.ns-rows__group { margin: 0 0 var(--ns-s-3); padding: 0 var(--ns-s-1); }
.ns-rowlink { display: flex; align-items: center; gap: var(--ns-s-3); min-height: 56px; padding: 0 var(--ns-s-4); width: 100%; box-sizing: border-box; border: none; border-bottom: 1px solid var(--ns-divider); background: transparent; font: inherit; font-weight: 600; color: var(--ns-text); text-align: left; text-decoration: none; cursor: pointer; }
.ns-rows > .ns-rowlink:last-child, .ns-rows > details:last-child > .ns-rowlink { border-bottom: none; }
.ns-rowlink .ns-sub { font-weight: 400; }
.ns-rowlink__text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ns-rowlink__chev { color: var(--ns-text-muted); flex-shrink: 0; transition: transform 0.15s; }
.ns-rows details[open] > .ns-rowlink .ns-rowlink__chev { transform: rotate(90deg); }
.ns-rows details > summary { list-style: none; }
.ns-rows details > summary::-webkit-details-marker { display: none; }
.ns-rows__body { padding: var(--ns-s-2) var(--ns-s-4) var(--ns-s-5); border-bottom: 1px solid var(--ns-divider); display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-rows details:last-child .ns-rows__body { border-bottom: none; }
.ns-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ns-s-4); }
@media (max-width: 600px) { .ns-form-grid { grid-template-columns: minmax(0, 1fr); } }
.ns-field select, .ns-select { height: var(--ns-hit); padding: 0 var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); font: inherit; font-size: 15px; color: var(--ns-text); }
.ns-toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); min-height: 48px; }
.ns-toggle input { width: 22px; height: 22px; flex-shrink: 0; }
.ns-toggle__text { display: flex; flex-direction: column; gap: 2px; }
.ns-toggle__text strong { font-size: 15px; }
.ns-swatches { display: flex; gap: var(--ns-s-2); flex-wrap: wrap; }
.ns-swatch { display: flex; align-items: center; gap: 8px; height: var(--ns-hit); padding: 0 var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); font: inherit; font-size: 14px; font-weight: 600; color: var(--ns-text); cursor: pointer; }
.ns-swatch[aria-pressed="true"] { border: 2px solid var(--ns-primary); background: var(--ns-surface-selected); }
.ns-swatch__dot { width: 14px; height: 14px; border-radius: 50%; border: 1px solid rgba(0,0,0,0.15); }
.ns-plan__meterrow { display: flex; flex-direction: column; gap: 6px; }
.ns-plan__meterrow .ns-row { justify-content: space-between; }
.ns-footerlinks { display: flex; gap: var(--ns-s-5); justify-content: center; padding: var(--ns-s-6) 0; font-size: 14px; }
.ns-footerlinks a, .ns-footerlinks button { font: inherit; font-size: 14px; color: var(--ns-text-2); background: none; border: none; padding: 0; cursor: pointer; text-decoration: underline; }
.ns-footerlinks .ns-danger { color: var(--ns-bad-ink); }
.ns-token-list { display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-token-list__item { display: flex; align-items: center; gap: var(--ns-s-3); padding: var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); font-size: 14px; }
.ns-token-list__item .ns-sub { flex-grow: 1; }
.ns-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; word-break: break-all; padding: var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); }
.ns-progress-head { padding: var(--ns-s-6) var(--ns-s-6) 0; margin: 0 auto; box-sizing: border-box; }
.ns-progress-tabs { margin-top: var(--ns-s-2); }
.ns-account-grid { grid-template-columns: minmax(280px, 0.9fr) minmax(0, 1.2fr); gap: var(--ns-s-5); align-items: start; }
@media (max-width: 900px) { .ns-account-grid { grid-template-columns: minmax(0, 1fr); } }
.ns-account-rows { display: flex; flex-direction: column; gap: var(--ns-s-4); min-width: 0; }
.ns-rows details[open] > summary svg { transform: rotate(180deg); }
.ns-rowlink svg { flex-shrink: 0; color: var(--ns-text-muted); transition: transform 0.15s; }

/* ---------- 26. Phone width chrome -------------------------------------- */
@media (max-width: 600px) {
  .ns-header { padding-left: var(--ns-s-3); padding-right: var(--ns-s-3); gap: var(--ns-s-3); }
  .ns-header__brand { font-size: 24px; }
  .ns-header__actions { gap: var(--ns-s-1); }
  .ns-focusbar { gap: var(--ns-s-2); }
  .ns-focusbar__title { min-width: 0; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
  .ns-focusbar .ns-steps { gap: 4px; margin: 0; }
  .ns-focusbar .ns-steps__step { padding: 0 9px; height: 30px; }
  .ns-focusbar .ns-steps__label { display: none; }
  .ns-focusbar__actions .ns-btn { padding: 0 var(--ns-s-3); }
}
@media (max-width: 900px) {
  .ns-tabbar { width: 100%; box-sizing: border-box; }
}
.ns-typed > summary { cursor: pointer; }

/* ---------- 27. Page reset, safe areas and the AI credit usage dialog ------ */
html, body { margin: 0; padding: 0; }
:root { --app-safe-top: env(safe-area-inset-top, 0px); --app-safe-left: env(safe-area-inset-left, 0px); --app-safe-right: env(safe-area-inset-right, 0px); --app-header-bg: var(--ns-surface); }
body::before { content: ""; position: fixed; top: 0; left: 0; right: 0; height: var(--app-safe-top); background: var(--app-header-bg); z-index: 999; pointer-events: none; }
.ai-credit-overlay { position: fixed; inset: 0; z-index: 2200; display: none; align-items: center; justify-content: center; padding: var(--ns-s-5); background: rgba(45, 59, 82, 0.45); }
.ai-credit-overlay.open { display: flex; }
.ai-credit-dialog { width: min(560px, 94vw); max-height: min(720px, 88vh); overflow: auto; border: 1px solid var(--ns-border); border-radius: var(--ns-r-lg); background: var(--ns-surface); color: var(--ns-text); box-shadow: 0 24px 60px rgba(45, 59, 82, 0.24); }
.ai-credit-dialog-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ns-s-4); padding: 18px 20px 12px; border-bottom: 1px solid var(--ns-divider); }
.ai-credit-dialog-title { margin: 0; font-size: 18px; line-height: 1.25; font-weight: 700; }
.ai-credit-dialog-subtitle { margin-top: 4px; color: var(--ns-text-2); font-size: 14px; }
.ai-credit-close { width: var(--ns-hit); height: var(--ns-hit); border: 1px solid var(--ns-border-strong); border-radius: var(--ns-r-md); background: var(--ns-surface); color: var(--ns-text); cursor: pointer; font-size: 18px; line-height: 1; }
.ai-credit-close:hover, .ai-credit-close:focus-visible { border-color: var(--ns-primary); outline: none; }
.ai-credit-dialog-body { padding: 16px 20px 20px; }
.ai-credit-total-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--ns-s-3); padding: 12px 14px; border: 1px solid var(--ns-border); border-radius: var(--ns-r-md); background: var(--ns-surface-soft); margin-bottom: 14px; }
.ai-credit-total-label { color: var(--ns-text-2); font-size: 14px; font-weight: 600; }
.ai-credit-total-value { font-size: 20px; font-weight: 800; white-space: nowrap; }
.ai-credit-breakdown-list { display: grid; gap: 10px; }
.ai-credit-breakdown-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--ns-divider); }
.ai-credit-breakdown-row:last-child { border-bottom: none; }
.ai-credit-breakdown-label { font-weight: 700; line-height: 1.25; }
.ai-credit-breakdown-meta { margin-top: 3px; color: var(--ns-text-2); font-size: 13px; }
.ai-credit-breakdown-value { color: var(--ns-ok-ink); font-weight: 800; white-space: nowrap; }
.ai-credit-empty, .ai-credit-error { padding: 16px; border-radius: var(--ns-r-md); background: var(--ns-surface-soft); color: var(--ns-text-2); border: 1px solid var(--ns-border); }
.ai-credit-error { color: var(--ns-bad-ink); border-color: var(--ns-state-review); background: var(--ns-bad-bg); }

/* ---------- 28. Calibration intro (Progress > Calibration) ---------------- */
/* The first-visit panel rides .ns-scrim / .ns-dialog--sm; only its prose and the
   link that reopens it need rules. The .ns-h1 reset is the legacy sheet's doing:
   static/css/style.css styles every bare h1 centred and gradient-filled with
   -webkit-text-fill-color: transparent, which .ns-h1 does not undo, so a dialog
   title on a page that still loads that sheet renders pale and centred. */
.ns-dialog .ns-h1 { text-align: left; color: var(--ns-text); background: none; -webkit-text-fill-color: currentColor; text-shadow: none; }
.ns-intro__body { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ns-text); }
.ns-intro__steps { margin: 0; padding-left: var(--ns-s-5); font-size: 15px; line-height: 1.55; color: var(--ns-text); }
.ns-intro__steps li { margin-bottom: var(--ns-s-2); }
.ns-intro__steps li:last-child { margin-bottom: 0; }
.ns-intro__note { margin: 0; padding: var(--ns-s-3) 14px; border-radius: var(--ns-r-sm); background: var(--ns-primary-tint); color: var(--ns-primary-ink); font-size: 14px; line-height: 1.55; }
/* The reopen control sits under the page lead, so it loses .ns-btn's side padding
   and keeps its 44px target. */
.ns-intro-reopen { margin: -12px 0 var(--ns-s-5); }
.ns-intro-reopen .ns-btn { padding: 0; text-decoration: underline; }

/* ---------- 29. Study calendar (/calendar, /calendar/setup, /calendar/launch) -- */
/* Month grid of scheduled and completed sessions. Chips are colour-coded by kind but
   every chip also carries a text kind label, so colour never carries meaning alone. */
.ns-cal__toolbar { display: flex; align-items: center; gap: var(--ns-s-2); flex-wrap: wrap; }
.ns-cal__toolbar .ns-cal__spacer { flex: 1; }
.ns-cal__month { min-width: 160px; text-align: center; font-weight: 700; font-size: 17px; }
.ns-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.ns-cal__dow { text-align: center; font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ns-text-muted); padding: 4px 0; }
.ns-cal__day { display: flex; flex-direction: column; gap: 4px; min-height: 124px; padding: 6px; border-radius: var(--ns-r-md); background: var(--ns-surface); border: 1px solid var(--ns-border); }
/* Days outside the month read as quieter by ground and ink, not opacity: faded text fell to 2:1. */
.ns-cal__day--other { background: var(--ns-surface-soft); border-style: dashed; }
.ns-cal__day--other .ns-cal__num { color: var(--ns-text-muted); }
.ns-cal__day--past { background: var(--ns-surface-soft); }
.ns-cal__day--today { border: 2px solid var(--ns-primary); }
.ns-cal__day--dragover { border-color: var(--ns-state-mastered); background: var(--ns-ok-bg); }
.ns-cal__num { display: flex; justify-content: space-between; align-items: center; font-size: 13px; font-weight: 700; color: var(--ns-text-2); }
.ns-cal__add { min-width: 32px; min-height: 32px; padding: 0; border: none; border-radius: 8px; background: transparent; color: var(--ns-link); font: inherit; font-size: 18px; line-height: 1; cursor: pointer; }
.ns-cal__add:hover, .ns-cal__add:focus-visible { background: var(--ns-primary-tint); }
.ns-cal__chips { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.ns-cal__chip { display: block; width: 100%; box-sizing: border-box; text-align: left; font: inherit; font-size: 12px; line-height: 1.3; padding: 4px 6px; border-radius: 6px; border: 1px solid var(--ns-border); background: var(--ns-surface-soft); color: var(--ns-text); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ns-cal__chip[data-kind="learn"] { background: var(--ns-primary-tint); border-color: var(--ns-primary-tint); color: var(--ns-primary-ink); }
.ns-cal__chip[data-kind="review_display"] { background: #ece7f7; border-color: #ece7f7; color: #4a3a7a; }
.ns-cal__chip[data-kind="review_eval"] { background: #f8efd9; border-color: #f8efd9; color: #6b4d12; }
.ns-cal__chip--done { background: var(--ns-ok-bg); border-color: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-cal__chip--abandoned { border-style: dashed; }
.ns-cal__chip--skipped { text-decoration: line-through; color: var(--ns-text-muted); }
.ns-cal__chip--dragging { opacity: 0.4; }
.ns-cal__chip[draggable="true"] { cursor: grab; }
.ns-cal__kind { font-weight: 700; }
.ns-cal__delta { font-weight: 700; }
.ns-cal__mastery { display: flex; justify-content: space-between; margin-top: auto; padding-top: 3px; border-top: 1px solid var(--ns-divider); font-size: 12px; color: var(--ns-text-muted); }
.ns-cal__mastery strong { color: var(--ns-text); }
.ns-cal__mastery--projected strong { color: var(--ns-text-muted); }
.ns-cal__legend { display: flex; flex-wrap: wrap; gap: var(--ns-s-3); font-size: 13px; color: var(--ns-text-2); }
.ns-cal__legend span::before { content: ''; display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: middle; background: var(--ns-border-strong); }
.ns-cal__legend [data-kind="learn"]::before { background: var(--ns-primary); }
.ns-cal__legend [data-kind="review_display"]::before { background: #8a74c9; }
.ns-cal__legend [data-kind="review_eval"]::before { background: var(--ns-state-progress); }
.ns-cal__legend [data-kind="done"]::before { background: var(--ns-state-mastered); }
.ns-cal__agenda { display: none; flex-direction: column; gap: var(--ns-s-2); }
.ns-cal__aday { display: flex; flex-direction: column; gap: 4px; padding: var(--ns-s-3); border-radius: var(--ns-r-md); background: var(--ns-surface); border: 1px solid var(--ns-border); }
.ns-cal__aday--today { border: 2px solid var(--ns-primary); }
.ns-cal__aday .ns-cal__chip { white-space: normal; font-size: 14px; padding: 8px 10px; min-height: var(--ns-hit); }
.ns-cal__ahead { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-2); }
.ns-cal__atitle { font-size: 15px; font-weight: 700; }
.ns-cal__aday--today .ns-cal__atitle { color: var(--ns-primary-ink); }
/* Phone and tablet: the same month grid, compact. Cells show a bar per session (completed ones green) and the
   day's mastery; tapping a cell shows that day's sessions in the agenda card under the grid. */
.ns-cal__pick, .ns-cal__marks { display: none; }
.ns-cal__marks { flex-direction: column; gap: 3px; }
.ns-cal__mark { display: block; height: 5px; border-radius: 3px; background: var(--ns-border-strong); }
.ns-cal__mark[data-kind="learn"] { background: var(--ns-primary); }
.ns-cal__mark[data-kind="review_display"] { background: #8a74c9; }
.ns-cal__mark[data-kind="review_eval"] { background: var(--ns-state-progress); }
.ns-cal__mark--done { background: var(--ns-state-mastered); }
.ns-cal__mark--skipped { opacity: 0.35; }
.ns-cal__more { font-size: 10px; line-height: 1; color: var(--ns-text-muted); }
@media (max-width: 900px) {
  .ns-cal__grid { gap: 3px; }
  .ns-cal__dow { font-size: 11px; }
  .ns-cal__day { position: relative; min-height: 78px; padding: 4px; gap: 3px; }
  .ns-cal__day--selected { background: var(--ns-primary-tint); }
  .ns-cal__day .ns-cal__chips, .ns-cal__day .ns-cal__add { display: none; }
  .ns-cal__marks { display: flex; }
  .ns-cal__day .ns-cal__mastery { padding-top: 0; border-top: none; font-size: 10px; }
  .ns-cal__day .ns-cal__mastery span + span { display: none; }
  /* body.ns-coach: the legacy sheet's bare-button rule (position, fill, shadow, hover sheen) outranks a single class. */
  body.ns-coach .ns-cal__pick { display: block; position: absolute; inset: 0; width: 100%; padding: 0; border: none; border-radius: inherit; background: transparent; box-shadow: none; cursor: pointer; }
  body.ns-coach .ns-cal__pick::after { content: none; }
  .ns-cal__pick:focus-visible { outline: 2px solid var(--ns-primary); outline-offset: 1px; }
  .ns-cal__agenda { display: flex; }
}
/* Per-concept progress list in the session dialog. */
.ns-cal__ideas { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ns-cal__idea { display: flex; gap: var(--ns-s-3); align-items: flex-start; padding: 8px 0; border-top: 1px solid var(--ns-divider); font-size: 14px; }
.ns-cal__badge { flex: 0 0 auto; min-width: 56px; text-align: center; padding: 3px 8px; border-radius: 8px; font-size: 12px; font-weight: 700; background: var(--ns-surface-soft); color: var(--ns-text-2); }
.ns-cal__badge--up { background: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-cal__badge--down { background: var(--ns-bad-bg); color: var(--ns-bad-ink); }
/* Setup page: pace options are ns-choice cards; the estimate is a soft card with KPIs. */
.ns-cal__choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ns-s-3); }
@media (max-width: 600px) { .ns-cal__choices { grid-template-columns: minmax(0, 1fr); } }
.ns-cal__choice-title { font-weight: 700; }
.ns-cal__kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ns-s-3); }
@media (max-width: 900px) { .ns-cal__kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ns-cal__preview { display: flex; flex-direction: column; gap: 4px; font-size: 14px; color: var(--ns-text-2); }
/* Launcher: the breathing orb and the step cards. */
.ns-cal__steps { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-cal__step-done { margin-left: auto; font-size: 13px; font-weight: 600; color: var(--ns-ok-ink); }
.ns-cal__orb { width: 150px; height: 150px; margin: var(--ns-s-4) auto; border-radius: 50%; background: radial-gradient(circle, var(--ns-primary) 0%, var(--ns-primary-tint) 70%); transform: scale(0.7); transition: transform 4s ease-in-out; }
.ns-cal__orb--in { transform: scale(1); transition-duration: 4s; }
.ns-cal__orb--sip { transform: scale(1.12); transition-duration: 1s; }
.ns-cal__orb--out { transform: scale(0.7); transition-duration: 8s; }
@media (prefers-reduced-motion: reduce) { .ns-cal__orb { transition: none; } }
.ns-cal__cue { text-align: center; font-size: 18px; min-height: 1.5em; }
.ns-cal__timer { text-align: center; font-variant-numeric: tabular-nums; color: var(--ns-text-muted); }

/* ---------- 30. Onboarding (/onboarding) -----------------------------------
   Motion explains, it does not decorate: steps slide in the direction of travel, the four
   moves of a session appear in order, the technique bars grow after the learner guesses, the
   forgetting curve draws when its card opens (never on a loop), and a tick closes the flow.
   Durations follow Material 3 (short 200ms, medium 300-400ms, long 500ms+) with the
   emphasized-decelerate curve. prefers-reduced-motion shows every end state at once.
   Spec: docs/ui-revamp/screens/onboarding.md.
   ------------------------------------------------------------------------ */
/* overflow-x: clip keeps a step sliding in from the side from widening the page (it does not
   create a scroll container, so sticky and focus rings inside the padding are unaffected). */
.ns-onb { --ns-onb-ease: cubic-bezier(0.05, 0.7, 0.1, 1); overflow-x: clip; }
.ns-onb__lead { margin: 0; font-size: 16px; line-height: 1.5; color: var(--ns-text-2); max-width: 640px; }
.ns-onb__h2 { margin: var(--ns-s-2) 0 0; font-size: 20px; font-weight: 700; }
.ns-onb__fields { display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-onb__fieldset { margin: 0; padding: 0; border: none; display: flex; flex-direction: column; gap: var(--ns-s-2); min-width: 0; }
.ns-onb__fieldset legend { padding: 0; margin-bottom: var(--ns-s-2); }
.ns-onb__scene { display: flex; flex-direction: column; gap: var(--ns-s-5); }
/* A topic chapter is named after its concepts are picked; keep the field clear of the concept list. */
.ns-onb__title-field { margin-top: var(--ns-s-4); }
.ns-onb__scene[hidden] { display: none; }
/* Five step pills leave little room at phone width; the Skip label must stay one line. */
body.ns-focus .ns-focusbar__actions .ns-btn { white-space: nowrap; }
/* Chips carry a choice here, so they get the full touch target. */
.ns-onb .ns-onb__chips .ns-chip { min-height: var(--ns-hit); padding: 0 var(--ns-s-4); transition: background-color 0.2s, border-color 0.2s, color 0.2s, transform 0.12s; }
body.ns-coach .ns-onb .ns-chip { background: var(--ns-surface); border: 1px solid var(--ns-border-strong); color: var(--ns-text); box-shadow: none; }
body.ns-coach .ns-onb .ns-chip[aria-pressed="true"] { background: var(--ns-ink-panel); border-color: var(--ns-ink-panel); color: #fff; }
.ns-onb .ns-chip:active, .ns-onb .ns-choice:active { transform: scale(0.97); }
.ns-onb .ns-choice { transition: background-color 0.2s, border-color 0.2s, transform 0.12s, box-shadow 0.2s; }
.ns-onb .ns-chip:focus-visible, .ns-onb .ns-choice:focus-visible, .ns-onb-science__head:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }

/* The legacy theme sheet styles bare buttons and spans (neumorphic shadows, link-blue text) and
   outranks a single class; re-assert the Coach look inside the wizard. */
body.ns-coach .ns-onb .ns-choice { background: var(--ns-surface); border: 1px solid var(--ns-border); color: var(--ns-text); box-shadow: none; }
body.ns-coach .ns-onb .ns-choice[aria-pressed="true"] { background: var(--ns-surface-selected); border: 2px solid var(--ns-primary); }
body.ns-coach body.ns-coach .ns-onb .ns-choice::after, body.ns-coach .ns-onb .ns-chip::after { content: none; }
body.ns-coach .ns-onb .ns-btn { box-shadow: none; }
body.ns-coach .ns-onb .ns-input, body.ns-coach .ns-onb .ns-textarea, body.ns-coach .ns-onb .ns-select { background: var(--ns-surface); border: 1px solid var(--ns-border-strong); box-shadow: none; color: var(--ns-text); }
body.ns-coach .ns-onb .ns-choice__label { color: var(--ns-text); }
body.ns-coach .ns-onb .ns-choice__hint { color: var(--ns-text-2); }
body.ns-coach .ns-onb .ns-onb-loop__num { color: #fff; }
/* Step and scene entrances, in the direction of travel. */
.ns-onb__step[data-enter="forward"], .ns-onb__scene[data-enter="forward"] { animation: ns-onb-in-fwd 0.36s var(--ns-onb-ease) both; }
.ns-onb__step[data-enter="back"] { animation: ns-onb-in-back 0.36s var(--ns-onb-ease) both; }
@keyframes ns-onb-in-fwd { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes ns-onb-in-back { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: none; } }
@keyframes ns-onb-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* The four moves of a session, revealed in order with a line joining them. */
.ns-onb-loop { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-onb-loop__item { position: relative; display: flex; gap: var(--ns-s-4); align-items: flex-start; padding: var(--ns-s-4) var(--ns-s-5); border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); animation: ns-onb-rise 0.4s var(--ns-onb-ease) both; }
.ns-onb-loop__item:nth-child(2) { animation-delay: 0.12s; }
.ns-onb-loop__item:nth-child(3) { animation-delay: 0.24s; }
.ns-onb-loop__item:nth-child(4) { animation-delay: 0.36s; }
.ns-onb-loop__item:not(:last-child)::after { content: ""; position: absolute; left: 37px; top: 52px; width: 2px; height: calc(100% - 24px); background: var(--ns-border-strong); transform-origin: top; animation: ns-onb-grow 0.3s ease-out both; animation-delay: inherit; z-index: 1; }
@keyframes ns-onb-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.ns-onb-loop__num { width: 36px; height: 36px; flex-shrink: 0; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--ns-primary); color: #fff; font-weight: 700; font-size: 15px; position: relative; z-index: 2; }
.ns-onb-loop__item:nth-child(4) .ns-onb-loop__num { background: var(--ns-state-mastered); }
.ns-onb-loop__body { display: flex; flex-direction: column; gap: 4px; min-width: 0; font-size: 15px; line-height: 1.45; color: var(--ns-text-2); }
.ns-onb-loop__body strong { font-size: 16px; color: var(--ns-text); }

/* Predict, then reveal. The fills start empty and grow once data-shown is set. */
.ns-onb-reveal { animation: ns-onb-rise 0.3s var(--ns-onb-ease) both; }
.ns-onb-reveal__verdict { margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; }
.ns-onb-bars { display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-onb-bars__row { display: grid; grid-template-columns: 140px minmax(0, 1fr) 72px; gap: var(--ns-s-3); align-items: center; font-size: 14px; }
.ns-onb-bars__label { font-weight: 600; }
.ns-onb-bars__track { height: 14px; border-radius: 7px; background: var(--ns-divider); overflow: hidden; }
.ns-onb-bars__fill { display: block; height: 100%; width: 0; border-radius: 7px; background: var(--ns-state-review); transition: width 0.7s var(--ns-onb-ease); }
.ns-onb-bars__fill[data-level="high"] { background: var(--ns-state-mastered); }
.ns-onb-bars__row:nth-child(2) .ns-onb-bars__fill { transition-delay: 0.08s; }
.ns-onb-bars__row:nth-child(3) .ns-onb-bars__fill { transition-delay: 0.16s; }
.ns-onb-bars__row:nth-child(4) .ns-onb-bars__fill { transition-delay: 0.24s; }
.ns-onb-bars__row:nth-child(5) .ns-onb-bars__fill { transition-delay: 0.32s; }
.ns-onb-reveal[data-shown="true"] .ns-onb-bars__fill[data-level="high"] { width: 92%; }
.ns-onb-reveal[data-shown="true"] .ns-onb-bars__fill[data-level="low"] { width: 22%; }
.ns-onb-bars__value { font-weight: 700; text-align: right; }
@media (max-width: 600px) { .ns-onb-bars__row { grid-template-columns: 104px minmax(0, 1fr) 44px; font-size: 13px; } }

/* Science cards: one line visible, the finding and its source one tap away. */
.ns-onb-science { border-radius: var(--ns-r-lg); background: var(--ns-primary-tint); border: 1px solid var(--ns-primary-tint); }
.ns-onb-science__head { display: flex; flex-direction: column; gap: 2px; min-height: var(--ns-hit); padding: var(--ns-s-3) var(--ns-s-10) var(--ns-s-3) var(--ns-s-4); box-sizing: border-box; justify-content: center; list-style: none; cursor: pointer; position: relative; border-radius: var(--ns-r-lg); }
.ns-onb-science__head::-webkit-details-marker { display: none; }
.ns-onb-science__head::after { content: ""; position: absolute; right: var(--ns-s-4); top: 50%; width: 8px; height: 8px; margin-top: -6px; border-right: 2px solid var(--ns-primary-ink); border-bottom: 2px solid var(--ns-primary-ink); transform: rotate(45deg); transition: transform 0.2s; }
.ns-onb-science[open] > .ns-onb-science__head::after { transform: rotate(225deg); margin-top: -2px; }
.ns-onb-science__title { font-weight: 700; color: var(--ns-primary-ink); }
.ns-onb-science__body { padding: 0 var(--ns-s-4) var(--ns-s-4); display: flex; flex-direction: column; gap: var(--ns-s-2); font-size: 15px; line-height: 1.5; animation: ns-onb-rise 0.3s var(--ns-onb-ease) both; }
.ns-onb-science__body p { margin: 0; }
.ns-onb-science__body .ns-btn { align-self: flex-start; }

/* The forgetting curve: both lines draw on play; the review dots pop in behind the line. */
.ns-onb-curve { margin: 0; display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-onb-curve svg { width: 100%; max-width: 30rem; height: auto; background: var(--ns-surface); border-radius: var(--ns-r-md); }
.ns-onb-curve__axis { stroke: var(--ns-border-strong); stroke-width: 1.5; }
.ns-onb-curve__forget, .ns-onb-curve__review { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 0; }
.ns-onb-curve__forget { stroke: var(--ns-state-review); stroke-dasharray: 0.02 0.02; }
.ns-onb-curve__review { stroke: var(--ns-state-mastered); }
.ns-onb-curve__dot { fill: var(--ns-primary); }
.ns-onb-curve__label { font-size: 11px; fill: var(--ns-text-2); font-family: var(--ns-font-body); }
.ns-onb-curve[data-play="false"] .ns-onb-curve__review { stroke-dashoffset: 1; }
.ns-onb-curve[data-play="false"] .ns-onb-curve__forget { opacity: 0; }
.ns-onb-curve[data-play="false"] .ns-onb-curve__dot { opacity: 0; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__forget { animation: ns-onb-fade 0.6s ease-out both; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__review { animation: ns-onb-draw 1.8s var(--ns-onb-ease) 0.5s both; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__dot { animation: ns-onb-pop 0.3s ease-out both; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__dot:nth-of-type(1) { animation-delay: 0.8s; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__dot:nth-of-type(2) { animation-delay: 1.2s; }
.ns-onb-curve[data-play="true"] .ns-onb-curve__dot:nth-of-type(3) { animation-delay: 1.7s; }
@keyframes ns-onb-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes ns-onb-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ns-onb-pop { 0% { opacity: 0; transform: scale(0); } 70% { opacity: 1; transform: scale(1.4); } 100% { opacity: 1; transform: scale(1); } }
.ns-onb-curve__dot { transform-box: fill-box; transform-origin: center; }
.ns-onb-curve__legend { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--ns-text-2); }
.ns-onb-curve__key { display: flex; align-items: center; gap: var(--ns-s-2); }
.ns-onb-curve__key::before { content: ""; width: 20px; height: 0; flex-shrink: 0; border-top: 3px solid var(--ns-state-mastered); }
.ns-onb-curve__key--forget::before { border-top: 3px dotted var(--ns-state-review); }

/* The plan sentence settles in each time it changes. */
.ns-onb-plan__sentence { margin: 0; font-size: 20px; font-weight: 700; line-height: 1.35; }
.ns-onb-plan__sentence[data-pulse="true"] { animation: ns-onb-rise 0.3s var(--ns-onb-ease) both; }

/* Start: a tick that draws itself, then a four-row timeline. */
.ns-onb-done svg { display: block; }
.ns-onb-done__ring { fill: var(--ns-ok-bg); stroke: var(--ns-state-mastered); stroke-width: 3; stroke-dasharray: 1; animation: ns-onb-draw 0.5s ease-out both; }
.ns-onb-done__tick { fill: none; stroke: var(--ns-ok-ink); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; animation: ns-onb-draw 0.35s ease-out 0.45s both; }
.ns-onb-timeline { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-onb-timeline__item { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: var(--ns-s-4); padding: var(--ns-s-4); border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); animation: ns-onb-rise 0.4s var(--ns-onb-ease) both; }
.ns-onb-timeline__item:nth-child(2) { animation-delay: 0.1s; }
.ns-onb-timeline__item:nth-child(3) { animation-delay: 0.2s; }
.ns-onb-timeline__item:nth-child(4) { animation-delay: 0.3s; }
.ns-onb-timeline__when { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ns-primary-ink); padding-top: 3px; }
.ns-onb-timeline__what { display: flex; flex-direction: column; gap: 4px; font-size: 15px; line-height: 1.45; color: var(--ns-text-2); }
.ns-onb-timeline__what strong { color: var(--ns-text); font-size: 16px; }
@media (max-width: 600px) { .ns-onb-timeline__item { grid-template-columns: minmax(0, 1fr); gap: var(--ns-s-1); } .ns-onb-loop__item { padding: var(--ns-s-3) var(--ns-s-4); } .ns-onb-loop__item:not(:last-child)::after { left: 33px; top: 48px; } .ns-onb-plan__sentence { font-size: 18px; } }

@media (prefers-reduced-motion: reduce) {
  .ns-onb *, .ns-onb *::before, .ns-onb *::after, .ns-onb__step, .ns-onb__scene { animation: none !important; transition: none !important; }
  .ns-onb-curve[data-play] .ns-onb-curve__review { stroke-dashoffset: 0; }
  .ns-onb-curve[data-play] .ns-onb-curve__forget, .ns-onb-curve[data-play] .ns-onb-curve__dot { opacity: 1; }
}

/* ---------- Focus prep (templates/focus-prep.html) ------------------------
   The pre-study readiness check: numbered answer scales, the tap-test target, a breathing
   guide and a breath counter. The science cards reuse .ns-onb-science, whose entrance easing
   is scoped to .ns-onb, so the same variable is set here. */
.ns-fp { --ns-onb-ease: cubic-bezier(0.05, 0.7, 0.1, 1); }
/* Headings take focus when a step opens (for screen readers), not from the keyboard. */
.ns-fp .ns-h1:focus { outline: none; }
body.ns-coach .ns-fp .ns-btn { box-shadow: none; }
.ns-fp-points { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-fp-points__item { display: flex; flex-direction: column; gap: 4px; padding: var(--ns-s-4) var(--ns-s-5); border-radius: var(--ns-r-lg); background: var(--ns-surface); border: 1px solid var(--ns-border); font-size: 15px; line-height: 1.5; color: var(--ns-text-2); }
.ns-fp-points__item strong { font-size: 16px; color: var(--ns-text); }
.ns-fp-howto { margin: 0; padding-left: var(--ns-s-5); display: flex; flex-direction: column; gap: 6px; font-size: 15px; line-height: 1.5; }
.ns-fp-sources { margin: 0; padding-left: var(--ns-s-5); display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--ns-text-2); overflow-wrap: anywhere; }
.ns-fp-advice { margin: 0; padding-left: var(--ns-s-5); display: flex; flex-direction: column; gap: 4px; font-size: 15px; }
.ns-fp-advice:empty { display: none; }
.ns-fp-alts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ns-s-2); }
.ns-fp-checklist { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-fp-checklist li { padding: 0 var(--ns-s-4); border-radius: var(--ns-r-md); background: var(--ns-surface); border: 1px solid var(--ns-border); }

/* Answer scales: numbered buttons; the label wraps under the number so long labels fit. */
.ns-fp-scale { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 6px; }
.ns-fp-scale--five { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.ns-fp-scale__opt { display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 64px; padding: var(--ns-s-2) 4px; border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); color: var(--ns-text); font: inherit; cursor: pointer; width: auto; text-align: center; }
.ns-fp-scale__num { font-size: 18px; font-weight: 700; }
.ns-fp-scale__label { font-size: 12px; line-height: 1.25; color: var(--ns-text-2); overflow-wrap: anywhere; }
.ns-fp-scale__opt[aria-checked="true"] { background: var(--ns-surface-selected); border: 2px solid var(--ns-primary); }
.ns-fp-scale__opt:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }
body.ns-coach .ns-fp-scale__opt { background: var(--ns-surface); border: 1px solid var(--ns-border-strong); color: var(--ns-text); box-shadow: none; }
body.ns-coach .ns-fp-scale__opt[aria-checked="true"] { background: var(--ns-surface-selected); border: 2px solid var(--ns-primary); }
body.ns-coach .ns-fp-scale__opt::after { content: none; }
@media (max-width: 900px) { .ns-fp-scale { grid-template-columns: repeat(3, minmax(0, 1fr)); } .ns-fp-scale--five { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 600px) { .ns-fp-scale--five { grid-template-columns: minmax(0, 1fr); } .ns-fp-scale--five .ns-fp-scale__opt { flex-direction: row; min-height: var(--ns-hit); padding: 0 var(--ns-s-4); gap: var(--ns-s-3); text-align: left; } .ns-fp-scale--five .ns-fp-scale__label { font-size: 14px; } }

/* The tap-test target: a big zone, not the stimulus itself, so a finger never hides it. */
.ns-fp-runhead { display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-fp-target { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 260px; border-radius: var(--ns-r-2xl); border: 2px solid var(--ns-border-strong); background: var(--ns-surface-soft); color: var(--ns-text-2); font: inherit; cursor: pointer; touch-action: manipulation; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.ns-fp-target__label { font-size: 22px; font-weight: 700; }
.ns-fp-target[data-state="go"] { background: var(--ns-state-mastered); border-color: var(--ns-state-mastered); color: #fff; }
.ns-fp-target[data-state="go"] .ns-fp-target__label { font-family: var(--ns-font-display); font-size: 64px; letter-spacing: 0.06em; }
.ns-fp-target[data-state="hit"] { background: var(--ns-ok-bg); border-color: var(--ns-state-mastered); color: var(--ns-ok-ink); }
.ns-fp-target[data-state="early"] { background: var(--ns-bad-bg); border-color: var(--ns-state-review); color: var(--ns-bad-ink); }
body.ns-coach .ns-fp-target { box-shadow: none; background: var(--ns-surface-soft); color: var(--ns-text-2); }
body.ns-coach .ns-fp-target::after { content: none; }
body.ns-coach .ns-fp-target[data-state="go"] { background: var(--ns-state-mastered); color: #fff; }
body.ns-coach .ns-fp-target[data-state="hit"] { background: var(--ns-ok-bg); color: var(--ns-ok-ink); }
body.ns-coach .ns-fp-target[data-state="early"] { background: var(--ns-bad-bg); color: var(--ns-bad-ink); }
.ns-fp-target:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 3px; }
@media (max-width: 600px) { .ns-fp-target { min-height: 220px; } }

/* Breathing guide: the orb grows on the in-breath and shrinks on the out-breath; data-dur is
   the phase length in seconds, so the animation always matches the cue. */
.ns-fp-breath { display: flex; flex-direction: column; align-items: center; gap: var(--ns-s-4); padding: var(--ns-s-5) 0; }
.ns-fp-breath__orb { width: 200px; height: 200px; border-radius: 50%; background: var(--ns-primary-tint); border: 3px solid var(--ns-primary); transform: scale(0.6); transition-property: transform; transition-timing-function: ease-in-out; transition-duration: 1s; }
.ns-fp-breath[data-phase="in"] .ns-fp-breath__orb { transform: scale(0.9); }
.ns-fp-breath[data-phase="sip"] .ns-fp-breath__orb, .ns-fp-breath[data-phase="hold-in"] .ns-fp-breath__orb { transform: scale(1); }
.ns-fp-breath[data-phase="out"] .ns-fp-breath__orb, .ns-fp-breath[data-phase="hold-out"] .ns-fp-breath__orb, .ns-fp-breath[data-phase="rest"] .ns-fp-breath__orb { transform: scale(0.6); }
.ns-fp-breath[data-dur="1"] .ns-fp-breath__orb { transition-duration: 1s; }
.ns-fp-breath[data-dur="2"] .ns-fp-breath__orb { transition-duration: 2s; }
.ns-fp-breath[data-dur="4"] .ns-fp-breath__orb { transition-duration: 4s; }
.ns-fp-breath[data-dur="6"] .ns-fp-breath__orb { transition-duration: 6s; }
.ns-fp-breath__cue { font-size: 20px; font-weight: 700; text-align: center; min-height: 2.6em; }
@media (prefers-reduced-motion: reduce) { .ns-fp-breath__orb { transition: none; } }
@media (max-width: 600px) { .ns-fp-breath__orb { width: 160px; height: 160px; } }

/* Breath counter and plain timers. */
.ns-fp-count { display: flex; flex-direction: column; align-items: center; gap: var(--ns-s-2); padding: var(--ns-s-4) 0; }
.ns-fp-count__num, .ns-fp-timer { font-family: var(--ns-font-display); font-size: 88px; line-height: 1; font-variant-numeric: tabular-nums; text-align: center; }

/* Today: the Focus prep step's rating row and parked thoughts. */
.ns-fp-rating { display: flex; flex-wrap: wrap; gap: var(--ns-s-2); }
.ns-fp-rating .ns-btn { min-width: var(--ns-hit); }
.ns-fp-parked { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ns-s-2); }
.ns-fp-parked li { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); font-size: 15px; overflow-wrap: anywhere; }
.ns-fp-kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ns-s-3); }
.ns-fp-kpis:empty { display: none; }
@media (max-width: 600px) { .ns-fp-kpis { gap: var(--ns-s-2); } .ns-fp-kpis .ns-kpi { padding: var(--ns-s-3); } .ns-fp-kpis .ns-kpi__value { font-size: 22px; } }

/* ---------- 31. Vocabulary words (static/js/ns-vocab.js) --------------------
   Session and review text marks the chapter's vocabulary words; tapping one opens its
   definition in a small dialog. The mark is a translucent tint plus an underline, so it reads
   on the light Coach cards and on the dark legacy display panels alike and never relies on
   colour alone. The words stay inline in their sentence, so they keep the text's line height
   instead of the 44px target (WCAG 2.5.8 exempts targets inside a sentence); the dialog's
   Close button is full size. The legacy sheets style every bare button -- fill, padding, full
   width at phone size, a lift on hover and a sheen in ::before/::after -- so all of it is reset. */
body.ns-coach button.ns-vocab,
body.ns-coach button.ns-vocab:hover,
body.ns-coach button.ns-vocab:active { display: inline; width: auto; min-width: 0; height: auto; min-height: 0; margin: 0; padding: 0 1px; border: 0; border-radius: 3px; background: rgba(61, 109, 179, 0.12); box-shadow: none; transform: none; position: static; overflow: visible; backdrop-filter: none; color: inherit; font: inherit; letter-spacing: inherit; text-transform: none; text-align: inherit; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; vertical-align: baseline; cursor: pointer; transition: background-color 0.15s ease; }
body.ns-coach button.ns-vocab:hover { background: rgba(61, 109, 179, 0.32); }
body.ns-coach button.ns-vocab::before,
body.ns-coach button.ns-vocab::after { content: none; }
body.ns-coach button.ns-vocab:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { body.ns-coach button.ns-vocab { transition: none; } }
/* A line may break between a button and the punctuation touching it, so the two are held together. */
.ns-vocab-glue { white-space: nowrap; }
/* Above the session's citation panel and deck picker. */
.ns-vocab-scrim { z-index: 1300; }
.ns-vocab-definition { margin: 0; font-size: 16px; line-height: 1.6; color: var(--ns-text); overflow-wrap: anywhere; }

/* ---------- 32. Quick games and Today's "Got a few minutes?" ------------------
   docs/ui-revamp/screens/quick-games.md. The tiles are links (not .ns-btn) so step 9 keeps one
   button. Every game control is a <button class="ns-qg-b ...">; the legacy sheets style every
   bare button (fill, shadow, sheen, a lift on hover, full width on phones), so .ns-qg-b resets
   all of it under body.ns-coach .ns-qg, and each control then styles itself at that weight.
   Animations are one-shot classes restarted from JS (is-pop, is-right, is-wrong, is-in); all of
   them stop under prefers-reduced-motion, where the games still work without movement. */
.ns-quick { display: flex; flex-direction: column; gap: var(--ns-s-2); padding-top: var(--ns-s-2); border-top: 1px solid var(--ns-divider); }
.ns-quick__grid { margin: 0 0 var(--ns-s-2); padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--ns-s-2); }
body.ns-coach .ns-quick__item { display: flex; align-items: center; gap: var(--ns-s-3); min-height: 56px; height: 100%; box-sizing: border-box; padding: 10px var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); color: var(--ns-text); text-decoration: none; transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease; }
body.ns-coach .ns-quick__item:hover { border-color: var(--ns-primary); box-shadow: var(--ns-shadow-float); transform: translateY(-1px); }
body.ns-coach .ns-quick__item:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }
.ns-quick__icon { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: var(--ns-r-sm); background: var(--ns-primary-tint); color: var(--ns-primary-ink); }
.ns-quick__icon[data-game="rain"], .ns-quick__icon[data-game="missing-word"] { background: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-quick__icon[data-game="true-false"] { background: var(--ns-bad-bg); color: var(--ns-bad-ink); }
.ns-quick__text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; overflow-wrap: anywhere; }
.ns-quick__name { font-weight: 700; font-size: 15px; }
.ns-quick__text .ns-sub { font-size: 13px; }
.ns-quick__time { flex: none; align-self: flex-start; padding: 2px 8px; border-radius: 8px; background: var(--ns-surface); border: 1px solid var(--ns-border); font-size: 12px; font-weight: 700; color: var(--ns-text-2); }
@media (prefers-reduced-motion: reduce) { body.ns-coach .ns-quick__item { transition: none; } body.ns-coach .ns-quick__item:hover { transform: none; } }

/* The game page. */
.ns-qg__screen { display: flex; flex-direction: column; gap: var(--ns-s-4); position: relative; }
.ns-qg__hero { display: flex; align-items: center; gap: var(--ns-s-4); }
body.ns-coach .ns-qg__badge { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 64px; height: 64px; border-radius: var(--ns-r-xl); background: var(--ns-primary-tint); color: var(--ns-primary-ink); animation: ns-qg-wobble 2.4s ease-in-out infinite; }
.ns-qg__howto { margin: 0; padding-left: var(--ns-s-6); display: flex; flex-direction: column; gap: var(--ns-s-2); font-size: 16px; line-height: 1.5; }
.ns-qg__best { font-weight: 600; }
.ns-qg__hud { display: flex; gap: var(--ns-s-2); }
.ns-qg__stat { flex: 1 1 0; position: relative; display: flex; flex-direction: column; gap: 2px; padding: var(--ns-s-2) var(--ns-s-3); border-radius: var(--ns-r-md); background: var(--ns-surface); border: 1px solid var(--ns-border); min-width: 0; }
.ns-qg__value { font-family: var(--ns-font-display); font-size: 30px; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
body.ns-coach .ns-qg__hearts { display: flex; gap: 2px; min-height: 30px; align-items: center; color: var(--ns-state-review); }
.ns-qg__heart { display: inline-flex; transition: opacity 0.2s ease, transform 0.2s ease; }
.ns-qg__heart.is-lost { opacity: 0.2; transform: scale(0.7); }
.ns-qg__plus { position: absolute; right: var(--ns-s-3); top: var(--ns-s-2); font-weight: 800; font-size: 16px; color: var(--ns-ok-ink); pointer-events: none; animation: ns-qg-float 0.9s ease-out forwards; }
.ns-qg__plus.is-minus { color: var(--ns-bad-ink); }
.ns-qg__timer { height: 10px; border-radius: 5px; background: var(--ns-state-new); overflow: hidden; }
.ns-qg__timer-fill { height: 100%; width: 100%; border-radius: 5px; background: var(--ns-primary); transform-origin: left center; }
.ns-qg__timer.is-running .ns-qg__timer-fill { animation: ns-qg-drain var(--qg-duration, 90s) linear forwards; }
.ns-qg__timer.is-low .ns-qg__timer-fill { background: var(--ns-state-review); }
.ns-qg__arena { min-height: 320px; display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-qg__feedback { min-height: 1.6em; text-align: center; font-weight: 700; font-size: 16px; color: var(--ns-text-2); }
.ns-qg__feedback[data-tone="good"] { color: var(--ns-ok-ink); }
.ns-qg__feedback[data-tone="bad"] { color: var(--ns-bad-ink); }
.ns-qg__feedback[data-tone="streak"] { color: var(--ns-primary-ink); }
.ns-qg__feedback.is-new { animation: ns-qg-rise 0.3s ease-out; }
/* While a round runs it covers the whole screen, chrome included; the page behind stops scrolling. */
body.ns-qg-playing { overflow: hidden; }
.ns-qg__play:not([hidden]) { position: fixed; inset: 0; z-index: 1400; overflow-y: auto; overscroll-behavior: contain; box-sizing: border-box; padding: max(var(--ns-s-4), env(safe-area-inset-top)) var(--ns-s-4) max(var(--ns-s-4), env(safe-area-inset-bottom)); background: var(--ns-bg); }
.ns-qg__play > * { width: 100%; max-width: 860px; margin-left: auto; margin-right: auto; box-sizing: border-box; }
.ns-qg__play > .ns-qg__countdown { max-width: none; border-radius: 0; }
.ns-qg__top { display: flex; align-items: center; justify-content: space-between; gap: var(--ns-s-3); }
.ns-qg__name { display: flex; align-items: center; gap: var(--ns-s-2); min-width: 0; font-weight: 700; font-size: 16px; color: var(--ns-primary-ink); overflow-wrap: anywhere; }
.ns-qg__close { flex: none; }
.ns-qg__play .ns-qg-rain__field:not(.is-still) { height: max(280px, calc(100dvh - 380px)); }
.ns-qg__countdown { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center; justify-content: center; background: rgba(238, 241, 246, 0.9); border-radius: var(--ns-r-xl); font-family: var(--ns-font-display); font-size: 120px; color: var(--ns-primary-ink); }
.ns-qg__countdown.is-pop { animation: ns-qg-count 0.6s ease-out; }
.ns-qg__kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ns-s-3); }
.ns-qg__burst { position: absolute; left: 50%; top: 80px; width: 0; height: 0; pointer-events: none; z-index: 5; }
.ns-qg__bit { position: absolute; width: 10px; height: 14px; border-radius: 3px; background: var(--ns-primary); animation: ns-qg-burst 1.2s cubic-bezier(0.15, 0.7, 0.3, 1) forwards; }
.ns-qg__bit[data-tone="1"] { background: var(--ns-state-mastered); }
.ns-qg__bit[data-tone="2"] { background: var(--ns-state-progress); }
.ns-qg__bit[data-tone="3"] { background: var(--ns-warm); }
@media (max-width: 600px) {
  .ns-qg__stat { padding: 6px var(--ns-s-2); }
  .ns-qg__stat .ns-eyebrow { font-size: 11px; }
  .ns-qg__value { font-size: 24px; }
  .ns-qg__kpis { gap: var(--ns-s-2); }
  .ns-qg__kpis .ns-kpi { padding: var(--ns-s-3); }
  .ns-qg__kpis .ns-kpi__value { font-size: 22px; }
  .ns-qg__countdown { font-size: 88px; }
}

/* Game controls: one reset, then each control. */
body.ns-coach .ns-qg .ns-qg-b,
body.ns-coach .ns-qg .ns-qg-b:hover,
body.ns-coach .ns-qg .ns-qg-b:active { width: auto; min-width: 0; height: auto; min-height: var(--ns-hit); margin: 0; padding: 10px 14px; box-sizing: border-box; border: 2px solid var(--ns-border-strong); border-radius: var(--ns-r-md); background: var(--ns-surface); box-shadow: none; transform: none; backdrop-filter: none; overflow: visible; color: var(--ns-text); font: inherit; font-size: 15px; font-weight: 600; letter-spacing: normal; text-transform: none; text-align: center; line-height: 1.35; overflow-wrap: anywhere; cursor: pointer; transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.2s ease; }
body.ns-coach .ns-qg .ns-qg-b::before,
body.ns-coach .ns-qg .ns-qg-b::after { content: none; }
body.ns-coach .ns-qg .ns-qg-b:focus-visible { outline: 3px solid var(--ns-primary); outline-offset: 2px; }
body.ns-coach .ns-qg .ns-qg-b:hover:not([disabled]) { border-color: var(--ns-primary); }
body.ns-coach .ns-qg .ns-qg-b[disabled] { cursor: default; }
body.ns-coach .ns-qg .ns-qg-b[aria-pressed="true"] { border-color: var(--ns-primary); background: var(--ns-primary-tint); color: var(--ns-primary-ink); }
.ns-qg .is-right { animation: ns-qg-right 0.45s ease-out; }
.ns-qg .is-wrong { animation: ns-qg-shake 0.4s ease-in-out; }
.ns-qg .is-pop { animation: ns-qg-pop 0.3s ease-out; }
.ns-qg .is-in { animation: ns-qg-rise 0.35s ease-out; }

/* Match Up */
.ns-qg-match { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--ns-s-3); }
.ns-qg-match__col { display: flex; flex-direction: column; gap: var(--ns-s-2); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-tile { text-align: left; font-weight: 500; font-size: 14px; flex-grow: 1; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-tile--word { text-align: center; font-weight: 700; font-size: 16px; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-tile.is-done { border-color: var(--ns-state-mastered); background: var(--ns-ok-bg); color: var(--ns-ok-ink); opacity: 0.55; }
@media (max-width: 600px) { .ns-qg-match { grid-template-columns: minmax(0, 1fr); } .ns-qg-match__col--words { flex-direction: row; flex-wrap: wrap; } body.ns-coach .ns-qg .ns-qg-b.ns-qg-tile--word { flex: 1 1 40%; } }

/* Word Rain */
.ns-qg-rain__clue { padding: var(--ns-s-4); border-radius: var(--ns-r-lg); background: var(--ns-ink-panel); color: var(--ns-text-on-dark); display: flex; flex-direction: column; gap: 4px; }
.ns-qg-rain__clue .ns-eyebrow { color: #c9d4e6; }
.ns-qg-rain__meaning { margin: 0; font-size: 17px; line-height: 1.45; font-weight: 600; overflow-wrap: anywhere; }
.ns-qg-rain__field { position: relative; height: 340px; border-radius: var(--ns-r-lg); background: linear-gradient(180deg, var(--ns-primary-tint), var(--ns-surface)); border: 1px solid var(--ns-border); overflow: hidden; }
.ns-qg-rain__ground { position: absolute; left: 0; right: 0; bottom: 0; height: 8px; background: var(--ns-state-review); opacity: 0.5; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-drop { position: absolute; top: -64px; left: calc(100% / var(--qg-lanes, 4) * var(--qg-lane, 0) + 4px); width: calc(100% / var(--qg-lanes, 4) - 8px); padding: 8px 6px; font-size: 14px; font-weight: 700; box-shadow: var(--ns-shadow-float); animation: ns-qg-fall var(--qg-fall, 7000ms) linear var(--qg-delay, 0ms) forwards; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-drop[disabled] { opacity: 0.35; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-drop.is-caught { border-color: var(--ns-state-mastered); background: var(--ns-ok-bg); color: var(--ns-ok-ink); opacity: 1; animation-play-state: paused; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-drop.is-gone:not(.is-caught) { animation-play-state: paused; }
.ns-qg-rain__field.is-still { height: auto; min-height: 0; padding: var(--ns-s-3); display: grid; grid-template-columns: repeat(var(--qg-lanes, 4), minmax(0, 1fr)); gap: var(--ns-s-2); }
body.ns-coach .ns-qg .ns-qg-rain__field.is-still .ns-qg-b.ns-qg-drop { position: static; width: auto; animation: none; }
.ns-qg-rain__field.is-still .ns-qg-rain__ground { display: none; }
@media (max-width: 600px) { .ns-qg-rain__field { height: 300px; } .ns-qg__play .ns-qg-rain__field:not(.is-still) { height: max(260px, calc(100dvh - 360px)); } body.ns-coach .ns-qg .ns-qg-b.ns-qg-drop { font-size: 13px; } }

/* Sure or Not */
.ns-qg-tf { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-qg-tf__stage { display: flex; flex-direction: column; gap: var(--ns-s-3); min-height: 200px; }
.ns-qg-tf__card { padding: var(--ns-s-6); border-radius: var(--ns-r-xl); background: var(--ns-surface); border: 1px solid var(--ns-border); box-shadow: var(--ns-shadow-float); display: flex; flex-direction: column; gap: var(--ns-s-2); text-align: center; }
.ns-qg-tf__card.is-out-left { animation: ns-qg-out-left 0.35s ease-in forwards; }
.ns-qg-tf__card.is-out-right { animation: ns-qg-out-right 0.35s ease-in forwards; }
.ns-qg-tf__term { font-size: 26px; font-weight: 800; overflow-wrap: anywhere; }
.ns-qg-tf__def { margin: 0; font-size: 17px; line-height: 1.5; overflow-wrap: anywhere; }
.ns-qg-tf__fix { padding: var(--ns-s-4); border-radius: var(--ns-r-lg); border: 1px solid var(--ns-state-review); background: var(--ns-bad-bg); display: flex; flex-direction: column; gap: var(--ns-s-2); animation: ns-qg-rise 0.3s ease-out; }
.ns-qg-tf__fix .ns-eyebrow { color: var(--ns-bad-ink); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-next { align-self: flex-start; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-bet { align-self: center; border-style: dashed; border-radius: 22px; }
.ns-qg-tf__answers { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ns-s-3); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-answer { min-height: 56px; font-size: 18px; font-weight: 800; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-answer--false { border-color: var(--ns-state-review); color: var(--ns-bad-ink); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-answer--true { border-color: var(--ns-state-mastered); color: var(--ns-ok-ink); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-answer[disabled] { opacity: 0.5; }

/* Concept Sort */
.ns-qg-sort { display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-qg-sort__drop { min-height: 150px; display: flex; align-items: center; justify-content: center; }
.ns-qg-sort__card { width: 100%; max-width: 520px; padding: var(--ns-s-5); border-radius: var(--ns-r-xl); background: var(--ns-surface); border: 1px solid var(--ns-border); box-shadow: var(--ns-shadow-float); display: flex; flex-direction: column; gap: var(--ns-s-2); text-align: center; }
.ns-qg-sort__card.is-in { animation: ns-qg-drop-in 0.4s cubic-bezier(0.2, 0.9, 0.3, 1.2); }
.ns-qg-sort__card.is-to-left { animation: ns-qg-to-left 0.38s ease-in forwards; }
.ns-qg-sort__card.is-to-right { animation: ns-qg-to-right 0.38s ease-in forwards; }
.ns-qg-sort__text { margin: 0; font-size: 18px; font-weight: 600; line-height: 1.45; overflow-wrap: anywhere; }
.ns-qg-sort__bins { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ns-s-3); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-bin { min-height: 88px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; border-style: dashed; border-color: var(--ns-border-dashed); background: var(--ns-surface-soft); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-bin.is-hint { animation: ns-qg-hint 0.9s ease-in-out; }
.ns-qg-bin__title { font-weight: 700; font-size: 16px; }
.ns-qg-bin__count { min-width: 28px; padding: 2px 8px; border-radius: 12px; background: var(--ns-ok-bg); color: var(--ns-ok-ink); font-size: 13px; font-weight: 800; }

/* Missing Word */
.ns-qg-gap { display: flex; flex-direction: column; gap: var(--ns-s-4); }
.ns-qg-gap__sentence { margin: 0; padding: var(--ns-s-5); border-radius: var(--ns-r-xl); background: var(--ns-surface); border: 1px solid var(--ns-border); font-size: 18px; line-height: 1.7; overflow-wrap: anywhere; }
.ns-qg-gap__blank { display: inline-block; min-width: 3em; padding: 0 8px; border-bottom: 3px solid var(--ns-primary); color: var(--ns-primary-ink); font-weight: 800; text-align: center; }
.ns-qg-gap__blank.is-filled { border-bottom-color: var(--ns-state-mastered); background: var(--ns-ok-bg); color: var(--ns-ok-ink); border-radius: 6px 6px 0 0; animation: ns-qg-pop 0.35s ease-out; }
.ns-qg-gap__slots { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.ns-qg-gap__space { width: 14px; }
.ns-qg-gap__fixed { display: inline-flex; align-items: center; font-size: 22px; font-weight: 800; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-slot { width: 44px; min-height: 52px; padding: 0; font-size: 22px; font-weight: 800; border-style: dashed; background: var(--ns-surface-soft); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-slot.is-filled { border-style: solid; border-color: var(--ns-primary); background: var(--ns-surface); color: var(--ns-primary-ink); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-slot.is-hinted { border-color: var(--ns-state-progress); background: #fbf1dc; }
.ns-qg-gap__tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--ns-s-2); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-letter { width: 48px; min-height: 48px; padding: 0; font-size: 20px; font-weight: 800; border-color: var(--ns-primary); background: var(--ns-primary-tint); color: var(--ns-primary-ink); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-letter[disabled] { opacity: 0.2; }
.ns-qg-gap__tools { justify-content: center; }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-tool { border-color: transparent; background: transparent; color: var(--ns-primary-ink); }
.ns-qg-gap__choices { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ns-s-2); }
body.ns-coach .ns-qg .ns-qg-b.ns-qg-choice[disabled] { opacity: 0.35; }
@media (max-width: 600px) { .ns-qg-gap__choices { grid-template-columns: minmax(0, 1fr); } .ns-qg-gap__sentence { font-size: 16px; padding: var(--ns-s-4); } }

@keyframes ns-qg-drain { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes ns-qg-fall { to { top: calc(100% - 8px); } }
@keyframes ns-qg-pop { 0% { transform: scale(1); } 45% { transform: scale(1.25); } 100% { transform: scale(1); } }
@keyframes ns-qg-count { 0% { transform: scale(0.4); opacity: 0; } 40% { transform: scale(1.15); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes ns-qg-right { 0% { transform: scale(1); } 40% { transform: scale(1.06); box-shadow: 0 0 0 6px var(--ns-ok-bg); } 100% { transform: scale(1); } }
@keyframes ns-qg-shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(5px); } }
@keyframes ns-qg-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes ns-qg-float { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-28px); } }
@keyframes ns-qg-out-left { to { opacity: 0; transform: translateX(-60%) rotate(-8deg); } }
@keyframes ns-qg-out-right { to { opacity: 0; transform: translateX(60%) rotate(8deg); } }
@keyframes ns-qg-drop-in { from { opacity: 0; transform: translateY(-40px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes ns-qg-to-left { to { opacity: 0; transform: translate(-40%, 120px) scale(0.5); } }
@keyframes ns-qg-to-right { to { opacity: 0; transform: translate(40%, 120px) scale(0.5); } }
@keyframes ns-qg-hint { 0%, 100% { background: var(--ns-surface-soft); } 50% { background: var(--ns-ok-bg); border-color: var(--ns-state-mastered); } }
@keyframes ns-qg-burst { from { opacity: 1; transform: translate(0, 0) rotate(0); } to { opacity: 0; transform: translate(var(--qg-x), var(--qg-y)) rotate(var(--qg-r)); } }
@keyframes ns-qg-wobble { 0%, 100% { transform: rotate(0); } 50% { transform: rotate(-6deg) scale(1.04); } }
@media (prefers-reduced-motion: reduce) {
  .ns-qg__badge, .ns-qg .is-right, .ns-qg .is-wrong, .ns-qg .is-pop, .ns-qg .is-in, .ns-qg__feedback.is-new, .ns-qg__countdown.is-pop, .ns-qg__plus,
  .ns-qg-tf__card.is-out-left, .ns-qg-tf__card.is-out-right, .ns-qg-sort__card.is-in, .ns-qg-sort__card.is-to-left, .ns-qg-sort__card.is-to-right,
  .ns-qg-tf__fix, .ns-qg-gap__blank.is-filled, body.ns-coach .ns-qg .ns-qg-b.ns-qg-bin.is-hint { animation: none; }
  .ns-qg__plus { display: none; }
  .ns-qg__timer.is-running .ns-qg__timer-fill { animation-timing-function: steps(20); }
  body.ns-coach .ns-qg .ns-qg-b, .ns-qg__heart { transition: none; }
}

/* ---------- 33. Session player: focus block timer and answer verdict ----------
   The timer sits beside the chapter title in the focus bar once a focus block starts;
   tapping it opens the focus controls (Break now, Exit focus).
   The verdict is the first thing in the answer card after Submit. A correct answer gets a
   short reward at the verdict itself, not somewhere else on screen: the check draws, the
   ring pops, sparks fly out. It is graded by surprise -- bigger when the learner was unsure
   or had just missed -- and never holds up Continue. Motion and sparks drop out under
   reduced motion, low stimulation and Low celebration intensity (data-reward="0"). */
.ns-focustimer { flex: none; display: inline-flex; flex-direction: column; align-items: center; justify-content: center; min-height: var(--ns-hit); min-width: var(--ns-hit); padding: 2px var(--ns-s-3); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border-strong); background: var(--ns-surface); color: var(--ns-text); font: inherit; line-height: 1.1; cursor: pointer; }
/* The legacy global button skin (gradient, glow, full width on phones) must not reach it. */
body.ns-coach .ns-focustimer { width: auto; margin: 0; background: var(--ns-surface); color: var(--ns-text); box-shadow: none; overflow: visible; backdrop-filter: none; transform: none; }
body.ns-coach .ns-focustimer::before { content: none; }
body.ns-coach .ns-focustimer:hover, .ns-focustimer:focus-visible { border-color: var(--ns-ink-panel); box-shadow: none; transform: none; }
/* The timer takes its room from the title (clamped to two lines), not from the step pills. */
.ns-focusbar:has(.ns-focustimer) .ns-focusbar__title { min-width: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; line-height: 1.3; }
.ns-focusbar:has(.ns-focustimer) .ns-steps__step { white-space: nowrap; }
.ns-focustimer__time { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ns-focustimer__label { font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ns-text-2); }
.ns-focusdlg__time { font-size: 15px; color: var(--ns-text-2); }
.ns-focusdlg__time span { font-size: 32px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ns-text); }
.ns-focusdlg__fill { width: 0; transition: width 1s linear; }
.ns-focusdlg__actions { display: flex; flex-wrap: wrap; gap: var(--ns-s-3); }
@media (max-width: 600px) { .ns-focusdlg__actions .ns-btn { flex: 1 1 100%; } }

.ns-verdict { scroll-margin-top: calc(var(--ns-header-h) + var(--ns-s-4)); margin-top: var(--ns-s-4); padding: var(--ns-s-4) var(--ns-s-5); border-radius: var(--ns-r-lg); border: 1px solid var(--ns-border); background: var(--ns-surface-soft); display: flex; flex-direction: column; gap: var(--ns-s-3); line-height: 1.55; }
.ns-verdict[data-tone="ok"] { border-color: var(--ns-state-mastered); background: var(--ns-ok-bg); }
.ns-verdict[data-tone="miss"] { border-color: var(--ns-state-review); background: var(--ns-bad-bg); }
.ns-verdict__head { display: flex; align-items: center; gap: var(--ns-s-4); }
.ns-verdict__mark { position: relative; flex: none; width: 48px; height: 48px; }
.ns-verdict__mark svg { display: block; width: 48px; height: 48px; overflow: visible; }
.ns-verdict__ring { fill: var(--ns-surface); stroke: currentColor; stroke-width: 2.5; }
.ns-verdict__glyph { fill: none; stroke: currentColor; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
.ns-verdict[data-tone="ok"] .ns-verdict__mark { color: var(--ns-ok-ink); }
.ns-verdict[data-tone="miss"] .ns-verdict__mark { color: var(--ns-bad-ink); }
.ns-verdict[data-tone="held"] .ns-verdict__mark { color: var(--ns-text-2); }
.ns-verdict__titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ns-verdict__title { font-size: 22px; font-weight: 700; line-height: 1.2; }
.ns-verdict[data-tone="ok"] .ns-verdict__title { color: var(--ns-ok-ink); }
.ns-verdict[data-tone="miss"] .ns-verdict__title { color: var(--ns-bad-ink); }
.ns-verdict__meta { font-size: 13px; font-weight: 600; color: var(--ns-text-2); }
.ns-verdict__cheer { font-size: 14px; font-weight: 700; color: var(--ns-ok-ink); }
.ns-verdict__body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.ns-verdict__answer { padding: var(--ns-s-3) var(--ns-s-4); border-radius: var(--ns-r-md); border: 1px solid var(--ns-border); background: var(--ns-surface); overflow-wrap: anywhere; }
.ns-verdict__answer strong { display: block; }
.ns-verdict__tags { display: flex; flex-wrap: wrap; gap: var(--ns-s-2); }
.ns-verdict-actions { margin-top: var(--ns-s-4); padding-bottom: var(--ns-s-5); margin-bottom: var(--ns-s-5); border-bottom: 1px solid var(--ns-divider); }

/* Reward: ~0.8s end to end. The check strokes in (pathLength="1"), the mark overshoots and
   settles, and the sparks travel out and fade. data-reward 1 = expected correct, 2 = unsure
   or just missed, 3 = streak milestone; each step adds sparks and distance. */
.ns-verdict[data-reward] .ns-verdict__ring { animation: ns-verdict-fade 0.15s ease-out both; }
.ns-verdict[data-reward] .ns-verdict__glyph { stroke-dasharray: 1; animation: ns-onb-draw 0.3s ease-out 0.1s both; }
.ns-verdict[data-reward="1"] .ns-verdict__mark, .ns-verdict[data-reward="2"] .ns-verdict__mark, .ns-verdict[data-reward="3"] .ns-verdict__mark { animation: ns-verdict-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both; }
.ns-verdict[data-reward="2"] .ns-verdict__mark { --ns-pop: 1.22; }
.ns-verdict[data-reward="3"] .ns-verdict__mark { --ns-pop: 1.3; }
.ns-verdict[data-reward="1"] .ns-verdict__title, .ns-verdict[data-reward="2"] .ns-verdict__title, .ns-verdict[data-reward="3"] .ns-verdict__title { animation: ns-verdict-rise 0.3s ease-out 0.15s both; }
.ns-verdict__burst { position: absolute; left: 50%; top: 50%; width: 0; height: 0; pointer-events: none; }
.ns-verdict__burst i { position: absolute; left: -4px; top: -4px; width: 8px; height: 8px; border-radius: 50%; background: var(--ns-state-mastered); opacity: 0; transform: rotate(var(--ns-a)) translateY(0) scale(1); animation: ns-verdict-spark 0.6s cubic-bezier(0.2, 0.7, 0.3, 1) 0.2s both; }
.ns-verdict__burst i:nth-child(3n+2) { background: var(--ns-warm); }
.ns-verdict__burst i:nth-child(3n) { background: var(--ns-primary); width: 6px; height: 6px; }
.ns-verdict[data-reward="2"] .ns-verdict__burst i { --ns-d: -46px; }
.ns-verdict[data-reward="3"] .ns-verdict__burst i { --ns-d: -56px; animation-duration: 0.75s; }
/* Evenly spread for any count: each prefix of this order fills the gaps the last one left. */
.ns-verdict__burst i:nth-child(1) { --ns-a: 0deg; }      .ns-verdict__burst i:nth-child(2) { --ns-a: 180deg; }
.ns-verdict__burst i:nth-child(3) { --ns-a: 60deg; }     .ns-verdict__burst i:nth-child(4) { --ns-a: 240deg; }
.ns-verdict__burst i:nth-child(5) { --ns-a: 120deg; }    .ns-verdict__burst i:nth-child(6) { --ns-a: 300deg; }
.ns-verdict__burst i:nth-child(7) { --ns-a: 30deg; }     .ns-verdict__burst i:nth-child(8) { --ns-a: 210deg; }
.ns-verdict__burst i:nth-child(9) { --ns-a: 150deg; }    .ns-verdict__burst i:nth-child(10) { --ns-a: 330deg; }
.ns-verdict__burst i:nth-child(11) { --ns-a: 90deg; }    .ns-verdict__burst i:nth-child(12) { --ns-a: 270deg; }
.ns-verdict__burst i:nth-child(13) { --ns-a: 15deg; }    .ns-verdict__burst i:nth-child(14) { --ns-a: 195deg; }
.ns-verdict__burst i:nth-child(15) { --ns-a: 105deg; }   .ns-verdict__burst i:nth-child(16) { --ns-a: 285deg; }
@keyframes ns-verdict-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ns-verdict-pop { 0% { transform: scale(0.6); } 55% { transform: scale(var(--ns-pop, 1.15)); } 100% { transform: scale(1); } }
@keyframes ns-verdict-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes ns-verdict-spark { 0% { opacity: 0; transform: rotate(var(--ns-a)) translateY(-24px) scale(1); } 20% { opacity: 1; } 100% { opacity: 0; transform: rotate(var(--ns-a)) translateY(var(--ns-d, -38px)) scale(0.3); } }
.ns-verdict[data-motion="reduced"] .ns-verdict__mark, .ns-verdict[data-motion="reduced"] .ns-verdict__title, .ns-verdict[data-motion="reduced"] .ns-verdict__glyph, .ns-verdict[data-motion="reduced"] .ns-verdict__ring { animation: none; stroke-dasharray: none; }
.ns-verdict[data-motion="reduced"] .ns-verdict__burst { display: none; }
@media (prefers-reduced-motion: reduce) {
  .ns-verdict .ns-verdict__mark, .ns-verdict .ns-verdict__title, .ns-verdict .ns-verdict__glyph, .ns-verdict .ns-verdict__ring { animation: none; stroke-dasharray: none; }
  .ns-verdict__burst { display: none; }
  .ns-focusdlg__fill { transition: none; }
}
/* Below 1200px one row cannot hold Exit, title, timer, steps and actions (the title used to
   collapse to nothing), so the timed focus bar wraps: Exit, title, timer and actions on the
   first row, the steps on the second. At phone width the actions move down beside the steps. */
@media (max-width: 1200px) {
  .ns-focusbar:has(.ns-focustimer) { height: auto; min-height: var(--ns-header-h); flex-wrap: wrap; row-gap: 0; padding-top: var(--ns-s-2); padding-bottom: var(--ns-s-2); }
  .ns-focusbar:has(.ns-focustimer)::after { content: ""; order: 2; flex-basis: 100%; height: var(--ns-s-2); }
  .ns-focusbar:has(.ns-focustimer) .ns-focusbar__title { flex: 1 1 0; }
  .ns-focusbar:has(.ns-focustimer) .ns-focusbar__actions { order: 1; }
  .ns-focusbar:has(.ns-focustimer) .ns-steps { order: 3; margin: 0; }
  .ns-verdict { scroll-margin-top: 136px; }
}
@media (max-width: 600px) {
  .ns-focusbar:has(.ns-focustimer) .ns-focusbar__actions { order: 4; }
  .ns-focusbar:has(.ns-focustimer) .ns-focusbar__title { white-space: normal; }
  .ns-focustimer { padding: 2px var(--ns-s-2); }
}
/* Downloads (/downloads, templates/downloads.html): chapters kept on this device for offline
   reading and listening. The list and reader are filled by static/js/offline-downloads.js. */
.ns-downloads__storage { justify-content: space-between; align-items: center; }
.ns-downloads__list { display: flex; flex-direction: column; gap: var(--ns-s-3); }
.ns-downloads__reader-title { margin: 0; font-size: 22px; line-height: 1.3; overflow-wrap: anywhere; }
.ns-downloads__audio { width: 100%; }
.ns-downloads__prose p { margin: 0 0 var(--ns-s-4); line-height: 1.65; overflow-wrap: anywhere; }
.ns-downloads__aside { display: flex; flex-direction: column; gap: var(--ns-s-3); border-top: 1px solid var(--ns-border); padding-top: var(--ns-s-4); }
.ns-downloads__aside ul { margin: 0; padding-left: var(--ns-s-5); line-height: 1.6; }
/* The chapter card's download button says which state it is in with its label; the tint only
   echoes it. */
.ns-btn[data-offline-state="downloaded"] { background: var(--ns-ok-bg); border-color: var(--ns-ok-bg); color: var(--ns-ok-ink); }
.ns-btn[data-offline-state="failed"] { background: var(--ns-bad-bg); border-color: var(--ns-bad-bg); color: var(--ns-bad-ink); }
.ns-btn[data-offline-state="working"] { cursor: progress; }
