/* ============================================================================
   /APP DASHBOARD — the V2 ("path composer v2") aesthetic, the design system for
   the WHOLE /app. It inherits platform.css's V2 tokens directly: the FLAT coral
   family (#DA7756 / #B8553A / #a8472a / #E8A488, zero gradients), white cards on
   the COOL near-white page (#fff on #f6f8fb), the cool-slate ink ramp, cool
   hairlines, Plus Jakarta Sans (headings + UI) + JetBrains Mono (eyebrows / ids),
   the shared --shadow-1/2/3 + the Emil --ease-out / --ease-move curves, and WCAG
   2.2 AA. State is encoded as DEPTH OF ONE CORAL (never a 2nd hue); no warm
   cream / beige anywhere, no gradients, no gamification theatre, no emoji, no
   em dashes.

   The local "w-" (surface) and "c-" (coral) custom-property NAMES are KEPT as a
   thin compatibility layer — every rule below reads them — but they now ALIAS
   the V2 platform tokens, so the whole surface is the cool V2 look in one place.
   The winding-ladder journey (SVG vine + numbered circles) is REPLACED below by
   a clean V2 journey VIEW (a tidy vertical path of module rows, grouped under
   their section separators).

   Scope: this file styles ONLY the /app dashboard surface; it loads after
   platform.css and the auth pages are untouched.
   ============================================================================ */

/* ============================================================================
   SKIN TOKEN CONTRACT  (the macro-THEME / data-skin axis — added 2026-05-31)
   ----------------------------------------------------------------------------
   A SKIN is a complete look applied via html[data-skin="miami|retro|minimal|
   editorial"] (Default = no attribute / no file). Skin CSS files load AFTER this
   file (skin-miami.css / skin-retro.css / skin-minimal.css / skin-editorial.css)
   and override the TOKENS below + hook the STRUCTURAL selectors below. A skin is
   ORTHOGONAL to the existing tone (data-theme) / style (data-style) / font
   (data-font) / accent axes — it sets sensible DEFAULTS for those (in theme.js's
   SKINS catalog) but composes with them; the user can still tune each knob.

   Authoring rule: scope EVERY rule under html[data-skin="X"] (and, when you need a
   tone-specific tweak, html[data-skin="X"][data-theme="dark"] etc.). Re-declare
   the tokens on html[data-skin="X"] so they cascade to the whole /app. Keep AA
   (text ≥4.5:1, UI ≥3:1) in every skin × tone combination. No emoji, no em dashes.

   ── THE TOKENS YOU OVERRIDE (name → Default value → what it controls) ──────────
   COLOR — surfaces (defined in platform.css :root + each data-theme bundle; the
   dashboard aliases them as --w-*):
     --bg            #ffffff   card surface           (alias --w-card)
     --bg-2          #f6f8fb   page ground            (alias --w-page; see --page-bg)
     --bg-3          #eef1f6   recessed fill (tabs/pills/locked)  (alias --w-locked)
     --card-2        #fbfcfe   faint alt card surface (alias --w-card-2)
     --border        #e7ebf0   hairline               (alias --w-line)
     --border-strong #dfe3ea   stronger hairline      (alias --w-line-2)
     --cover-1/2/3   #2f3850/#232a3a/#1a2030  dark cover/tile fills (module covers)
   COLOR — ink ramp:
     --ink           #1a1f2e   primary text/heading   (alias --w-ink)
     --ink-2         #404a5c   secondary text         (alias --w-ink-2)
     --ink-3         #5b6678   tertiary/meta text     (alias --w-ink-3)
     --w-ink-4       #646d82   faintest AA mono/meta  (dashboard-local; darker than
                               platform --ink-4 #8a93a6 for AA on near-white)
   COLOR — the ACCENT family (one claim-bearing hue; the coral family aliases to it):
     --accent        #DA7756   bars / borders / non-text accents   (alias --c-coral)
     --accent-deep   #B8553A   button fill (AA behind white label) (alias --c-deep)
     --accent-text   #a8472a   small accent TEXT on surface (AA)   (alias --c-text)
     --accent-soft   #E8A488   soft accent on dark covers
     --coral-tint    #fcefe9   faint accent fill (chips/banners)   (alias --c-tint)
     --coral-tint2   #f8e2d8   deeper accent fill                  (alias --c-tint2)
     --coral-line    rgba(218,119,86,.26)  accent hairline          (alias --c-line)
     --coral-wash    rgba(218,119,86,.07)  hover/drag bed           (alias --c-wash)
     NOTE: the accent is also set INLINE on <html> by theme.js (per tone, for AA).
     Inline wins the cascade, so to force a skin's signature accent regardless of the
     accent picker, give that skin a DEFAULT accent in theme.js's SKINS catalog
     (preferred) rather than fighting the inline style. Overriding --coral-tint etc.
     in the skin file is fine (those are not set inline).
   SHAPE / DENSITY (defined in platform.css :root + each data-style bundle):
     --radius-xs/-sm/(-)/-lg/-xl  7/10/14/18/22px   corner ramp (pill stays 999px)
     --pad-card / -sm / -lg       18/15/22px         card inner padding (density)
     --gap-card                   12px               inter-card grid gap
     --border-weight              1px                component border weight
   ELEVATION:
     --shadow-1/2/3   layered cool shadows           card / lifted / modal depth
     --shadow-coral   coral-tinted shadow            primary-button glow
     --card-shadow    = var(--w-shadow)=--shadow-1   the base .card elevation (SKIN HOOK)
   TYPE:
     --font           Plus Jakarta Sans stack        body + UI font (data-font swaps it)
     --font-mono      JetBrains Mono stack            eyebrows / ids / tabular nums
     --font-display   = var(--font)                   HEADINGS only (SKIN HOOK — set a
                                                      signature display face here)
   SKIN-ONLY HOOKS (added so skins have a clean single override point; Default routes
   its current value through, so Default is visually unchanged):
     --page-bg        = var(--w-page)                 the whole-page background layer
                                                      (body + .app-shell). Put a gradient
                                                      / image here. Keep ink AA over it.
     --card-shadow    = var(--w-shadow)               base .card elevation (flatten/glow)
     --font-display   = var(--font)                   heading face (see TYPE above)

   ── THE STRUCTURAL SELECTORS YOU CAN HOOK (for flourishes beyond tokens) ───────
   Shell / nav:    .app-shell · .app-sidebar · .side-link / .side-link.current /
                   .side-exit · .app-main · .app-topbar
   Cards:          .card · .card-eyebrow · .hero-card (+ .hero-card::before coral rail)
   Home grid:      .learn-grid (the dashboard card column) · .dash-head / h1 / .dash-eyebrow
   Journey/modules ladder:  .journey (the vertical path) + .journey::before (spine) ·
                   .journey-sep (a SECTION grouping — NO number; reads "Section: {name}"
                   via .jsep-label > .jsep-eyebrow + .jsep-name) · .journey-divider /
                   .jd-name / .jd-count · .jrow (module row) · .jcover (number/cover
                   tile) · .jbody / .jmain / .jtitle / .jmeta · .jbar (progress) /
                   .jpct · .jstate · .jgo (chevron)
   Dashboard-view tabs:  .dv-bar · .dv-tabs / .dv-tab / .dv-tab[aria-selected] ·
                   .dv-pick / .dv-pick-trigger / .dv-pick-menu · .dv-sec-head / .dv-sec-h
   Pills / chips:  .jel (element pill) · .id-role (role chip) · .ord-status ·
                   .banner-ok / .banner-note · .dv-tab (filter pills)
   Buttons:        .btn-coral (primary) · .btn-ghost-coral (secondary) · .pbar (progress)
   Account pill:   .cc-acct (styled in account-menu.js via --acct-* tokens in
                   platform.css; to re-skin it, override --acct-surface / --acct-ink /
                   --acct-ink-2 / --acct-ink-3 / --acct-border / --acct-tint).
   Settings Appearance picker (theme.js):  .ap-tile / .ap-style / .ap-font / .ap-acc /
                   .ap-preview + the new .sk-tab / .sk-mini skin tabs (see theme.js).

   The canonical, maintained copy of this contract lives in
   _orchestration/MACRO-THEME-SKINS-2026-05-31.md (§ TOKEN CONTRACT). Keep them in sync.
   ============================================================================ */

:root {
  /* Page / cards / lines — the V2 cool surfaces (white cards on cool near-white). */
  --w-page: var(--bg-2);          /* #f6f8fb — the V2 page ground */
  --w-card: var(--bg);            /* #ffffff — the V2 card surface */
  --w-card-2: var(--card-2);      /* #fbfcfe — faint cool card alt */
  --w-line: var(--border);        /* #e7ebf0 — cool hairline */
  --w-line-2: var(--border-strong); /* #dfe3ea */
  --w-locked: var(--bg-3);        /* #eef1f6 — a quiet cool recessed fill for locked/planned */
  --w-lock-border: var(--border-strong);
  /* the one coral, straight from the V2 family (FLAT accents only) */
  --c-coral: var(--coral);        /* #DA7756 */
  --c-deep: var(--coral-deep);    /* #B8553A — primary button fill (AA) */
  --c-text: var(--coral-text);    /* #a8472a — secondary text + border (AA) */
  --c-tint: var(--coral-tint);    /* #fcefe9 — the V2 faint cool-leaning coral fill */
  --c-tint2: var(--coral-tint2);  /* #f8e2d8 — a touch deeper, still flat */
  --c-line: var(--coral-line);    /* the flat coral hairline */
  --c-wash: var(--coral-wash);    /* the faint coral wash for drag/hover beds */
  /* heatmap 4-step single-hue coral ramp (sequential metric encoding), cool base. */
  --hm-0: var(--bg-3); --hm-1: #EBC3B0; --hm-2: #DA7756; --hm-3: #B8553A;
  /* ink — the V2 cool-slate scale, so headings + body match the system */
  --w-ink: var(--ink);            /* #1a1f2e */
  --w-ink-2: var(--ink-2);        /* #404a5c */
  --w-ink-3: var(--ink-3);        /* #5b6678 */
  /* A11y (WCAG 2.2 AA): the platform --ink-4 (#8a93a6) is only ~2.9–3.1:1 on the white
     card / cool page, which FAILS AA for the small mono micro-labels that use it (the
     "Working toward" / "Enrolled courses" switcher eyebrows, momentum eyebrows, journey
     separator counts). DARKEN the dashboard's faintest-ink token to #646d82 — still the
     same cool-slate hue, just deep enough to clear 4.5:1 on #fff (5.18:1), the page
     #f6f8fb (4.87:1), AND the recessed #eef1f6 fill (4.58:1). Scoped to the /app surface
     only (dashboard.css loads after platform.css); the auth pages keep platform's --ink-4.
     Decorative uses (icon strokes, locked covers) are unaffected by the slightly deeper ink. */
  --w-ink-4: #646d82;             /* was var(--ink-4) #8a93a6 — darkened for AA on near-white */
  --w-shadow: var(--shadow-1);
  --w-shadow-lift: var(--shadow-2);

  /* ── SKIN HOOKS (added 2026-05-31 for the macro-THEME / data-skin axis) ───────
     Three clean hooks a SKIN can override without restating dozens of rules. Each
     routes Default's CURRENT value through, so Default is byte-for-byte unchanged
     (no visual diff) — they exist only to give skin authors a single override point.
     • --page-bg     the WHOLE-PAGE background layer (the `background` shorthand on
                     body/.app-shell). Default = the flat cool page ground. A skin can
                     set a gradient / image here (Miami sunset, Retro warm wash) in ONE
                     place. Keep AA: ink must stay ≥4.5:1 over whatever you set.
     • --card-shadow the elevation on the base .card (was a literal var(--w-shadow)).
                     A skin can flatten it (Minimal/Editorial → none) or glow it (Miami)
                     without touching the style-axis --shadow-* ramp.
     • --font-display the HEADINGS / display type. Default = the body --font (Plus
                     Jakarta), so no change. A skin can give headings a signature face
                     (Miami geometric, Retro slab/mono) while body text keeps --font.
                     The dashboard heading rules read var(--font-display) (which falls
                     back to --font), so a skin sets ONE token to re-face every heading. */
  --page-bg: var(--w-page);
  --card-shadow: var(--w-shadow);
  --font-display: var(--font);
}

/* TRUE NEUTRAL dark tones — the dashboard-local --w-ink-4 above is a fixed cool
   blue-gray (#646d82) tuned for AA on the near-WHITE light page; it does NOT follow
   platform.css's per-tone --ink-4. On the Dark / Midnight tones that cool faint ink
   would read navy on a neutral-black page, so re-point it to a NEUTRAL gray that
   clears AA on the dark surfaces (Felipe: night/gray/black, never blue/navy). */
html[data-theme="dark"]     { --w-ink-4: #8a8a8a; --coral-text: #e98a67; }  /* neutral faint ink — AA (4.9:1) on #121212. Themes-QA: relighten ONLY the small-coral TEXT token (--c-text) so role-chip / coral links / the price hint stay AA on dark surfaces (the dark-mode coral accent). --coral-deep stays #B8553A — it's a button FILL with white text, which must NOT relighten. */
html[data-theme="midnight"] { --w-ink-4: #8c8c8c; --coral-text: #ef9a78; }  /* neutral faint ink — AA (5.6:1) on #0a0a0a; matching relighten of the coral text token */

/* Match the signed-in shell to the landing: white cards on the cool-gray page.
   The page background reads --page-bg (Default = the flat cool ground; a skin can
   paint a gradient/image here in one place — see the SKIN HOOKS block above). */
body { background: var(--page-bg); }
.app-shell { background: var(--page-bg); }
.app-sidebar { background: var(--w-card); border-right: 1px solid var(--w-line); }
.app-main { color: var(--w-ink); }
.side-link { color: var(--w-ink-2); }
.side-link:hover { background: var(--w-page); color: var(--w-ink); }
.side-link.current { background: var(--c-tint); color: var(--c-text); }
.side-exit:hover { color: var(--c-text); }
@media (max-width: 760px) {
  .app-sidebar { background: color-mix(in srgb, var(--w-card) 90%, transparent); border-bottom: 1px solid var(--w-line); }
}

/* The dashboard content column: 1120px max, comfortable rhythm. */
.app-main { max-width: 1120px; }

/* ── shared heading blocks (Plus Jakarta display + sans lead) ── */
.dash-head { margin: 0 0 22px; }
.dash-head h1 {
  font-family: var(--font-display); font-size: 30px; font-weight: 800;
  letter-spacing: -0.03em; color: var(--w-ink); line-height: 1.12;
}
.dash-head.learn-head h1 { font-size: 30px; }
.dash-head > p { font-size: 15px; color: var(--w-ink-2); margin-top: 8px; max-width: 64ch; line-height: 1.55; }
.dash-eyebrow {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--c-text); margin-bottom: 10px;
}
/* FIX 4 (2026-05-31) — the registrar eyebrow above "Welcome back" (a long display_name can run 4–6 lines).
   Clamp it to at most 2 lines with an ellipsis, matching how the switcher pill truncates — keeps the long
   "WORKING TOWARD MKTG 4333 · CRN … · Sec 001 · Institution" line readable without wrapping into a wall.
   `overflow-wrap: anywhere` lets a long unbroken token still wrap before the clamp cuts it. */
.dash-head.learn-head .dash-eyebrow {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere; line-height: 1.35; max-width: 64ch;
}
.app-loading { color: var(--w-ink-3); font-size: 14px; padding: 28px 4px; }

/* ── the base card (V2: cool white, cool hairline, refined shadow, soft radius).
   Radius + padding + border weight all follow the active STYLE (data-style). ── */
.card {
  background: var(--w-card); border: var(--border-weight) solid var(--w-line); border-radius: var(--radius-lg);
  padding: var(--pad-card); box-shadow: var(--card-shadow);
}
.card-eyebrow {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--c-text); margin-bottom: 10px;
}
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* primary / secondary buttons (V2: flat coral fill + coral shadow, tight tracking) */
.btn-coral, .btn-ghost-coral {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font); font-weight: 700; font-size: 14px; cursor: pointer;
  border-radius: var(--radius-sm); padding: 10px 17px; border: 1px solid transparent;
  letter-spacing: -0.01em; line-height: 1; min-height: 40px;
  transition: background 150ms var(--ease-out), border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out), transform 120ms var(--ease-out);
  text-decoration: none;
}
.btn-coral:active, .btn-ghost-coral:active { transform: scale(0.98); }
@media (prefers-reduced-motion: reduce) { .btn-coral:active, .btn-ghost-coral:active { transform: none; } }
.btn-coral { background: var(--c-deep); color: #fff; border-color: var(--c-deep); box-shadow: var(--shadow-coral); }
.btn-coral:hover { background: var(--c-text); border-color: var(--c-text); text-decoration: none; color: #fff; box-shadow: var(--shadow-2); }
.btn-coral.sm, .btn-ghost-coral.sm { padding: 8px 14px; font-size: 13px; min-height: 34px; }
.btn-ghost-coral { background: var(--w-card); color: var(--c-text); border-color: var(--c-line); box-shadow: var(--shadow-1); }
.btn-ghost-coral:hover { background: var(--c-tint); text-decoration: none; color: var(--c-text); border-color: var(--c-line); }

/* progress bar primitive: 8px track + coral fill, tabular % */
.pbar { height: 8px; border-radius: 99px; background: var(--w-line); overflow: hidden; flex: 1; min-width: 140px; }
.pbar > i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 400ms var(--ease); }

/* ════════════════════════════════════════════════════════════════════════
   LEARNER HOME
   ════════════════════════════════════════════════════════════════════════ */
/* WAVE 2 PART B — DENSER (Felipe: "too much spacing in the screenshot"). Tighten the inter-card gap
   (16 → 12) + trim the learner header's bottom margin so the progress-led workspace reads tighter without
   losing the V2 breathing room. */
.learn-grid { display: grid; gap: var(--gap-card); }
.dash-head.learn-head { margin-bottom: 16px; }
/* Tighten the home cards a touch (the screenshot's cards had a lot of air). The
   card padding follows the style density (--pad-card-sm); the hero/journey/momentum
   keep their per-card rhythm but pick up the density via the shared token. */
.learn-grid > .card { padding: var(--pad-card-sm); }
.learn-grid > .hero-card { padding: var(--pad-card-sm) var(--pad-card-sm) var(--pad-card-sm) calc(var(--pad-card-sm) + 4px); }
.learn-grid > .journey-wrap { padding: var(--pad-card-sm) calc(var(--pad-card-sm) + 2px) calc(var(--pad-card-sm) + 2px); }
.learn-grid > .momentum { padding: calc(var(--pad-card-sm) - 2px) calc(var(--pad-card-sm) + 2px); }

/* 1. Continue hero — pinned card, a flat coral RAIL on the left edge marks it as
   the live "continue" surface (V2: a flat accent, never a gradient wash). */
.hero-card {
  display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  background: var(--w-card);
  border-color: var(--c-line); border-radius: var(--radius-lg);
  position: relative; overflow: hidden; padding-left: 22px;
}
.hero-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--c-deep);
}
.hero-main { flex: 1; min-width: 260px; }
.hero-eyebrow {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--c-text); margin-bottom: 8px;
}
.hero-title { font-family: var(--font-display); font-size: 21px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); line-height: 1.2; }
.hero-next { font-size: 14px; color: var(--w-ink-2); margin-top: 5px; }
.hero-bar { display: flex; align-items: center; gap: 14px; margin-top: 14px; max-width: 440px; }
.pbar-pct { font-size: 13px; color: var(--w-ink-2); font-weight: 600; }
.hero-resume { font-size: 14px; padding: 10px 22px; white-space: nowrap; }

/* ════════════════════════════════════════════════════════════════════════
   2. THE V2 JOURNEY VIEW — replaces the winding-ladder (the SVG vine + numbered
   circles swaying off a centre spine). The journey is now a TIDY VERTICAL PATH:
   a single column of clean module ROWS, grouped under their section separators
   (Foundations / The 4 Ps / …). Each row is a flat V2 card — a flat coral / slate
   cover TILE (number + state glyph) + the module title + a progress line + the
   lock / owned state + a flat coral accent. Cool base, Plus Jakarta, no vine, no
   alternating geometry, no horizontal scroll at any width.
   ════════════════════════════════════════════════════════════════════════ */
.journey-wrap { padding: 20px 20px 22px; }
.journey-divider {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding-bottom: 14px; margin-bottom: 4px; border-bottom: 1px solid var(--w-line);
}
.jd-name { font-family: var(--font-display); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); }
.jd-count { font-size: 12.5px; color: var(--w-ink-3); font-weight: 600; }

/* The path: one vertical column. A quiet cool connector spine runs down the left
   gutter behind the cover tiles, tying the rows into one continuous path. */
.journey {
  list-style: none; position: relative; margin: 14px 0 0; padding: 0;
  /* WAVE 2 PART B — denser ladder: tighter inter-row gap (9 → 6). */
  display: flex; flex-direction: column; gap: 6px;
}
.journey::before {
  content: ""; position: absolute; left: 25px; top: 10px; bottom: 10px; width: 2px;
  background: var(--w-line); border-radius: 2px; z-index: 0;
}
/* A SECTION separator inside the path (the named/themed groups: Place / Digital / Foundations / The 4 Ps).
   RULE 2 (SECTION-MODULE-NUMBERING-COHERENCE): a section is a GROUPING, NOT a numbered step — the number
   belongs to the MODULE (.jnum on its cover). So the separator carries NO number badge; it reads
   "Section: {name}" via a small coral "SECTION" eyebrow chip + the name, distinct from a numbered module
   row, and matches the reader bookshelf's "Section: " prefix. */
.journey-sep {
  display: flex; align-items: center; gap: 10px; position: relative; z-index: 1;
  margin: 16px 0 5px; padding: 0;
}
.journey-sep:first-child { margin-top: 2px; }
/* The whole label = the eyebrow + the name, grouped so they align left. It is shrinkable (flex: 0 1 auto
   + min-width: 0) so a long section name ellipsizes instead of pushing the rule line off a narrow phone. */
.jsep-label {
  display: inline-flex; align-items: baseline; gap: 8px; flex: 0 1 auto; min-width: 0;
}
/* The "SECTION" eyebrow — a quiet uppercase coral-deep chip that signals a GROUPING (toggle header),
   visibly different from the white-on-coral numbered module cover. No number, ever. */
.jsep-eyebrow {
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--c-deep); background: var(--c-tint, rgba(218,119,86,0.12));
  border: 1px solid var(--c-line); border-radius: 6px; padding: 2px 6px; flex: none;
  line-height: 1.2; white-space: nowrap;
}
/* The section NAME — the grouping title; sentence/normal case so it reads as a name, not a step. */
.jsep-name {
  font-size: 13px; font-weight: 700; letter-spacing: 0.01em; color: var(--c-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.jsep-rule { height: 2px; flex: 1 1 auto; min-width: 16px; background: var(--w-line); border-radius: 2px; }
.jsep-n { font-family: var(--font-mono); font-size: 10.5px; color: var(--w-ink-4); font-weight: 600; white-space: nowrap; }

/* A module ROW — a clean horizontal V2 card: cover tile (number / state) + body. */
.jrow {
  display: flex; align-items: stretch; gap: 0; position: relative; z-index: 1;
  background: var(--w-card); border: 1px solid var(--w-line); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--w-shadow); text-decoration: none; color: inherit;
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
a.jrow:hover { transform: translateY(-2px); box-shadow: var(--w-shadow-lift); border-color: var(--c-line); text-decoration: none; color: inherit; }
a.jrow:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { a.jrow:hover { transform: none; } }

/* The flat cover TILE on the left of each row (flat fill, never a gradient). */
.jcover {
  width: 52px; flex: none; position: relative; display: grid; place-items: center;
  color: #fff; background: var(--cover-1);
}
.jrow.is-completed .jcover { background: var(--c-deep); }
.jrow.is-current   .jcover { background: var(--c-coral); }
.jrow.is-available .jcover { background: var(--cover-1); }
.jrow.is-locked    .jcover { background: var(--w-locked); }
.jcover .jnum { font-family: var(--font-mono); font-size: 15px; font-weight: 700; color: #fff; line-height: 1; }
.jrow.is-locked .jcover .jnum { color: var(--w-ink-4); }
.jcover svg { width: 20px; height: 20px; }
.jrow.is-locked .jcover svg { color: var(--w-ink-3); }
/* current row: a thin flat coral accent on the right edge of the cover marks "here". */
.jrow.is-current .jcover::after {
  content: ""; position: absolute; right: 0; top: 0; bottom: 0; width: 3px; background: var(--c-deep);
}

/* WAVE 2 PART B — denser rows: trim the vertical padding (12 → 10). */
.jbody { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; padding: 10px 14px; }
.jmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.jtitle { font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); line-height: 1.25;
  overflow-wrap: break-word; word-break: normal; hyphens: auto; }
.jrow.is-locked .jtitle { color: var(--w-ink-3); font-weight: 600; }
/* the row's status line: a thin progress bar for the current/started row, a quiet
   state word otherwise. */
.jmeta { display: flex; align-items: center; gap: 10px; }
.jbar { height: 6px; border-radius: 99px; background: var(--w-line); overflow: hidden; flex: 1; max-width: 200px; min-width: 90px; }
.jbar > i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 400ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .jbar > i { transition: none; } }
.jpct { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; color: var(--c-text); }
.jstate { font-size: 12px; font-weight: 600; }
.jstate.s-completed { color: var(--c-deep); display: inline-flex; align-items: center; gap: 5px; }
.jstate.s-completed svg { width: 14px; height: 14px; }
.jstate.s-available { color: var(--w-ink-3); }
.jstate.s-locked { color: var(--w-ink-4); display: inline-flex; align-items: center; gap: 5px; }
.jcond { font-size: 12px; color: var(--c-text); font-weight: 600; }
.jrow.is-locked .jcond { color: var(--w-ink-4); }
/* FIX 3 (2026-05-31) — a content-less module rung. Visually distinct from a real rung: muted, a DASHED border,
   no hover lift, no chevron, no lock CTA — it's an informational "No content yet" placeholder, never clickable. */
.jrow.is-empty { border-style: dashed; box-shadow: none; background: var(--w-page, transparent); cursor: default; }
.jrow.is-empty:hover { transform: none; box-shadow: none; border-color: var(--w-line); }
.jrow.is-empty .jcover { background: var(--w-line); }
.jrow.is-empty .jcover svg { color: var(--w-ink-4); }
.jrow.is-empty .jtitle { color: var(--w-ink-3); font-weight: 600; }
.jstate.s-empty { color: var(--w-ink-4); font-style: italic; }
/* a quiet coral chevron on openable rows (drops on locked rows). */
.jgo { flex: none; color: var(--c-deep); display: flex; align-items: center; transition: transform 150ms var(--ease-out); }
.jgo svg { width: 17px; height: 17px; }
a.jrow:hover .jgo { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { a.jrow:hover .jgo { transform: none; } }
.jrow.is-locked .jlock { flex: none; color: var(--w-ink-4); display: flex; align-items: center; }
.jrow.is-locked .jlock svg { width: 16px; height: 16px; }

/* one soft pulse on the current row's cover on load (the only motion). */
.jrow.is-current.pulse-once .jcover { animation: jPulse 1.4s var(--ease-out) 1; }
@keyframes jPulse {
  0% { box-shadow: inset 0 0 0 0 rgba(255,255,255,0.5); }
  60% { box-shadow: inset 0 0 0 3px rgba(255,255,255,0.35); }
  100% { box-shadow: inset 0 0 0 0 rgba(255,255,255,0); }
}
@media (prefers-reduced-motion: reduce) { .jrow.is-current.pulse-once .jcover { animation: none; } }

/* 3. Momentum trio — quiet fitness-tracker row, one coral number each. */
.momentum { display: flex; gap: 16px; justify-content: space-around; padding: 16px 20px; }
.mom-stat { display: flex; flex-direction: column; align-items: center; gap: 3px; flex: 1; }
.mom-n { font-size: 26px; font-weight: 700; color: var(--c-deep); letter-spacing: -0.02em; line-height: 1; }
.mom-l { font-size: 12px; color: var(--w-ink-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }

/* ════════════════════════════════════════════════════════════════════════
   WAVE 2 PART B — THE PROGRESS SUMMARY (the progress-forward card that LEADS the
   per-course workspace). An overall journey % bar + a row of per-GROUP / per-TYPE
   mini bars. One coral (depth only), AA, no 2nd hue, no gamification theatre.
   ════════════════════════════════════════════════════════════════════════ */
.progress-summary { display: flex; flex-direction: column; gap: 12px; }
.ps-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.ps-head-tx { min-width: 0; }
.ps-head-tx .card-eyebrow { margin-bottom: 4px; }
.ps-journey { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); line-height: 1.25;
  overflow-wrap: anywhere; }
.ps-overall { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.ps-pct { font-size: 24px; font-weight: 800; color: var(--c-deep); letter-spacing: -0.02em; line-height: 1; }
.ps-of { font-size: 11px; color: var(--w-ink-3); font-weight: 600; }
/* the overall bar — a thicker 10px coral track. */
.ps-bar { height: 10px; border-radius: 99px; background: var(--w-line); overflow: hidden; }
.ps-bar > i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 500ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .ps-bar > i, .vpl-bar > i, .ps-mini-bar > i { transition: none; } }
/* the mini-bar row — per-group or per-type, wraps on narrow widths. */
.ps-minis { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px 16px; }
.ps-mini { display: flex; flex-direction: column; gap: 5px; }
.ps-mini-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ps-mini-label { font-size: 12.5px; font-weight: 600; color: var(--w-ink-2); overflow-wrap: anywhere; line-height: 1.2; }
.ps-mini-frac { font-size: 11.5px; font-weight: 600; color: var(--c-text); }
.ps-mini-dev { font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--w-ink-3); background: var(--w-page); border: 1px solid var(--w-line);
  border-radius: 999px; padding: 2px 7px; }
.ps-mini-bar { height: 6px; border-radius: 99px; background: var(--w-line); overflow: hidden; }
.ps-mini-bar > i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 500ms var(--ease-out); }
.ps-mini.is-dev .ps-mini-bar { background: var(--w-locked); }
.ps-mini.is-dev .ps-mini-label { color: var(--w-ink-3); }
/* FIX 3 — NON-completable REFERENCE types (slides/glossary/cases/…) show a plain COUNT, never a progress bar
   (they are reference material, not "completed"). A quiet pill carries "3 slides"; there is no .ps-mini-bar. */
.ps-mini.is-ref { gap: 0; }
.ps-mini-count { font-size: 11.5px; font-weight: 600; color: var(--w-ink-3); }

/* WAVE 2 PART B — per-row element-type CHIPS on a MIXED journey's ladder rows (Reading · Video · Quiz
   coming · Assignment coming). Small, quiet, coral-text; an in-dev type greys out + reads "coming". */
.jels { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.jel { display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--c-text); background: var(--c-tint); border: 1px solid var(--c-line); border-radius: 999px; padding: 2px 8px; }
.jel svg { width: 12px; height: 12px; }
.jel.coming { color: var(--w-ink-3); background: var(--w-page); border-color: var(--w-line); }

/* ════════════════════════════════════════════════════════════════════════
   DASHBOARD-REORG (2026-05-31) — THE VIEW-CONFIGURABLE DASHBOARD
   The learner home is layered into SECTIONS (Overview · Modules · Assignments &
   grades · Progress) arranged by a STUDENT-CHOSEN layout (Tabbed / One page /
   Left sub-nav), persisted in localStorage. Same data, three arrangements. Every
   surface uses the theme variables (works in ALL themes — no hardcoded colors),
   V2 aesthetic, Emil motion (<300ms, transform/opacity only, reduced-motion
   settles), mobile-safe (≥44px, scrollable tabs/sub-nav, no overflow at 390).
   ════════════════════════════════════════════════════════════════════════ */

/* ── THE BAR: the tab strip (tabbed view) + the "View ▾" layout picker ── */
.dv-bar { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; min-width: 0; }
/* The tab strip — a horizontally-scrollable row of section tabs (tabbed view only). */
.dv-tabs { display: flex; gap: 4px; flex: 1; min-width: 0; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-bottom: 2px; }
.dv-tabs::-webkit-scrollbar { display: none; }
.dv-tab { display: inline-flex; align-items: center; gap: 8px; flex: none; min-height: 40px; white-space: nowrap;
  padding: 9px 14px; border-radius: 999px; border: 1px solid transparent; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 14px; font-weight: 650; letter-spacing: -0.01em; color: var(--w-ink-3);
  transition: background 150ms var(--ease-out), color 150ms var(--ease-out), border-color 150ms var(--ease-out), transform 120ms var(--ease-out); }
.dv-tab:hover { color: var(--w-ink); background: var(--w-page); }
.dv-tab:active { transform: scale(0.98); }
.dv-tab.is-on { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); }
.dv-tab:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.dv-tab-ic { display: inline-flex; }
.dv-tab-ic svg { width: 16px; height: 16px; }
/* The "View ▾" picker (Emil popover). */
.dv-pick { position: relative; flex: none; }
.dv-pick-trigger { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 8px 12px;
  border-radius: var(--radius-sm); border: var(--border-weight) solid var(--w-line-2); background: var(--w-card); cursor: pointer;
  font-family: var(--font); font-size: 13.5px; font-weight: 650; color: var(--w-ink); box-shadow: var(--w-shadow);
  transition: border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out), transform 120ms var(--ease-out); }
.dv-pick-trigger:hover { border-color: var(--c-line); box-shadow: var(--w-shadow-lift); }
.dv-pick-trigger:active { transform: scale(0.985); }
.dv-pick-trigger:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.dv-pick-ic { display: inline-flex; color: var(--w-ink-3); }
.dv-pick-ic svg { width: 16px; height: 16px; }
.dv-caret { width: 15px; height: 15px; color: var(--w-ink-4); transition: transform 200ms var(--ease-move); }
.dv-pick[data-open="true"] .dv-caret { transform: rotate(180deg); }
.dv-pick-menu { position: absolute; top: calc(100% + 8px); right: 0; min-width: 220px; max-width: calc(100vw - 24px);
  background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: var(--radius-lg); box-shadow: var(--shadow-3, 0 18px 48px rgba(20,30,50,.16));
  padding: 7px; transform-origin: top right; opacity: 0; transform: scale(0.97) translateY(-6px); pointer-events: none;
  z-index: 40; transition: opacity 180ms var(--ease-out), transform 200ms var(--ease-out); }
.dv-pick[data-open="true"] .dv-pick-menu { opacity: 1; transform: none; pointer-events: auto; }
.dv-pick-head { font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--w-ink-4); margin: 4px 9px 4px; }
.dv-pick-row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 42px; text-align: left;
  padding: 9px 10px; border: 0; border-radius: 10px; background: transparent; cursor: pointer; font-family: var(--font);
  font-size: 13.5px; font-weight: 600; color: var(--w-ink); transition: background 130ms var(--ease-out); }
.dv-pick-row:hover { background: var(--w-page); }
.dv-pick-row[aria-checked="true"] { background: var(--c-tint); color: var(--c-text); }
.dv-pick-row:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.dv-pick-ic, .dv-pick-row .dv-pick-ic { flex: none; }
.dv-pick-lbl { flex: 1; min-width: 0; }
.dv-pick-ck { flex: none; width: 16px; height: 16px; color: var(--c-deep); display: inline-flex; }
.dv-pick-ck svg { width: 16px; height: 16px; }

/* ── THE VIEW BODY: the sub-nav rail + the section panels ── */
.dash-views { display: block; }
.dv-subnav { display: none; }
.dv-body { min-width: 0; }
/* A small per-section header (shown in one-page + sub-nav so a section reads as a section; hidden in tabbed,
   where the active tab already names it). */
.dv-sec-head { display: flex; align-items: center; gap: 9px; margin: 0 0 12px; }
.dv-sec-ic { display: inline-flex; color: var(--c-text); }
.dv-sec-ic svg { width: 18px; height: 18px; }
.dv-sec-h { font-family: var(--font-display); font-size: 18px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink); }
/* The panel — fades/rises in on activation (Emil; reduced-motion settles). */
.dv-panel { animation: dvIn 240ms var(--ease-out) both; }
@keyframes dvIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .dv-panel { animation: none; } }

/* TABBED (default): the tab strip shows; the active panel only; no per-section header (the tab names it). */
.dash-views[data-view="tabbed"] .dv-sec-head { display: none; }
.dash-views[data-view="tabbed"] .dv-subnav { display: none; }

/* ONE PAGE: hide the tab strip; show ALL panels stacked, each with its section header + a divider gap. */
.dash-views[data-view="onepage"] .dv-panel { margin-bottom: 22px; }
.dash-views[data-view="onepage"] .dv-panel:last-child { margin-bottom: 0; }
/* the tab strip is hidden in one-page + sub-nav (the bar keeps just the View picker, right-aligned). The
   layout is mirrored onto .dv-bar by applyView() so no CSS :has() is needed. */
.dv-bar[data-view="onepage"] .dv-tabs, .dv-bar[data-view="subnav"] .dv-tabs { display: none; }
.dv-bar[data-view="onepage"], .dv-bar[data-view="subnav"] { justify-content: flex-end; }

/* LEFT SUB-NAV: a left rail of section links + the active panel filling the main area. The tab strip up top
   is hidden (the rail replaces it). On a phone the rail becomes a top scroll strip (mobile rule below). */
.dash-views[data-view="subnav"] { display: grid; grid-template-columns: 186px 1fr; gap: 18px; align-items: start; }
.dash-views[data-view="subnav"] .dv-subnav { display: flex; flex-direction: column; gap: 3px; position: sticky; top: 14px;
  border: var(--border-weight) solid var(--w-line); border-radius: var(--radius-lg); background: var(--w-card); padding: 8px; box-shadow: var(--w-shadow); }
.dash-views[data-view="subnav"] .dv-sec-head { display: flex; }
.dv-sub { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; text-align: left;
  padding: 10px 12px; border: 0; border-radius: 10px; background: transparent; cursor: pointer; font-family: var(--font);
  font-size: 14px; font-weight: 600; color: var(--w-ink-2); transition: background 140ms var(--ease-out), color 140ms var(--ease-out); }
.dv-sub:hover { background: var(--w-page); color: var(--w-ink); }
.dv-sub.is-on { background: var(--c-tint); color: var(--c-text); }
.dv-sub:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.dv-sub-ic { display: inline-flex; flex: none; }
.dv-sub-ic svg { width: 17px; height: 17px; }
.dv-sub-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── THE OVERVIEW CARD (tight summary): progress ring + Continue + per-group minis + due-soon ── */
.overview-card { display: flex; flex-direction: column; gap: 14px; }
.ov-top { display: flex; align-items: center; gap: 18px; min-width: 0; flex-wrap: wrap; }
.ov-ring { position: relative; flex: none; width: 72px; height: 72px; display: flex; align-items: center; justify-content: center; }
.ov-ring-svg { width: 72px; height: 72px; }
.ov-ring-track { stroke: var(--w-line); }
.ov-ring-fill { stroke: var(--c-coral); transition: stroke-dashoffset 600ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .ov-ring-fill { transition: none; } }
.ov-ring-pct { position: absolute; font-size: 15px; font-weight: 800; color: var(--c-deep); letter-spacing: -0.02em; }
.ov-cont { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 4px; }
.ov-cont-h { font-family: var(--font-display); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); line-height: 1.2; }
.ov-cont-sub { font-size: 12px; color: var(--w-ink-3); font-weight: 600; }
.ov-resume { margin-top: 6px; align-self: flex-start; }
.ov-minis { margin-top: 0; }
.ov-due { border-top: 1px solid var(--w-line); padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.ov-sub { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--w-ink-4); margin: 0; }
.ov-due-row { display: flex; align-items: center; gap: 11px; min-width: 0; }
.ov-due-ic { display: inline-flex; flex: none; color: var(--c-text); }
.ov-due-ic svg { width: 16px; height: 16px; }
.ov-due-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ov-due-tx b { font-size: 13.5px; font-weight: 650; color: var(--w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-due-tx .mono { font-size: 11px; color: var(--w-ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-due-go { flex: none; }
.ov-due-soon { flex: none; font-size: 11.5px; font-weight: 600; color: var(--w-ink-3); }
/* "You're all caught up" — shown when every assignment/quiz on the path is finished (no stale due-soon item). */
.ov-due-allclear { display: flex; align-items: center; gap: 9px; min-width: 0;
  font-size: 13px; color: var(--w-ink-2); line-height: 1.45; }
.ov-due-allclear-ic { display: inline-flex; flex: none; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; background: var(--c-tint, #fcefe9); color: var(--c-deep, #B8553A); }
.ov-due-allclear-ic svg { width: 14px; height: 14px; }

/* ── THE CANVAS-LIKE "ASSIGNMENTS & GRADES" CARD (your work) ── */
.assign-grades { display: flex; flex-direction: column; gap: 14px; }
.ag-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.ag-head-tx { min-width: 0; }
.ag-h { font-family: var(--font-display); font-size: 18px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink); margin: 2px 0 4px; }
.ag-sub { font-size: 13px; color: var(--w-ink-2); line-height: 1.5; max-width: 52ch; }
.ag-count { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.ag-count-n { font-size: 20px; font-weight: 800; color: var(--c-deep); letter-spacing: -0.02em; }
.ag-count-l { font-size: 10.5px; color: var(--w-ink-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.ag-rows { display: flex; flex-direction: column; }
.ag-row { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-top: 1px solid var(--w-line); min-width: 0; }
.ag-row:first-child { border-top: 0; }
.ag-ic { display: inline-flex; flex: none; color: var(--c-text); }
.ag-ic svg { width: 18px; height: 18px; }
.ag-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ag-title { font-size: 14px; font-weight: 650; color: var(--w-ink); overflow-wrap: anywhere; line-height: 1.3; }
.ag-meta { font-size: 11.5px; color: var(--w-ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-status-cell { flex: none; min-width: 92px; display: flex; justify-content: flex-end; }
.ag-status { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
.ag-status.is-done { color: var(--c-text); }
.ag-status.is-todo { color: var(--w-ink-3); }
.ag-status.is-soon { color: var(--w-ink-3); }
.ag-status.is-locked { color: var(--c-text); }
.ag-status svg { width: 13px; height: 13px; }
.ag-action { flex: none; }
.ag-na { font-size: 11.5px; font-weight: 600; color: var(--w-ink-3); }
/* On a phone the row stacks the status+action under the title (no overflow). */
@media (max-width: 560px) {
  .ag-row { flex-wrap: wrap; }
  .ag-main { flex: 1 1 100%; }
  .ag-status-cell { min-width: 0; justify-content: flex-start; }
  .ag-action { margin-left: auto; }
}

/* ── LADDER GROUP COLLAPSE — the Modules ladder's section separators become toggle headers ── */
/* The whole "Section: {name}" eyebrow is the toggle button (role=button). It gets a comfortable
   WCAG 2.5.5 hit area (>=44px) at every width — the eyebrow + name stay visually compact, vertically
   centered in the taller, full-width clickable row (a section header is a chunky, easy target by design).
   The reduced top margin compensates so the ladder rhythm stays tight despite the taller hit row. */
.journey-sep.is-collapsible { cursor: pointer; border-radius: 9px; min-height: 44px; padding: 6px;
  margin: 10px -6px 2px; transition: background 130ms var(--ease-out); }
.journey-sep.is-collapsible:first-child { margin-top: 2px; }
.journey-sep.is-collapsible:hover { background: var(--w-page); }
.journey-sep.is-collapsible:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.jsep-chev { display: inline-flex; flex: none; margin-left: 8px; color: var(--w-ink-4); transition: transform 200ms var(--ease-move); }
.jsep-chev svg { width: 16px; height: 16px; }
.journey-sep.is-collapsed .jsep-chev { transform: rotate(-90deg); }

/* ════════ PER-SECTION DASHBOARD "View ▾" CONTROLS (2026-05-31) ════════
   The Modules density/expand control + the Assignments filter/sort control live WITHIN whatever dashboard
   layout is active. Both reuse the shared .xv-pick popover (themed in every theme/style). A tools row places
   the section eyebrow on the left + the picker on the right. */
.dv-sec-tools { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-width: 0; margin: 0 0 4px; }
.dv-sec-tools .card-eyebrow { flex: 1; min-width: 0; }
/* command rows in a popover (Expand all / Collapse all) — no persistent check, just an action affordance. */
.xv-pick-cmd .xv-pick-ck { visibility: hidden; }

/* MODULES DENSITY (Felipe 2026-05-31) — three real layouts for the ladder, persisted in cc-modules-view, so the
   "convoluted big-card wall" can become a scannable list. Comfortable = the rich card (default sizes above).
   Compact = the same card with the chrome shrunk. Minimal = a clean one-line-per-module list. The collapsible
   groups, the overview popup, the % and the ✓ ticks keep working in all three (these rules only restyle). */

/* COMPACT — genuinely LESS chrome: smaller cover tile, thin bar, trimmed padding, and the type chips HIDDEN
   (the journey reads as a tight scannable column; the per-element take rows + transfer prompts stay). */
.journey[data-density="compact"] { gap: 4px; }
.journey[data-density="compact"] .jcover { width: 38px; }
.journey[data-density="compact"] .jcover .jnum { font-size: 12.5px; }
.journey[data-density="compact"] .jcover svg { width: 16px; height: 16px; }
.journey[data-density="compact"] .jbody { padding: 6px 12px; gap: 10px; }
.journey[data-density="compact"] .jmain { gap: 2px; }
.journey[data-density="compact"] .jtitle { font-size: 13.5px; }
.journey[data-density="compact"] .jbar { height: 4px; max-width: 120px; min-width: 60px; }
.journey[data-density="compact"] .journey-sep { margin: 9px 0 3px; }
/* hide the pill chips in Compact (the per-element take ROWS below the module still show the real work). */
.journey[data-density="compact"] .jels { display: none; }

/* MINIMAL — the lightest view: one clean LINE per module. No giant coral number block, no full-width bar, no
   pill chips. The shared row markup is repurposed: the cover tile collapses to a tiny status dot (the index /
   a check / a lock), the title sits on the line, a TINY progress meter replaces the bar, and the type chips
   become small dots. The whole ladder reads as a scannable table of contents. */
.journey[data-density="minimal"] { gap: 0; }
.journey[data-density="minimal"]::before { display: none; }   /* drop the spine — a flat list needs no connector */
.journey[data-density="minimal"] .jrow {
  border: 0; border-bottom: 1px solid var(--w-line); border-radius: 0; box-shadow: none; background: transparent;
}
.journey[data-density="minimal"] li:last-child .jrow { border-bottom: 0; }
.journey[data-density="minimal"] a.jrow:hover { transform: none; box-shadow: none; background: var(--w-page); border-color: var(--w-line); }
/* the cover tile → a tiny 18px status dot (no big coral block). The index number / check / lock shrinks into it. */
.journey[data-density="minimal"] .jcover {
  width: 18px; height: 18px; flex: none; border-radius: 50%; align-self: center; margin: 0 0 0 4px; background: transparent;
}
.journey[data-density="minimal"] .jrow.is-completed .jcover { background: var(--c-deep); }
.journey[data-density="minimal"] .jrow.is-current   .jcover { background: var(--c-coral); }
.journey[data-density="minimal"] .jrow.is-available .jcover { background: transparent; border: 1.5px solid var(--c-line, #e8c4b4); }
.journey[data-density="minimal"] .jrow.is-locked    .jcover { background: var(--w-locked); }
.journey[data-density="minimal"] .jcover::after { display: none; }   /* drop the current-row edge accent */
.journey[data-density="minimal"] .jcover .jnum { font-size: 9.5px; color: var(--c-deep); }
.journey[data-density="minimal"] .jrow.is-available .jcover .jnum { color: var(--w-ink-3); }
.journey[data-density="minimal"] .jrow.is-current .jcover .jnum { color: #fff; }
.journey[data-density="minimal"] .jcover svg { width: 11px; height: 11px; }
/* the body becomes a single tight line: title left, meta right. */
.journey[data-density="minimal"] .jbody { padding: 8px 10px; gap: 10px; align-items: center; }
.journey[data-density="minimal"] .jmain { flex-direction: row; align-items: center; gap: 10px; }
.journey[data-density="minimal"] .jtitle { font-size: 13px; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
/* a TINY progress meter (a thin short bar) instead of the wide one; the % chip stays small. */
.journey[data-density="minimal"] .jmeta { flex: none; gap: 6px; }
.journey[data-density="minimal"] .jbar { height: 3px; max-width: 54px; min-width: 40px; }
.journey[data-density="minimal"] .jpct { font-size: 10.5px; }
.journey[data-density="minimal"] .jstate { font-size: 11px; }
.journey[data-density="minimal"] .jstate.s-completed svg { width: 12px; height: 12px; }
.journey[data-density="minimal"] .jcond { font-size: 11px; }
.journey[data-density="minimal"] .jgo svg { width: 15px; height: 15px; }
.journey[data-density="minimal"] .jrow.is-locked .jlock { font-size: 11px; }
/* the type CHIPS → small dots (icon only, no pill, no label). */
.journey[data-density="minimal"] .jels { margin: 0; gap: 5px; flex: none; }
.journey[data-density="minimal"] .jel {
  padding: 0; background: transparent; border: 0; font-size: 0; gap: 0; color: var(--w-ink-3); }
.journey[data-density="minimal"] .jel svg { width: 13px; height: 13px; margin: 0; }
.journey[data-density="minimal"] .jel.coming { opacity: 0.45; }
/* group separators stay (collapse still works) but read lighter — the de-numbered "Section: {name}"
   eyebrow + name shrink to suit the dense list (no number badge anymore). */
.journey[data-density="minimal"] .journey-sep { margin: 12px 0 2px; }
.journey[data-density="minimal"] .jsep-eyebrow { font-size: 8.5px; padding: 1px 5px; }
.journey[data-density="minimal"] .jsep-name { font-size: 12px; }
/* the below-row Wave D extras align to the new tiny cover. */
.journey[data-density="minimal"] .jrow-extra { margin-left: 32px; }
@media (max-width: 600px) {
  .journey[data-density="minimal"] .jmain { flex-wrap: wrap; gap: 4px 10px; }
  .journey[data-density="minimal"] .jtitle { white-space: normal; flex: 1 1 100%; }
}

/* ASSIGNMENTS & GRADES head — the count + the "View ▾" picker share a right-aligned column. */
.ag-head-right { flex: none; display: flex; align-items: center; gap: 12px; }
/* the friendly empty-filter line. */
.ag-empty { font-size: 13px; color: var(--w-ink-3); line-height: 1.5; padding: 16px 4px 4px; }
@media (max-width: 560px) {
  .ag-head { flex-wrap: wrap; }
  .ag-head-right { width: 100%; justify-content: space-between; }
}

/* The "View ▾" picker: respect reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .dv-pick-menu { transition: opacity 120ms linear; transform: none; }
  .dv-pick[data-open="true"] .dv-pick-menu { transform: none; }
  .dv-caret, .jsep-chev, .dv-tab, .dv-pick-trigger, .ov-ring-fill { transition: none; }
}

/* MOBILE (≤640px): the sub-nav becomes a top horizontal scroll strip; the tab strip already scrolls. No
   horizontal page overflow at 390 (everything wraps / scrolls within its container). */
@media (max-width: 760px) {
  .dash-views[data-view="subnav"] { grid-template-columns: 1fr; gap: 12px; }
  .dash-views[data-view="subnav"] .dv-subnav { flex-direction: row; position: static; overflow-x: auto;
    scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .dash-views[data-view="subnav"] .dv-subnav::-webkit-scrollbar { display: none; }
  .dash-views[data-view="subnav"] .dv-sub { flex: none; white-space: nowrap; }
  .dv-bar { flex-wrap: wrap; }
}

/* ════════════════════════════════════════════════════════════════════════
   WAVE D — REAL element completion + the cross-journey TRANSFER PROMPT.
   .jxfer = the explicit "✓ Completed in [X] — count it here?" affordance on a
   ladder/element row (a coral tint band + a Transfer button). .jelrs/.jelr =
   the per-element ACTION ROWS beneath a module (a takeable assignment/quiz, a
   video) with their real ✓ / "Start" / "In development" state. Coral-family on
   the V2 cool ink; mobile-safe (wraps, min-width:0, 44px touch). Emil motion:
   only transform/opacity on hover; settles instantly under reduced-motion. */
.jxfer { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  padding: 9px 11px; border-radius: 10px;
  background: var(--c-tint, #fcefe9); border: 1px solid var(--c-line, #e8c4b4); }
.jxfer-txt { display: inline-flex; align-items: flex-start; gap: 7px; min-width: 0; flex: 1;
  font-size: 12.5px; line-height: 1.45; color: var(--w-ink-2, #404a5c); }
.jxfer-txt svg { flex: none; width: 14px; height: 14px; color: var(--c-deep, #B8553A); margin-top: 1px; }
.jxfer-txt b { color: var(--w-ink, #1a1f2e); font-weight: 700; }
.jxfer .btn-coral.sm { flex: none; min-height: 34px; }
.jxfer-err { flex: 1 1 100%; font-size: 11.5px; color: var(--c-deep, #B8553A); font-weight: 600; margin-top: 2px; }

/* The container for a module's BELOW-row Wave D extras (transfer prompt + element-take rows). Sits under the
   row, indented to align with the row BODY (past the 52px cover tile) so it reads as part of the module. */
.jrow-extra { margin: 6px 0 2px 52px; display: flex; flex-direction: column; gap: 6px; }
@media (max-width: 600px) { .jrow-extra { margin-left: 0; } }

.jelrs { display: flex; flex-direction: column; gap: 5px; margin-top: 0; }
.jelr { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0;
  padding: 8px 10px; border-radius: 9px; background: var(--w-page, #f6f8fb);
  border: 1px solid var(--w-line, #eef1f6); min-height: 40px; }
a.jelr.is-open { cursor: pointer; text-decoration: none; color: inherit;
  transition: transform 120ms var(--ease-out, ease), box-shadow 120ms var(--ease-out, ease), border-color 120ms var(--ease-out, ease); }
a.jelr.is-open:hover { transform: translateY(-1px); border-color: var(--c-line, #e8c4b4); box-shadow: var(--w-shadow, 0 1px 2px rgba(20,30,50,.05)); }
a.jelr.is-open:focus-visible { outline: 2px solid var(--c-deep, #B8553A); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { a.jelr.is-open:hover { transform: none; } }
.jelr.is-soon { opacity: 0.72; }
.jelr-label { display: inline-flex; align-items: center; gap: 7px; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--w-ink, #1a1f2e); }
.jelr-label svg { flex: none; width: 14px; height: 14px; color: var(--w-ink-3, #5b6678); }
.jelr-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.jelr-done { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 700; color: var(--c-deep, #B8553A); }
.jelr-done svg { width: 13px; height: 13px; }
.jelr-soon { flex: none; font-size: 11px; font-weight: 600; color: var(--w-ink-4, #646d82); }
.jelr-go { flex: none; display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 700; color: var(--c-text, #a8472a); }
.jelr-go svg { width: 13px; height: 13px; }
@media (max-width: 600px) {
  .jxfer { gap: 8px; }
  .jxfer-txt { flex: 1 1 100%; }
  .jxfer .btn-coral.sm { width: 100%; }
}

/* ════════════════════════════════════════════════════════════════════════
   WAVE 2 PART B — THE VIDEO-CENTRIC HOME (a videos-only journey). A lecture
   PLAYLIST: a header ("N lectures") + a watched-progress line + a list of play
   rows (each a lecture with a play affordance + duration). No reading ladder.
   ════════════════════════════════════════════════════════════════════════ */
.videos-playlist { display: flex; flex-direction: column; gap: 14px; }
.vpl-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.vpl-head-tx { min-width: 0; flex: 1; }
.vpl-head-tx .card-eyebrow { margin-bottom: 4px; }
.vpl-h { font-family: var(--font-display); font-size: 20px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink); line-height: 1.15; }
.vpl-sub { font-size: 13.5px; color: var(--w-ink-2); margin-top: 5px; line-height: 1.5; max-width: 54ch; }
.vpl-gallery { flex: none; }
.vpl-progress { display: flex; align-items: center; gap: 12px; }
.vpl-bar { height: 8px; border-radius: 99px; background: var(--w-line); overflow: hidden; flex: 1; }
.vpl-bar > i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 500ms var(--ease-out); }
.vpl-frac { font-size: 12px; font-weight: 600; color: var(--w-ink-3); white-space: nowrap; }
.vpl-list { display: flex; flex-direction: column; gap: 6px; }
.vpl-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--w-card); border: 1px solid var(--w-line); text-decoration: none; color: inherit;
  box-shadow: var(--w-shadow);
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out), border-color 160ms var(--ease-out); }
a.vpl-row:hover { transform: translateY(-2px); box-shadow: var(--w-shadow-lift); border-color: var(--c-line); text-decoration: none; color: inherit; }
a.vpl-row:focus-visible, .vpl-row[role="button"]:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { a.vpl-row:hover { transform: none; } }
.vpl-row.is-locked { cursor: pointer; }
.vpl-ic { flex: none; width: 36px; height: 36px; border-radius: 9px; display: grid; place-items: center;
  background: var(--c-deep); color: #fff; }
.vpl-ic svg { width: 18px; height: 18px; }
.vpl-ic.done { background: var(--c-tint); color: var(--c-deep); border: 1px solid var(--c-line); }
.vpl-ic.locked { background: var(--w-locked); color: var(--w-ink-3); }
.vpl-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.vpl-title { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); line-height: 1.25; overflow-wrap: anywhere; }
.vpl-row.is-locked .vpl-title { color: var(--w-ink-3); font-weight: 600; }
.vpl-meta { font-size: 12px; color: var(--w-ink-3); }
.vpl-go { flex: none; color: var(--c-deep); display: flex; align-items: center; transition: transform 150ms var(--ease-out); }
.vpl-go svg { width: 16px; height: 16px; }
a.vpl-row:hover .vpl-go { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { a.vpl-row:hover .vpl-go { transform: none; } }

/* 4a. Your Class — the title is an <h2> (a11y heading order: it's the first card under the home h1).
   .cc-title keeps the exact prior visual weight regardless of the heading tag. The All-lecture-videos Home
   card (.videos-card, the §A all-videos journey lead) shares the same title treatment. */
.class-card h3, .class-card .cc-title,
.videos-card h2, .videos-card .cc-title { font-family: var(--font); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); margin: 0; }
.cc-meta { font-size: 11.5px; color: var(--w-ink-3); margin-top: 3px; }
.cc-line { font-size: 14px; color: var(--w-ink-2); margin-top: 5px; }
.cc-cov {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 13px;
  padding: 12px 14px; background: var(--c-tint); border: 1px solid var(--c-line); border-radius: var(--radius-sm);
}
.cc-cov span { font-size: 13.5px; color: var(--w-ink-2); flex: 1; min-width: 160px; }

/* 4b. Assignments */
.asg-rows { display: grid; gap: 8px; }
.asg-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--w-line); }
.asg-row:last-child { border-bottom: 0; }
.asg-row-main { display: flex; flex-direction: column; gap: 2px; }
.asg-row-main b { font-size: 14px; color: var(--w-ink); }
.asg-row-main .mono { font-size: 11px; color: var(--w-ink-3); }
.asg-locked { font-size: 12px; font-weight: 600; color: var(--c-text); }

/* 4c. Your Purchases */
.ord-rows { display: grid; }
.ord-row { display: flex; align-items: center; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--w-line); }
.ord-row:last-child { border-bottom: 0; }
.ord-main { display: flex; flex-direction: column; gap: 2px; }
.ord-main b { font-size: 14px; color: var(--w-ink); }
.ord-main .mono { font-size: 11.5px; color: var(--w-ink-3); }
.ord-amt { margin-left: auto; font-weight: 600; font-size: 14.5px; color: var(--w-ink); }
.ord-status { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 3px 9px; border-radius: 999px; }
.ord-status.paid { background: var(--c-tint); color: var(--c-text); }
.ord-status.refunded, .ord-status.failed, .ord-status.canceled { background: var(--w-locked); color: var(--w-ink-3); }
.ord-status.pending { background: var(--c-tint2); color: var(--c-text); }

/* return-state banners */
.banner-ok, .banner-note {
  display: flex; align-items: flex-start; gap: 14px; margin-bottom: 16px;
  padding: 14px 16px; border-radius: var(--radius); border: 1px solid var(--w-line);
}
.banner-ok { background: var(--c-tint); border-color: var(--c-line); }
.banner-note { background: var(--w-card); }
.banner-ok svg, .banner-note svg { width: 24px; height: 24px; flex: none; color: var(--c-deep); margin-top: 1px; }
.banner-note svg { color: var(--w-ink-3); }
.banner-ok b, .banner-note b { font-size: 15px; display: block; margin-bottom: 2px; color: var(--w-ink); }
.banner-ok p, .banner-note p { font-size: 13.5px; color: var(--w-ink-2); }
/* #54 approved-instructor banner extras: a dismiss × + a CTA action row (reuses .btn-coral for the button) */
.banner-ok .bn-x, .banner-note .bn-x { margin-left: auto; flex: none; align-self: flex-start; background: none; border: 0; font-size: 20px; line-height: 1; color: var(--w-ink-3); cursor: pointer; padding: 0 2px; border-radius: 8px; }
.banner-ok .bn-x:hover, .banner-note .bn-x:hover { color: var(--w-ink); }
.banner-ok .bn-actions { margin-top: 10px; }
.banner-ok .bn-actions .bn-cta { padding: 7px 14px; font-size: 13px; }

/* ── Info tooltip primitive (#115): a focusable ⓘ trigger + a bubble on hover/focus. Emil: 150ms ease-out,
   scale(0.97)→1, trigger-origin, reduced-motion-safe; fixed dark bubble (theme-independent, AA white-on-dark);
   opens DOWNWARD so it never clips against the top of the page where these triggers live. */
.cc-tip { position: relative; display: inline-flex; vertical-align: middle; margin-left: 5px; }
.cc-tip-btn { display: inline-flex; align-items: center; justify-content: center; width: 17px; height: 17px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--w-ink-3); cursor: help; -webkit-tap-highlight-color: transparent; }
.cc-tip-btn:hover, .cc-tip-btn:focus-visible { color: var(--c-deep); }
.cc-tip-btn svg { display: block; }
.cc-tip-pop {
  position: absolute; left: 50%; top: calc(100% + 9px); z-index: 80;
  width: max-content; max-width: 244px; padding: 9px 12px; border-radius: 10px;
  background: #1f2430; color: #fff; font: 450 12px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  text-align: left; letter-spacing: 0; text-transform: none;
  box-shadow: 0 8px 28px rgba(15, 18, 28, 0.28); opacity: 0; pointer-events: none;
  transform: translateX(-50%) scale(0.97); transform-origin: top center;
  transition: opacity 150ms cubic-bezier(0.23, 1, 0.32, 1), transform 150ms cubic-bezier(0.23, 1, 0.32, 1);
}
.cc-tip-pop::after { content: ""; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); border: 5px solid transparent; border-bottom-color: #1f2430; }
.cc-tip-btn:hover + .cc-tip-pop, .cc-tip-btn:focus-visible + .cc-tip-pop { opacity: 1; transform: translateX(-50%) scale(1); }
@media (prefers-reduced-motion: reduce) {
  .cc-tip-pop { transition: opacity 120ms ease; transform: translateX(-50%); }
  .cc-tip-btn:hover + .cc-tip-pop, .cc-tip-btn:focus-visible + .cc-tip-pop { transform: translateX(-50%); }
}
@media (max-width: 560px) { .cc-tip-pop { max-width: 200px; } }

/* ════════════════════════════════════════════════════════════════════════
   INSTRUCTOR HOME — "Sections you teach" cards (Canvas-like).
   ════════════════════════════════════════════════════════════════════════ */
.ix-toolbar { display: flex; justify-content: flex-end; margin-bottom: 16px; }
.sec-card-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); }
.sec-card {
  display: flex; flex-direction: column; gap: 12px; cursor: pointer;
  background: var(--w-card); border: var(--border-weight) solid var(--w-line); border-radius: var(--radius-lg); padding: var(--pad-card);
  box-shadow: var(--w-shadow); transition: border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out), transform 150ms var(--ease-out);
}
.sec-card:hover { border-color: var(--c-line); box-shadow: var(--w-shadow-lift); transform: translateY(-2px); }
.sec-card:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .sec-card:hover { transform: none; } }
.sec-card-head h3 { font-family: var(--font); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); }
.sec-card-reg { font-size: 11.5px; color: var(--w-ink-3); margin-top: 3px; font-family: var(--font-mono); }
.sec-card-stats { display: flex; flex-direction: column; gap: 10px; }
.stat-inline { display: flex; align-items: baseline; gap: 7px; }
.stat-n { font-size: 21px; font-weight: 700; color: var(--w-ink); letter-spacing: -0.01em; }
.stat-l { font-size: 13px; color: var(--w-ink-3); }
.sec-card-track { display: flex; align-items: center; gap: 12px; }
.track-bar { height: 8px; border-radius: 99px; background: var(--w-line); overflow: hidden; flex: 1; }
.track-bar i { display: block; height: 100%; background: var(--c-coral); border-radius: 99px; transition: width 500ms var(--ease); }
.track-pct { font-size: 12.5px; color: var(--w-ink-2); font-weight: 600; white-space: nowrap; }
.sec-card-behind { font-size: 13px; color: var(--c-text); font-weight: 600; display: flex; align-items: center; gap: 7px; min-height: 18px; }
.behind-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--c-deep); flex: none; }
.sec-card-behind .ontrack { color: var(--w-ink-3); font-weight: 500; }
.sec-card-foot { margin-top: auto; }
.sec-open { font-size: 13.5px; font-weight: 600; color: var(--c-text); }
.ix-empty { grid-column: 1 / -1; text-align: center; padding: 32px 20px; background: var(--w-card);
  border: 1px dashed var(--w-lock-border); border-radius: var(--radius-lg); }
.ix-empty h3 { font-family: var(--font); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; margin-bottom: 5px; color: var(--w-ink); }
.ix-empty p { font-size: 14px; color: var(--w-ink-2); margin-bottom: 14px; }

/* ════════════════════════════════════════════════════════════════════════
   COURSE WORKSPACE
   ════════════════════════════════════════════════════════════════════════ */
.ws-top { margin-bottom: 8px; }
.ws-back { display: inline-flex; align-items: center; gap: 7px; background: none; border: 0; cursor: pointer;
  font-size: 13.5px; font-weight: 600; color: var(--c-text); padding: 6px 4px; font-family: inherit; }
.ws-back:hover { color: var(--c-deep); }
.ws-back svg { width: 16px; height: 16px; }
.ws-head { margin-bottom: 16px; }
.ws-head h1 { font-family: var(--font); font-size: 26px; font-weight: 800; color: var(--w-ink); letter-spacing: -0.03em; }
.ws-reg { font-size: 12px; color: var(--w-ink-3); margin-top: 4px; }
/* The workspace tab bar is a SINGLE horizontally-scrollable strip — it never wraps
   to a second row (it used to wrap at ~390 into Overview/Students/Assignments/Staff
   then Course path/Reports). On a narrow phone the overflowing tabs scroll sideways;
   the bottom border still reads as one rule. The tabs do not shrink, so each stays
   tappable, and momentum scrolling is enabled on touch. */
.ws-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--w-line); margin-bottom: 20px;
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; }
.ws-tab { flex: 0 0 auto; white-space: nowrap; padding: 10px 14px; font-size: 14px; font-weight: 600; color: var(--w-ink-3); background: none; border: 0;
  border-bottom: 2px solid transparent; cursor: pointer; font-family: inherit; transition: color 150ms var(--ease-out); }
.ws-tab:hover { color: var(--w-ink); }
.ws-tab.on { color: var(--c-text); font-weight: 700; border-bottom-color: var(--c-coral); }
.ws-sec { margin-bottom: 28px; }
.ws-sec:last-child { margin-bottom: 0; }
.ws-h2 { font-family: var(--font); font-size: 20px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); margin-bottom: 12px; }
.ws-h2-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 6px; }
.ws-h2-row .ws-h2 { margin-bottom: 0; }
.ws-quiet { font-size: 14px; color: var(--w-ink-3); line-height: 1.55; }

/* join code + invite */
.join-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.join-code-box { display: flex; flex-direction: column; gap: 3px; padding: 8px 16px; background: var(--c-tint);
  border: 1px solid var(--c-coral); border-radius: var(--radius); }
.join-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--c-text); font-weight: 600; }
.join-code { font-size: 22px; font-weight: 700; letter-spacing: 0.16em; color: var(--c-text); }
.join-msg { font-size: 12.5px; color: var(--w-ink-3); opacity: 0; transition: opacity 200ms; min-height: 16px; margin-top: 8px; }
.invite-form { display: grid; gap: 10px; margin-top: 16px; max-width: 560px; }
.invite-form textarea { font-family: var(--font); font-size: 14px; padding: 11px 13px; border: 1px solid var(--w-line-2);
  border-radius: 10px; resize: vertical; background: var(--w-card); color: var(--w-ink); }
.invite-form textarea:focus { outline: none; border-color: var(--c-coral); box-shadow: 0 0 0 3px var(--c-tint); }
.invite-msg { font-size: 12.5px; color: var(--w-ink-2); }

/* who's behind rail */
.behind-rail { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 6px; }
.behind-chip { flex: none; padding: 11px 15px; background: var(--c-tint); border: 1px solid var(--c-coral); border-radius: var(--radius); min-width: 130px; }
.bc-name { display: block; font-size: 13.5px; font-weight: 600; color: var(--w-ink); }
.bc-meta { display: block; font-size: 11px; color: var(--c-text); margin-top: 3px; }

/* heatmap */
/* The bordered scroll container shrinks to the table's own width so the border + tint
   hug the columns instead of stretching the full content column (a ~430px empty void to
   the right of the last module read as broken). width:max-content sizes the box to the
   table; max-width:100% lets it cap at the column and fall back to internal scrolling on a
   phone (where the 12-col table is wider than the viewport). Generalize: any narrow data
   table in a bordered overflow-x rail should size to content, not the column. */
.hm-scroll { overflow-x: auto; border: 1px solid var(--w-line); border-radius: var(--radius);
  width: max-content; max-width: 100%; }
.hm-table { border-collapse: separate; border-spacing: 2px; background: var(--w-line); font-size: 12px; }
.hm-table th { font-weight: 600; color: var(--w-ink-2); padding: 7px 8px; background: var(--w-card); position: sticky; }
.hm-table thead th { top: 0; z-index: 2; }
.hm-corner { left: 0; z-index: 3 !important; text-align: left; }
.hm-rowh { left: 0; z-index: 1; text-align: left; white-space: nowrap; color: var(--w-ink); font-weight: 500;
  display: flex; align-items: center; gap: 6px; }
.hm-col { text-align: center; min-width: 30px; cursor: pointer; }
.hm-col:hover { color: var(--c-text); }
.hm-cell { width: 30px; height: 30px; cursor: pointer; padding: 0; }
.hm-cell:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.hm-behind { width: 7px; height: 7px; border-radius: 50%; background: var(--c-deep); flex: none; display: inline-block; }
.hm-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 14px; }
.hm-leg { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--w-ink-2); }
.hm-leg i { width: 14px; height: 14px; border-radius: 4px; display: inline-block; }
.hm-drill { margin-top: 18px; border: 1px solid var(--w-line); border-radius: var(--radius); padding: 16px 18px; background: var(--w-card); }
.drill-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.drill-head b { font-size: 14.5px; color: var(--w-ink); }
.drill-x { background: none; border: 0; font-size: 22px; line-height: 1; color: var(--w-ink-3); cursor: pointer; }
.drill-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 0; border-bottom: 1px solid var(--w-line); font-size: 13.5px; }
.drill-row:last-child { border-bottom: 0; }
.drill-row.hot { background: var(--c-tint); margin: 0 -8px; padding: 7px 8px; border-radius: 7px; }
.ds-complete { color: var(--c-deep); font-weight: 600; }
.ds-in-progress { color: var(--c-coral); }
.ds-not-started { color: var(--w-ink-3); }

/* roster table */
.roster-scroll { overflow-x: auto; border: 1px solid var(--w-line); border-radius: var(--radius); }
.roster-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.roster-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--w-ink-3);
  font-weight: 600; padding: 9px 13px; border-bottom: 1px solid var(--w-line); background: var(--w-card); }
.roster-table td { padding: 9px 13px; border-bottom: 1px solid var(--w-line); color: var(--w-ink-2); }
.roster-table tr:last-child td { border-bottom: 0; }
.rt-name { font-weight: 600; color: var(--w-ink); display: flex; align-items: center; gap: 7px; }
.rt-email { font-size: 11px; color: var(--w-ink-3); margin-top: 2px; }
.tag-behind { font-size: 11px; font-weight: 600; color: var(--c-text); background: var(--c-tint); padding: 3px 9px; border-radius: 999px; }
.tag-ok { font-size: 11px; font-weight: 600; color: var(--w-ink-3); }

/* assignments tab */
.asg-list { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); }
.asg-card { background: var(--w-card); border: var(--border-weight) solid var(--w-line); border-radius: var(--radius); padding: var(--pad-card-sm); }
.asg-card h3 { font-size: 15px; font-weight: 600; color: var(--w-ink); }
.asg-meta { font-size: 11px; color: var(--w-ink-3); margin-top: 3px; }
.asg-prompt { font-size: 13.5px; color: var(--w-ink-2); margin-top: 8px; line-height: 1.5; }
/* #J — the Create-assignment form (the reachable authoring entry) */
.asg-new { margin-top: 18px; padding: 16px 18px; background: var(--w-card); border: var(--border-weight) solid var(--w-line); border-radius: var(--radius); display: grid; gap: 12px; max-width: 640px; }
.asg-new .ws-h3 { font-size: 15px; font-weight: 700; color: var(--w-ink); margin: 0; }
.asg-f { display: grid; gap: 5px; }
.asg-f > span { font-size: 12.5px; font-weight: 600; color: var(--w-ink-2); }
.asg-f .q { font-weight: 400; color: var(--w-ink-3); }
.asg-f input, .asg-f textarea, .asg-f select { width: 100%; font: inherit; font-size: 14px; color: var(--w-ink); background: var(--w-bg, #fff); border: 1px solid var(--w-line); border-radius: 9px; padding: 9px 11px; }
.asg-f input:focus-visible, .asg-f textarea:focus-visible, .asg-f select:focus-visible { outline: 2px solid var(--c-coral); outline-offset: 1px; }
.asg-f textarea { resize: vertical; line-height: 1.5; }
.asg-f-row { grid-template-columns: auto 1fr; align-items: center; gap: 12px; }
.asg-f-row select { max-width: 280px; }
.asg-actions { display: flex; align-items: center; gap: 14px; }
.asg-msg { font-size: 13px; color: var(--w-ink-3); }

/* ── ASSESSMENT (0027) — the instructor GRADES tab: gradebook + grade dialog ── */
/* The table scrolls horizontally inside its own container; the page never overflows. */
.gb-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--w-line); border-radius: var(--radius); }
.gb-table { border-collapse: collapse; font-size: 13px; min-width: 100%; }
.gb-table th, .gb-table td { padding: 0; }
.gb-table thead th { text-align: left; font-size: 11px; font-weight: 600; color: var(--w-ink-3); background: var(--w-card);
  padding: 10px 13px; border-bottom: 1px solid var(--w-line); white-space: nowrap; position: sticky; top: 0; z-index: 1; }
.gb-corner { position: sticky; left: 0; z-index: 2 !important; background: var(--w-card) !important; min-width: 150px; }
.gb-col { max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
.gb-col-tot, .gb-tot { background: var(--bg-2); }
.gb-name { position: sticky; left: 0; z-index: 1; background: var(--w-card); border-right: 1px solid var(--w-line);
  padding: 9px 13px !important; border-bottom: 1px solid var(--w-line); min-width: 150px; }
.gb-cell { min-height: 44px; height: 44px; padding: 6px 13px !important; border-bottom: 1px solid var(--w-line);
  border-left: 1px solid var(--w-line); color: var(--w-ink-2); white-space: nowrap; font-weight: 600; }
.gb-table tbody tr:last-child .gb-cell, .gb-table tbody tr:last-child .gb-name { border-bottom: 0; }
.gb-tot { font-weight: 700; color: var(--w-ink); }
.gb-not-started { color: var(--w-ink-3); font-weight: 500; }
.gb-submitted { color: var(--w-ink-2); }
.gb-graded { color: var(--c-deep); }
.gb-empty { color: var(--w-ink-4); font-weight: 500; }
.gb-awaiting { color: var(--c-text); }
.gb-clickable { cursor: pointer; color: var(--c-text); text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 3px; }
.gb-clickable:hover { background: var(--c-tint); }
@media (hover: hover) and (pointer: fine) { .gb-clickable:focus-visible { outline: 2px solid var(--c-line); outline-offset: -2px; } }
.gb-pill { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: var(--c-tint); color: var(--c-text); }

/* the grade-an-open-response dialog (self-contained; scales from center) */
.gb-veil { position: fixed; inset: 0; background: rgba(20, 28, 48, .46); z-index: 8000; display: none;
  align-items: center; justify-content: center; padding: 22px; opacity: 0; transition: opacity 200ms var(--ease-out);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.gb-veil.show { display: flex; opacity: 1; }
.gb-modal { background: var(--w-card); border: 1px solid var(--w-line); border-radius: var(--radius-xl); box-shadow: var(--shadow-3);
  width: min(560px, 100%); max-height: 88vh; overflow-y: auto; transform: translateY(12px) scale(.985);
  transition: transform 240ms var(--ease-out); transform-origin: center; }
.gb-veil.show .gb-modal { transform: none; }
@media (prefers-reduced-motion: reduce) { .gb-modal, .gb-veil { transition: none; } }
.gb-modal-pad { padding: 22px; }
.gb-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 22px 12px; border-bottom: 1px solid var(--w-line); }
.gb-modal-head h3 { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); margin: 0; }
.gb-modal-x { width: 34px; height: 34px; min-width: 34px; border-radius: 10px; border: 1px solid var(--w-line);
  background: var(--w-card); color: var(--w-ink-3); cursor: pointer; display: grid; place-items: center; font-size: 18px;
  line-height: 1; padding: 0; }
.gb-modal-x:hover { color: var(--c-text); border-color: var(--c-line); background: var(--c-tint); }
.gb-modal-body { padding: 16px 22px 6px; }
.gb-modal-sub { font-size: 14px; color: var(--w-ink-2); margin: 0 0 14px; }
.gb-modal-sub strong { color: var(--w-ink); }
.gb-resp-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 18px; }
.gb-resp { border: 1px solid var(--w-line); border-radius: var(--radius); background: var(--bg-2); padding: 12px 14px; }
.gb-resp-q { font-size: 13px; font-weight: 700; color: var(--w-ink); margin-bottom: 6px; line-height: 1.4; }
.gb-resp-a { font-size: 14px; color: var(--w-ink-2); line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.gb-grade-row { margin-bottom: 14px; }
.gb-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.gb-field > span { font-size: 12.5px; font-weight: 600; color: var(--w-ink-2); }
.gb-field > span em { font-style: normal; color: var(--w-ink-3); font-weight: 500; }
.gb-score-wrap { display: flex; align-items: center; gap: 9px; }
.gb-score-wrap input { width: 110px; }
.gb-outof { font-size: 14px; color: var(--w-ink-3); }
.gb-field input[type="number"], .gb-field textarea { font-family: var(--font); font-size: 16px; padding: 10px 12px;
  border: 1px solid var(--w-line-2); border-radius: var(--radius-sm); background: var(--w-card); color: var(--w-ink); }
.gb-field textarea { resize: vertical; min-height: 64px; line-height: 1.5; }
.gb-field input:focus, .gb-field textarea:focus { outline: none; border-color: var(--c-line); box-shadow: 0 0 0 3px var(--c-wash); }
.gb-err { font-size: 12.5px; font-weight: 600; color: var(--c-text); background: var(--c-tint); border: 1px solid var(--c-line);
  border-radius: var(--radius-sm); padding: 9px 12px; display: none; }
.gb-err.show { display: block; }
.gb-modal-foot { display: flex; gap: 11px; flex-wrap: wrap; padding: 14px 22px 20px; }
.gb-modal-foot .btn-coral, .gb-modal-foot .btn-ghost-coral { min-height: 44px; }

/* content tab (the "Course path" tab) */
.content-ctl { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.ed-pick { font-size: 13.5px; font-weight: 600; color: var(--w-ink-2); display: flex; align-items: center; gap: 9px; }
.ed-pick select { font-family: var(--font); font-size: 14px; padding: 7px 11px; border: 1px solid var(--w-line-2); border-radius: 8px; background: var(--w-card); color: var(--w-ink); }
.ch-pick summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--c-text); padding: 8px 0; }
/* C-fix: the module list is now shown EXPANDED (no collapsed <details>). The
   .is-open block carries a small heading + the grid inline, so it is immediately
   clear what the course path covers. */
.ch-pick.is-open { margin-top: 4px; }
.ch-pick-h { font-family: var(--font); font-size: 15px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0 0 4px; }
.ch-pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 6px 16px; max-height: 360px; overflow: auto; padding: 10px 2px; }
.cc-check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--w-ink-2); cursor: pointer; }
.cc-check input { width: 15px; height: 15px; accent-color: var(--c-coral); }

/* ── P3 — the Course-path tab's read-only ASSIGNED-PACK summary (groups → modules). ── */
.ws-path-summary { margin-top: 8px; }
.ws-path-card { border: var(--border-weight) solid var(--w-line); border-radius: var(--radius-lg); background: var(--w-card); padding: var(--pad-card) var(--pad-card) 8px; }
.ws-path-card-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--w-line); }
.ws-path-card-title { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); overflow-wrap: anywhere; }
.ws-path-card-meta { font-size: 11.5px; color: var(--w-ink-3); white-space: nowrap; }
.ws-path-group { margin-bottom: 16px; }
.ws-path-group:last-child { margin-bottom: 6px; }
.ws-path-group-h { font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--c-text); margin: 0 0 8px; }
.ws-path-mod { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border: 1px solid var(--w-line);
  border-radius: var(--radius-sm); background: var(--w-page); margin-bottom: 6px; }
.ws-path-mod-n { flex: none; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; color: var(--c-deep); background: var(--c-tint); border: 1px solid var(--c-line);
  border-radius: 7px; }
.ws-path-mod-t { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; color: var(--w-ink); overflow-wrap: anywhere; }
.ws-path-mod-els { flex: none; display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
.ws-path-el { font-family: var(--font-mono); font-size: 9.5px; font-weight: 600; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--w-ink-3); background: var(--w-card); border: 1px solid var(--w-line);
  border-radius: 999px; padding: 3px 8px; white-space: nowrap; }
.ws-path-empty { text-align: center; padding: 40px 24px; background: var(--w-card); border: 1px dashed var(--w-line-2);
  border-radius: 14px; margin-top: 14px; }
.ws-path-empty h3 { font-size: 17px; font-weight: 700; color: var(--w-ink); margin: 0 0 8px; }
.ws-path-empty p { font-size: 14px; color: var(--w-ink-3); line-height: 1.55; max-width: 46ch; margin: 0 auto 18px; }
.ws-path-empty .btn-coral { min-height: 44px; display: inline-flex; align-items: center; }
.ws-path-mod > *, .ws-path-card-h > * { min-width: 0; }
@media (max-width: 640px) {
  .ws-path-card { padding: 15px 14px 6px; }
  /* On a phone, drop the element badges below the title so the row never overflows. */
  .ws-path-mod { flex-wrap: wrap; }
  .ws-path-mod-els { width: 100%; justify-content: flex-start; padding-left: 32px; }
}

/* reports tab */
.rep-bars { display: grid; gap: 10px; }
.rep-row { display: grid; grid-template-columns: 1.4fr 2fr auto; gap: 14px; align-items: center; }
.rep-label { font-size: 13.5px; color: var(--w-ink); }
.rep-bar { position: relative; height: 12px; background: var(--w-line); border-radius: 99px; overflow: hidden; }
.rep-bar i { position: absolute; left: 0; top: 0; height: 100%; background: var(--hm-1); border-radius: 99px; }
.rep-bar b { position: absolute; left: 0; top: 0; height: 100%; background: var(--c-coral); border-radius: 99px; }
.rep-meta { font-size: 11.5px; color: var(--w-ink-3); white-space: nowrap; }

/* create-course card */
.create-card { margin-top: 18px; }
.cc-head-row { display: flex; align-items: center; justify-content: space-between; }
/* The builder "×" close. The glyph is ~14px wide, below the 24px tap-target floor on desktop (it only had
   a mobile 44px enlargement). Give it a >=24px square hit area with the glyph centered, on desktop too;
   coral neutrals + the compact inline look are unchanged. The mobile rule still grows it to 44px. */
.cc-x { background: none; border: 0; font-size: 24px; color: var(--w-ink-3); cursor: pointer; line-height: 1;
  min-width: 24px; min-height: 24px; display: inline-flex; align-items: center; justify-content: center; }
.cc-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 14px 0; }
.cc-field { display: flex; flex-direction: column; gap: 5px; }
.cc-field span { font-size: 12.5px; font-weight: 600; color: var(--w-ink-2); }
.cc-field input, .cc-field select { font-family: var(--font); font-size: 14.5px; padding: 9px 12px;
  border: var(--border-weight) solid var(--w-line-2); border-radius: var(--radius-sm); background: var(--w-card); color: var(--w-ink); }
.cc-field input:focus, .cc-field select:focus { outline: none; border-color: var(--c-coral); box-shadow: 0 0 0 3px var(--c-tint); }
.cc-pack-block { margin: 18px 0; }
.cc-presets { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.cc-preset { display: flex; flex-direction: column; gap: 5px; text-align: left; padding: 14px; cursor: pointer;
  background: var(--w-card); border: var(--border-weight) solid var(--w-line-2); border-radius: var(--radius-sm); }
.cc-preset:hover:not(:disabled) { border-color: var(--c-coral); }
.cc-preset[aria-pressed="true"] { border-color: var(--c-coral); background: var(--c-tint); box-shadow: inset 0 0 0 1px var(--c-coral); }
.cc-preset:disabled { opacity: 0.55; cursor: not-allowed; }
.cc-p-name { font-weight: 700; font-size: 15px; color: var(--w-ink); }
.cc-p-price { font-size: 15px; font-weight: 600; color: var(--c-text); }
.cc-p-soon { font-size: 10px; text-transform: uppercase; color: var(--w-ink-3); }
.cc-p-meta { font-size: 10.5px; color: var(--w-ink-3); }
.cc-chosen { margin-top: 12px; font-size: 13.5px; color: var(--w-ink-2); }
.cc-chosen b { color: var(--c-text); }
.cc-success { margin-top: 16px; padding: 18px; background: var(--c-tint); border: 1px solid var(--c-coral); border-radius: var(--radius); }
.cc-success h3 { font-size: 16px; font-weight: 700; color: var(--w-ink); margin-bottom: 8px; }
.cc-success-code { display: block; font-size: 22px; font-weight: 700; letter-spacing: 0.18em; color: var(--c-text); margin: 6px 0 10px; }

/* ── Courseware tiles (warm) ── */
.cw-tiles { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.cw-tile { position: relative; display: flex; flex-direction: column; background: var(--w-card);
  border: var(--border-weight) solid var(--w-line); border-radius: var(--radius); padding: var(--pad-card-sm); box-shadow: var(--w-shadow);
  color: inherit; text-decoration: none; cursor: pointer;
  transition: border-color 150ms var(--ease), box-shadow 150ms var(--ease), transform 150ms var(--ease); }
a.cw-tile:hover { border-color: var(--c-coral); box-shadow: var(--w-shadow-lift); transform: translateY(-2px); text-decoration: none; }
@media (prefers-reduced-motion: reduce) { a.cw-tile:hover { transform: none; } }
.cw-tile:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.cw-tile.is-planned { background: var(--w-locked); border-style: dashed; box-shadow: none; cursor: default; }
.cw-tile-top { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.cw-tile-icon { width: 36px; height: 36px; flex: none; border-radius: var(--radius-sm); display: flex; align-items: center;
  justify-content: center; color: var(--c-deep); background: var(--c-tint); border: 1px solid var(--w-line); }
.cw-tile-icon svg { width: 18px; height: 18px; }
.cw-tile-heading { flex: 1; min-width: 0; }
.cw-tile-title { font-size: 15px; font-weight: 600; color: var(--w-ink); letter-spacing: -0.01em; }
.cw-tile-meta { font-size: 10px; color: var(--w-ink-3); margin-top: 3px; }
.cw-tile-blurb { font-size: 13px; line-height: 1.5; color: var(--w-ink-2); margin-bottom: 11px; flex: 1; }
.cw-tile-foot { display: flex; align-items: center; gap: 10px; margin-top: auto; }
.cw-pill { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 10px;
  font-weight: 600; padding: 3px 8px; border-radius: 6px; border: 1px solid; }
.cw-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.cw-pill.available { color: var(--c-text); border-color: var(--c-coral); background: var(--w-card); }
.cw-pill.wip { color: var(--w-ink-2); border-color: var(--w-line-2); background: var(--w-locked); }
.cw-pill.planned { color: var(--w-ink-3); border-color: var(--w-line); background: var(--w-locked); }
.cw-arrow { margin-left: auto; color: var(--c-deep); display: flex; align-items: center; transition: transform 150ms var(--ease); }
a.cw-tile:hover .cw-arrow { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { a.cw-tile:hover .cw-arrow { transform: none; } }
.cw-course-head { font-family: var(--font); font-size: 17px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); margin: 14px 0 10px; }
.cw-group { margin-bottom: 26px; }
.cw-group-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  padding-bottom: 9px; margin-bottom: 12px; border-bottom: 1px solid var(--w-line); }
.cw-eyebrow { font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--c-text); margin-bottom: 5px; }
.cw-group-head h3 { font-family: var(--font); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); }
.cw-group-blurb { font-size: 12.5px; color: var(--w-ink-2); max-width: 62ch; margin-top: 3px; }
.cw-count { flex: none; font-family: var(--font-mono); font-size: 11.5px; color: var(--w-ink-3);
  background: var(--w-card); border: 1px solid var(--w-line); border-radius: 999px; padding: 4px 11px; white-space: nowrap; }
.cw-count b { color: var(--c-text); }
.empty-cw { text-align: center; padding: 32px 20px; background: var(--w-card); border: 1px dashed var(--w-lock-border); border-radius: 13px; }
.empty-cw p { font-size: 14px; color: var(--w-ink-2); margin-bottom: 16px; max-width: 46ch; margin-left: auto; margin-right: auto; }

/* ════════════════════════════════════════════════════════════════════════
   MOBILE (≤640px)
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  .dash-head h1 { font-size: 24px; }
  .hero-card { gap: 16px; padding: 16px 16px 16px 20px; }
  .hero-title { font-size: 19px; }
  .hero-resume { width: 100%; }
  /* The V2 journey is a vertical list, so it just needs a tighter card pad on a
     phone — no per-width geometry tuning (the winding ladder is gone). */
  .journey-wrap { padding: 18px 14px 20px; }
  .journey::before { left: 23px; }
  .jcover { width: 48px; }
  .jbody { padding: 11px 12px; gap: 10px; }
  .jbar { min-width: 70px; }
  .momentum { padding: 18px 14px; gap: 8px; }
  .mom-n { font-size: 24px; }
  .mom-l { font-size: 11px; }
  .sec-card-grid { grid-template-columns: 1fr; }
  .cc-fields { grid-template-columns: 1fr; }
  .ws-head h1 { font-size: 24px; }
  .ws-tabs { gap: 0; }
  .ws-tab { padding: 10px 12px; font-size: 13.5px; }
  /* The join-code box takes its OWN full-width row so the code stays on one line
     (its 0.16em tracking can't fit beside Copy/Rotate/Invite on a phone); the
     action buttons wrap below it and each grow to fill, ≥44px tall + tappable. */
  .join-row { gap: 10px; }
  .join-code-box { flex: 1 1 100%; min-width: 0; align-items: flex-start; }
  .join-code { letter-spacing: 0.12em; }
  .join-row .btn-coral, .join-row .btn-ghost-coral { flex: 1 1 auto; min-height: 44px; }
  .rep-row { grid-template-columns: 1fr; gap: 5px; }
  .rep-meta { white-space: normal; }
  .cw-tiles { grid-template-columns: 1fr; }
  .card { padding: var(--pad-card-sm); border-radius: var(--radius-lg); }
  /* Gradebook on a phone: the table scrolls inside .gb-scroll (no page overflow);
     tighten the cells + let the sticky name column keep a usable width. The CSV
     button grows to a full-width ≥44px tap target in the header row. */
  .gb-table { font-size: 12.5px; }
  .gb-corner, .gb-name { min-width: 120px; }
  .gb-col { max-width: 150px; }
  .ws-h2-row #gb-csv { flex: 1 1 100%; min-height: 44px; }
  .gb-veil { padding: 0; align-items: flex-end; }
  .gb-modal { width: 100%; max-height: 92dvh; border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    padding-bottom: env(safe-area-inset-bottom); }
}

/* Narrow phones: keep the journey row legible — tighten the cover tile + bar so
   the title column keeps real width, and let the meta line wrap below the title
   if it must. No horizontal scroll at 390/360/320: the row is a flex card that
   shrinks to the column, the title wraps between whole words. */
@media (max-width: 430px) {
  .journey-wrap { padding: 16px 12px 18px; }
  .jcover { width: 44px; }
  .jcover .jnum { font-size: 14px; }
  .jtitle { font-size: 13.5px; }
  /* On the narrowest rows the bar + chevron can crowd a 2-line title; let the body
     stack the meta under the title so nothing collides. */
  .jbody { flex-wrap: wrap; }
  .jmeta { flex: 1 1 100%; }
}
@media (max-width: 360px) {
  .jcover { width: 40px; }
  .jbody { padding: 10px 11px; gap: 8px; }
  .jtitle { font-size: 13px; }
}

/* ════════════════════════════════════════════════════════════════════════
   MOBILE TAP TARGETS (WCAG 2.5.5) — coarse pointers / phone widths.
   Several controls render below the 28px hand-tap floor on a phone: the
   content-tab + builder-palette chapter checkboxes (15px), the create-a-course
   assignments toggle (16px), and the two drill/builder close "×" glyphs
   (~13-14px wide). They can't grow on desktop without disturbing the dense
   layouts, so we enlarge ONLY on touch/narrow widths. Each fix is written to its
   CLASS so it covers every instance of that control, present and future.
   The markup for the palette/toggle/close lives in app.js (not ours to edit), so
   these style the existing classes by hand; the attribute-qualified selectors
   (specificity 0,2,1) outrank app.js's injected <style> rules (0,1,1) and win
   regardless of source order.
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px), (pointer: coarse) {
  /* Checkbox controls: pad the LABEL row to a >=44px hit area and enlarge the box
     itself to 28px, so both the visible control AND its tappable surface clear the
     floor. The native checkbox stays centered in the padded row. */
  .cc-check { min-height: 44px; padding: 6px 4px; }
  .cc-check input[type="checkbox"] { width: 28px; height: 28px; flex: none; }

  /* Builder palette rows (.cc-pal-row) + the assignments toggle (.cc-toggle-row),
     both authored in app.js's injected style. The rows already have padding; we
     bump the box to 28px and floor the row height to 44px so the whole row taps. */
  .cc-pal-row { min-height: 44px; }
  .cc-pal-row input[type="checkbox"] { width: 28px; height: 28px; }
  .cc-toggle-row input[type="checkbox"] { width: 28px; height: 28px; flex: none; }

  /* Close "×" buttons: the drill close, the create-course close, and the builder
     selected-item remove. Give each a >=44px square hit area with the glyph centered;
     desktop keeps the compact inline glyph. */
  .drill-x, .cc-x, .cc-sel-x {
    min-width: 44px; min-height: 44px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* The drill header lays out as space-between; keep the enlarged button from pushing
     the title by letting it sit flush to the right edge. */
  .drill-head .drill-x { margin: -10px -10px -10px 0; }
  .cc-head-row .cc-x { margin: -8px -8px -8px 0; }
}

/* ════════════════════════════════════════════════════════════════════════
   MOBILE FIX PASS 2026-05-30 — three reported defects + the global floors.
   (MOBILE-UX-RESEARCH-2026-05-30.md: scroll-shadow cues, 44px targets,
   overflow-x:clip floors, min-width:0 on flex children.) dashboard.css loads
   AFTER platform.css and styles ONLY the /app surface, so these overrides win
   on ties without touching the auth pages or any desktop layout.
   ════════════════════════════════════════════════════════════════════════ */

/* ── DEFECT 2 — the /app TOP NAV clipped the Settings gear + "View site" past the
   390px edge. platform.css already makes .nav-right a horizontal scroll strip at
   <=640px, but with NO scroll cue it reads as "broken / cut off". Add a right-edge
   FADE so a partially-hidden trailing item reads as "scroll for more", keep a small
   right gutter so the last item is never flush-clipped, and floor every nav control
   (the gear + Sign out) to a 44px tap height. Desktop (>640px) is untouched. */
@media (max-width: 640px) {
  .navbar .nav-right {
    /* the fade mask signals "more here"; it only bites once the strip overflows. */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
    /* a hair of trailing room so the final item never sits flush against the clip. */
    padding-right: 22px;
    scroll-padding-right: 22px;
  }
  /* every trailing nav control reads as a real tap target (gear + Sign out + links). */
  .navbar .nav-right > .nav-link,
  .navbar .nav-right > .btn,
  .navbar .nav-right > a {
    min-height: 44px; display: inline-flex; align-items: center;
  }
}

/* ── DEFECT 3 — the instructor workspace TAB STRIP (.ws-tabs) is already an
   overflow-x:auto scroll strip, but it (a) had NO scroll cue, so the 5th tab
   ("Reports") was undiscoverable and the active tab truncated to "Re", and
   (b) tabs were ~39px tall, under the 44px floor. Add a right-edge fade cue and
   floor the tab height. The active-tab scrollIntoView lives in dashboard.js (NOT
   ours to edit) and is noted as a follow-up. Desktop is unchanged (the fade only
   bites on overflow; the height floor is harmless on a wide bar). */
@media (max-width: 760px) {
  .ws-tabs {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
    scroll-padding-inline: 8px;
  }
  .ws-tab {
    min-height: 44px; display: inline-flex; align-items: center;
  }
}

/* ── TAP-TARGET PASS 2026-06-01 — the /app TOPBAR + DASHBOARD controls below the
   WCAG 2.5.8 / Apple-HIG 44px floor on a phone (QA-swarm finding). Three named
   controls render under 44px tall on mobile and several siblings sit just under:
     • the dashboard-view tabs (.dv-tab — Tabbed/One-page/Sub-nav section tabs) ≈40px
     • the "View ▾" layout picker trigger (.dv-pick-trigger) ≈40px
     • the inline "Resume reading" CTA (.btn-coral / its .sm form .ov-resume) ≈34px
     • the docked account pill in the /app header (.cc-acct[data-dock=header]) ≈36px
   Each is floored to ≥44px ONLY on a phone / coarse pointer; the visual compactness
   is kept (the extra height is padding-vacuum around vertically-centred content, the
   existing pattern up-thread). All use TOKENS (no hardcoded colour), so the floor
   holds in every skin × tone. Desktop (>640px, fine pointer) is byte-unchanged.
   Written to each CLASS so it covers every instance, present + future. */
@media (max-width: 640px), (pointer: coarse) {
  /* The dashboard-view section tabs + the layout-picker trigger → ≥44px. They are
     already inline-flex with centred content, so only the floor changes (the pill /
     button keeps its look; the scroll strip + active state are untouched). */
  .dv-tab { min-height: 44px; }
  .dv-pick-trigger { min-height: 44px; }
  /* the layout-picker popover rows (42px → 44px) — the menu items the trigger opens. */
  .dv-pick-row { min-height: 44px; }

  /* The inline primary CTA — incl. the dashboard "Resume reading" (.ov-resume is a
     .btn-coral.sm at 34px; the hero .hero-resume is a .btn-coral at 40px). Floor the
     base + the .sm variant so both clear 44px; content stays vertically centred so
     the visual padding/size is unchanged, only the hit area grows. Ghost twins match
     so a coral+ghost pair stays the same height in a row. */
  .btn-coral, .btn-ghost-coral { min-height: 44px; }
  .btn-coral.sm, .btn-ghost-coral.sm { min-height: 44px; }

  /* The DOCKED account pill in the /app top header (#acct-dock / .header-right). It
     is account-menu.js's .cc-acct[data-dock=header] .cc-acct-btn, pinned to 34px there
     to match the BOOK reader's depth/edition control row. In /app the dock holds ONLY
     the pill (no sibling control row — app.html: "exactly one .cc-acct"), so growing it
     to 44px misaligns nothing. Scoping under the #acct-dock ID (specificity 1,3,0)
     decisively outranks account-menu.js's injected (0,3,0) rule regardless of source
     order, and #acct-dock exists ONLY in /app — so the R2 reader's docked pill (which
     does not even load this file) keeps its intentional 34px compact dock. The avatar
     stays its compact size; the extra height is centred padding-vacuum, not a bigger
     visual pill. */
  #acct-dock .cc-acct[data-dock=header] .cc-acct-btn { min-height: 44px; }
}

/* ── DEFECT 5 — GLOBAL MOBILE FLOORS (preventative). Conservative + /app-scoped
   so they can't fight an existing layout: clip any stray horizontal overflow at
   the page root (clip, not hidden, so it never becomes a touch-scroll container),
   cap replaced media to the column, and stop the known overflow-prone flex/grid
   children from refusing to shrink (flex/grid items default to min-width:auto).
   These mirror the research baseline but are written narrowly to /app primitives
   we own here, not a blanket * selector. */
html, body { overflow-x: clip; }
.app, .app-main, .dash, .dash-wrap, .workspace, .ws-wrap { overflow-x: clip; }
img, svg, canvas, video { max-width: 100%; }
/* min-width:0 lets these known flex/grid rows shrink below their content instead
   of forcing a sideways scroll (the #1 silent overflow source on a phone). */
.hero-card, .jbody, .jrow, .ws-h2-row, .join-row, .sec-card-grid > *,
.cw-tiles > *, .behind-rail > *, .navbar .nav-right > * { min-width: 0; }

/* ════════════════════════════════════════════════════════════════════════════
   STAGE B IA PAGES — Explore (#explore) · My Journeys/Coursepacks (#journeys) ·
   My Courses (#courses). V2 design system (Plus Jakarta via inherit, coral family,
   cool ink, Emil easing). Built MOBILE-SAFE: intrinsic grids collapse to 1 column,
   inputs ≥16px (no iOS zoom), tap targets ≥44px, no horizontal overflow, dropdowns/
   overlays don't clip. Animate transform+opacity only; reduced-motion settles.
   ════════════════════════════════════════════════════════════════════════════ */

/* Wave J — the whole-book price anchor in the Explore body (non-full users only). */
.iax-pricehint { margin: -6px 0 18px; font-size: 13.5px; line-height: 1.5; color: var(--w-ink-2); }
.iax-pricehint strong { color: var(--c-text); font-weight: 700; }  /* --c-text (#a8472a) is AA on the default light bg; --c-deep #B8553A was 4.49:1 (a hair under). Dark tones relighten --c-text. */

/* #O — the getting-started checklist on the teach home (Wave O onboarding) */
.gs-checklist { margin: 0 0 22px; padding: 18px 20px; background: var(--w-card); border: var(--border-weight) solid var(--w-line); border-radius: var(--radius-lg); }
.gs-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.gs-eyebrow { font-family: var(--font-mono, monospace); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--c-deep); margin: 0 0 3px; }
.gs-h { font-family: var(--font); font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--w-ink); margin: 0; }
.gs-x { flex: none; background: none; border: 0; font-size: 20px; line-height: 1; color: var(--w-ink-3); cursor: pointer; padding: 0 4px; border-radius: 8px; }
.gs-x:hover { color: var(--w-ink); }
.gs-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.gs-step { display: flex; align-items: center; gap: 13px; padding: 11px 13px; border-radius: var(--radius); border: 1px solid var(--w-line); background: var(--w-bg, #fff); }
.gs-step.is-next { border-color: var(--c-line); background: var(--c-tint); }
.gs-step.is-todo { opacity: 0.72; }
.gs-mark { flex: none; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; font-family: var(--font-mono, monospace); color: var(--w-ink-3); background: var(--w-tint, #f1f3f7); border: 1px solid var(--w-line); }
.gs-step.is-next .gs-mark { color: #fff; background: var(--c-coral); border-color: var(--c-coral); }
.gs-step.is-done .gs-mark { color: #fff; background: var(--c-deep); border-color: var(--c-deep); }
.gs-step.is-done .gs-mark svg { width: 15px; height: 15px; }
.gs-tx { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.gs-tx b { font-size: 14px; font-weight: 600; color: var(--w-ink); }
.gs-step.is-done .gs-tx b { color: var(--w-ink-2); }
.gs-tx span { font-size: 12.5px; color: var(--w-ink-3); line-height: 1.4; }
.gs-cta { flex: none; padding: 7px 14px; font-size: 13px; }
@media (max-width: 560px) { .gs-step { flex-wrap: wrap; } .gs-cta { width: 100%; margin-top: 6px; } }

/* The "open the textbook" affordance at the top of Explore (the book is never hidden). */
.iax-bookrow { display: flex; align-items: center; gap: 14px; margin: 0 0 22px; padding: 14px 16px;
  border-radius: var(--radius-lg); background: var(--c-tint); border: 1px solid var(--c-line);
  text-decoration: none; color: var(--w-ink);
  transition: transform 150ms var(--ease-out), box-shadow 150ms var(--ease-out); }
.iax-bookrow:hover { text-decoration: none; box-shadow: var(--shadow-2); }
.iax-bookrow:active { transform: scale(0.992); }
.iax-bookrow-ic { flex: none; width: 42px; height: 42px; border-radius: var(--radius-sm); background: var(--w-card);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-bookrow-ic svg { width: 22px; height: 22px; }
.iax-bookrow-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.iax-bookrow-tx b { font-size: 15px; font-weight: 700; color: var(--w-ink); letter-spacing: -0.01em; }
.iax-bookrow-tx span { font-size: 12.5px; color: var(--w-ink-3); line-height: 1.45; }
.iax-bookrow-arrow { flex: none; color: var(--c-text); display: flex; }

/* Tabs (Explore: Full library | Videos). */
.iax-tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--w-line); margin: 0 0 18px; flex-wrap: wrap; }
.iax-tab { font-family: inherit; font-size: 14.5px; font-weight: 600; color: var(--w-ink-3); cursor: pointer;
  background: transparent; border: 0; border-bottom: 2.5px solid transparent; padding: 10px 4px; margin-right: 14px;
  min-height: 44px; display: inline-flex; align-items: center; gap: 8px;
  transition: color 130ms var(--ease-out), border-color 130ms var(--ease-out); }
.iax-tab:hover { color: var(--w-ink); }
.iax-tab.on { color: var(--c-text); border-bottom-color: var(--c-deep); }
.iax-tab-n { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-4);
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: 999px; padding: 2px 8px; line-height: 1.3; }
.iax-tab.on .iax-tab-n { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); }
.iax-pane-lead { font-size: 13.5px; color: var(--w-ink-3); margin: 0 0 16px; line-height: 1.5; }

/* Search + filter chips. Input ≥16px (no iOS zoom); chips wrap, ≥36px tall but tappable. */
.iax-tools { display: flex; flex-direction: column; gap: 12px; margin: 0 0 18px; }
.iax-search { display: flex; align-items: center; gap: 9px; padding: 0 14px; background: var(--w-card);
  border: var(--border-weight) solid var(--w-line-2); border-radius: var(--radius); min-height: 46px;
  transition: border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out); }
.iax-search:focus-within { border-color: var(--c-line); box-shadow: 0 0 0 3px var(--c-tint); }
.iax-search svg { flex: none; width: 18px; height: 18px; color: var(--w-ink-4); }
.iax-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font-family: inherit;
  font-size: 16px; color: var(--w-ink); padding: 11px 0; }
.iax-search input::placeholder { color: var(--w-ink-4); }
.iax-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.iax-chip { font-family: inherit; font-size: 13px; font-weight: 600; color: var(--w-ink-2); cursor: pointer;
  background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: 999px; padding: 8px 15px;
  min-height: 38px; text-transform: capitalize;
  transition: background 130ms var(--ease-out), color 130ms var(--ease-out), border-color 130ms var(--ease-out); }
.iax-chip:hover { border-color: var(--c-line); color: var(--c-text); }
.iax-chip.on { background: var(--c-tint); color: var(--c-text); border-color: var(--c-line); }

/* The card grid: intrinsic auto-fit so it collapses to one column on a phone (never overflows). */
.iax-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); }
.iax-cgrid, .iax-jgrid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
.iax-empty-inline { grid-column: 1 / -1; color: var(--w-ink-3); font-size: 14px; padding: 20px 4px; }

/* The base V2 card + the stagger-in entrance (opacity + translateY; settles on .iax-in). */
.iax-card { background: var(--w-card); border: 1px solid var(--w-line); border-radius: var(--radius-lg);
  overflow: hidden; min-width: 0; display: flex; flex-direction: column; text-decoration: none; color: var(--w-ink);
  opacity: 0; transform: translateY(8px);
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out),
    box-shadow 160ms var(--ease-out), border-color 160ms var(--ease-out); }
.iax-card.iax-in { opacity: 1; transform: none; }
.iax-card:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .iax-card[role="button"]:hover, a.iax-card:hover { box-shadow: var(--shadow-2); border-color: var(--c-line); transform: translateY(-2px); }
}
[role="button"].iax-card, a.iax-card { cursor: pointer; }
.iax-card[role="button"]:active, a.iax-card:active { transform: scale(0.992); }

/* The module/video card cover — reuses the composer's flat coral themes (t-coral/t-ink/t-slate/t-soft). */
.iax-cover { position: relative; height: 92px; padding: 12px 14px; display: flex; flex-direction: column;
  justify-content: space-between; overflow: hidden; }
.iax-cover.t-coral { background: var(--c-deep); color: #fff; }
.iax-cover.t-ink { background: var(--cover-2); color: #fff; }
.iax-cover.t-slate { background: var(--cover-1); color: #fff; }
.iax-cover.t-soft { background: var(--c-tint2); color: var(--c-text); }
.iax-motif { position: absolute; inset: 0; pointer-events: none; }
.iax-motif svg { width: 100%; height: 100%; display: block; }
.iax-cover-top { position: relative; display: flex; align-items: center; justify-content: space-between; z-index: 1; }
.iax-cover-num { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; opacity: 0.92; }
.iax-cover-ico svg, .iax-lock svg { width: 16px; height: 16px; opacity: 0.92; }
.iax-cover-title { position: relative; z-index: 1; font-size: 15px; font-weight: 700; letter-spacing: -0.01em;
  line-height: 1.22; max-height: 2.5em; overflow: hidden; }
.iax-card.is-locked .iax-cover { filter: saturate(0.7); }

.iax-body { padding: 13px 14px 14px; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.iax-blurb { font-size: 12.8px; color: var(--w-ink-2); line-height: 1.5; margin: 0;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.iax-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.iax-els { display: flex; gap: 7px; flex-wrap: wrap; }
.iax-el { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: 10px;
  font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; color: var(--w-ink-3);
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: 999px; padding: 3px 9px; }
.iax-el svg { width: 11px; height: 11px; }
.iax-el.soon { opacity: 0.6; }
.iax-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: auto; }
.iax-foot-open { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 700;
  color: var(--c-text); white-space: nowrap; }
.iax-foot-lock { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--w-ink-4); display: inline-flex; align-items: center; gap: 5px; }

/* Video card: a play badge centered on the cover. */
.iax-vid .iax-cover { height: 110px; align-items: center; justify-content: center; }
.iax-vid-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 1; color: #fff; }
.iax-vid .iax-cover-top { position: absolute; top: 12px; left: 14px; right: 14px; }
.iax-vid .iax-cover-title { position: absolute; bottom: 12px; left: 14px; right: 14px; }

/* ── The coverage popup overlay (Explore module → coverage + read/unlock). Modal scales from center;
      scrim dims; body scroll-locked while open (set in JS). Mobile: a bottom-anchored sheet. ── */
.iax-overlay { position: fixed; inset: 0; z-index: 220; display: none; align-items: center; justify-content: center;
  padding: 24px; }
.iax-overlay.show { display: flex; }
.iax-veil { position: absolute; inset: 0; background: rgba(20,28,48,0.42); opacity: 0;
  transition: opacity 200ms var(--ease-out); }
.iax-overlay.show .iax-veil { opacity: 1; }
.iax-modal { position: relative; z-index: 1; width: 100%; max-width: 480px; max-height: 86vh; overflow-y: auto;
  background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3); transform: scale(0.96) translateY(8px); opacity: 0; transform-origin: center;
  transition: opacity 200ms var(--ease-out), transform 220ms var(--ease-out); }
.iax-overlay.show .iax-modal { transform: none; opacity: 1; }
.iax-modal-x { position: absolute; top: 10px; right: 10px; z-index: 2; width: 36px; height: 36px; border: 0;
  border-radius: 999px; background: var(--w-card); border: 1px solid var(--w-line); color: var(--w-ink-2); font-size: 22px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center; }
.iax-modal-x:hover { background: var(--w-card); color: var(--w-ink); }
.iax-modal-cover { position: relative; height: 116px; padding: 16px 18px; display: flex; flex-direction: column;
  justify-content: flex-end; overflow: hidden; }
.iax-modal-cover.t-coral { background: var(--c-deep); color: #fff; }
.iax-modal-cover.t-ink { background: var(--cover-2); color: #fff; }
.iax-modal-cover.t-slate { background: var(--cover-1); color: #fff; }
.iax-modal-cover.t-soft { background: var(--c-tint2); color: var(--c-text); }
.iax-modal-cover h3 { position: relative; z-index: 1; font-size: 20px; font-weight: 700; letter-spacing: -0.02em; margin: 4px 0 0; }
.iax-modal-mid { position: relative; z-index: 1; font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase; opacity: 0.9; }
.iax-modal-body { padding: 18px; }
.iax-modal-body h5 { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--c-text); margin: 18px 0 9px; }
.iax-modal-body h5:first-child { margin-top: 0; }
.iax-cov { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 8px; font-size: 13.5px; color: var(--w-ink-2); line-height: 1.45; }
.iax-ck { flex: none; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; color: var(--c-deep); margin-top: 1px; }
.iax-ck svg { width: 16px; height: 16px; }
.iax-tagrow { display: flex; gap: 6px; flex-wrap: wrap; }
.iax-modal-foot { display: flex; gap: 10px; padding: 0 18px 18px; flex-wrap: wrap; }
.iax-modal-foot .btn-coral, .iax-modal-foot .btn-ghost-coral { flex: 1 1 auto; min-height: 44px; justify-content: center; }

/* ── The OVERVIEW popup's ELEMENT list (Reading / Video, with type + meta; Assignment / Quiz greyed). Each
      row: a type icon, the element title + a meta line (duration / depth / "in development"), and a type
      chip on the right. A reserved (in-dev) type is greyed via .iax-elrow.soon. ── */
.iax-ellist { display: flex; flex-direction: column; gap: 8px; margin: 0 0 4px; }
.iax-elrow { display: flex; align-items: center; gap: 11px; min-height: 48px; padding: 9px 12px;
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: var(--radius-sm); min-width: 0; }
.iax-elrow-ic { flex: none; width: 30px; height: 30px; border-radius: var(--radius-xs); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-elrow-ic svg { width: 16px; height: 16px; }
.iax-elrow-tx { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.iax-elrow-tx b { font-size: 13.5px; font-weight: 600; color: var(--w-ink); line-height: 1.3; overflow-wrap: anywhere; }
.iax-elrow-meta { font-family: var(--font-mono); font-size: 11px; color: var(--w-ink-3); }
.iax-elrow-type { flex: none; font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--c-text); background: var(--c-tint); border: 1px solid var(--c-line);
  border-radius: 999px; padding: 3px 9px; }
/* in-development / reserved element → greyed, neutral chip (no coral claim), but still legible (AA). */
.iax-elrow.soon { opacity: 0.72; }
.iax-elrow.soon .iax-elrow-ic { background: var(--w-page); border-color: var(--w-line); color: var(--w-ink-3); }
.iax-elrow.soon .iax-elrow-type { color: var(--w-ink-3); background: var(--w-page); border-color: var(--w-line); }
/* The overlap / coverage note under the element list. */
.iax-modal-note { font-size: 12.5px; color: var(--w-ink-3); line-height: 1.55; margin: 12px 0 0;
  overflow-wrap: anywhere; }
/* The duration chip on a Videos-tab card cover. */
.iax-vid-dur { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.03em;
  background: rgba(0,0,0,0.28); color: #fff; border-radius: 999px; padding: 2px 8px; }

/* ════════ §4 + §5 — THE MODULE-PROGRESS POPUP (Felipe 2026-06-01) ════════
   A DISTINCT dashboard popup (vs Explore's iaxModulePopup): the module's PROGRESS + per-element STATUS +
   a "why complete?" explainer + a Mark-as-unread/Reset control + Open-in-bookshelf. It rides the shared
   .iax-overlay/.iax-modal shell but uses its own .mpp-* markup so it reads as a different component. All
   coral-family tokens (coral-deep #B8553A for the done ✓ / progress fill); AA, ≥44px controls, mobile-safe. */
.mpp-body { padding: 18px; }
.mpp-h5 { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--c-text); margin: 16px 0 9px; }
/* PROGRESS — the module's own % bar. */
.mpp-prog { margin: 0 0 4px; }
.mpp-prog-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0 0 7px; }
.mpp-prog-label { color: var(--w-ink-4); }
.mpp-prog-frac { font-size: 12.5px; font-weight: 700; color: var(--c-deep); white-space: nowrap; }
.mpp-prog-bar { height: 8px; border-radius: 999px; background: var(--c-tint); overflow: hidden; }
.mpp-prog-bar > i { display: block; height: 100%; border-radius: 999px; background: var(--c-deep);
  transition: width 320ms var(--ease-out, cubic-bezier(0.22,1,0.36,1)); }
/* COMPLETE banner + the Mark-as-unread / Reset control. */
.mpp-complete { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 14px 0 0;
  padding: 11px 13px; border-radius: var(--radius-sm); background: var(--c-tint2, var(--c-tint));
  border: 1px solid var(--c-line); }
.mpp-complete-ic { flex: none; width: 26px; height: 26px; border-radius: 999px; background: var(--c-deep);
  color: #fff; display: flex; align-items: center; justify-content: center; }
.mpp-complete-ic svg { width: 15px; height: 15px; }
.mpp-complete-tx { flex: 1; min-width: 140px; font-size: 13px; line-height: 1.4; color: var(--w-ink-2); }
.mpp-complete-tx b { color: var(--w-ink); font-weight: 700; }
.mpp-complete .mpp-reset { flex: none; min-height: 36px; }
.mpp-reset-err { flex: 1 1 100%; font-size: 12px; color: var(--c-deep); margin: 4px 0 0; }
/* The ELEMENT status list — a row per element with a type icon, title + type, and a STATUS pill. */
.mpp-ellist { display: flex; flex-direction: column; gap: 8px; margin: 0 0 4px; }
.mpp-empty { font-size: 13px; color: var(--w-ink-3); margin: 0; }
.mpp-elrow { display: flex; align-items: center; gap: 11px; min-height: 48px; padding: 9px 12px;
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: var(--radius-sm); min-width: 0; }
.mpp-elrow-ic { flex: none; width: 30px; height: 30px; border-radius: var(--radius-xs); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.mpp-elrow-ic svg { width: 16px; height: 16px; }
.mpp-elrow-tx { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.mpp-elrow-tx b { font-size: 13.5px; font-weight: 600; color: var(--w-ink); line-height: 1.3; overflow-wrap: anywhere; }
.mpp-elrow-type { font-family: var(--font-mono); font-size: 10.5px; color: var(--w-ink-4); letter-spacing: 0.04em; }
.mpp-elrow-status { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  font-weight: 700; letter-spacing: 0.02em; white-space: nowrap; }
.mpp-elrow-status svg { width: 13px; height: 13px; }
.mpp-elrow.is-done .mpp-elrow-status { color: var(--c-deep); }
.mpp-elrow.is-todo .mpp-elrow-status { color: var(--w-ink-3); }
.mpp-elrow.is-ref .mpp-elrow-status { color: var(--w-ink-4); font-weight: 600; }
/* an in-dev row → greyed, neutral (no coral claim), still legible (AA). */
.mpp-elrow.is-dev { opacity: 0.78; }
.mpp-elrow.is-dev .mpp-elrow-ic { background: var(--w-page); border-color: var(--w-line); color: var(--w-ink-3); }
.mpp-elrow.is-dev .mpp-elrow-status { color: var(--w-ink-4); font-weight: 600; }
/* The "Why is this marked as complete?" expandable explainer (§5 — scroll-based completion, made transparent). */
.mpp-why { margin: 14px 0 0; border: 1px solid var(--w-line); border-radius: var(--radius-sm); background: var(--w-page); }
.mpp-why-sum { cursor: pointer; padding: 11px 13px; min-height: 44px; display: flex; align-items: center;
  font-size: 13px; font-weight: 600; color: var(--c-deep); list-style: none; }
.mpp-why-sum::-webkit-details-marker { display: none; }
.mpp-why-sum::after { content: "›"; margin-left: auto; font-size: 18px; line-height: 1;
  transform: rotate(90deg); transition: transform 180ms var(--ease-out, ease); color: var(--w-ink-4); }
.mpp-why[open] .mpp-why-sum::after { transform: rotate(-90deg); }
.mpp-why-body { padding: 0 13px 13px; font-size: 12.5px; line-height: 1.55; color: var(--w-ink-2); }
.mpp-why-body p { margin: 4px 0 8px; }
.mpp-why-list { margin: 0 0 8px; padding-left: 18px; }
.mpp-why-list li { margin: 0 0 5px; }
.mpp-why-body b { color: var(--w-ink); font-weight: 700; }
.mpp-why-foot { color: var(--w-ink-3); }
@media (max-width: 640px) {
  .mpp-foot .btn-coral, .mpp-foot .btn-ghost-coral { flex: 1 1 100%; }
  .mpp-complete .mpp-reset { flex: 1 1 100%; }
}

/* ════════ §2 ELEMENT POPUP (Felipe 2026-06-01) — popup-before-bookshelf for a SPECIFIC element ════════
   Reuses the .iax-overlay/.iax-modal shell + the .mpp status colours; its own .ep-* chrome reads as the
   element popup. All theme-variable driven (every skin/tone), ≥44px controls, AA. */
.ep-body { padding: 18px; }
/* The STATUS pill (Submitted / Not started / Watched / Read …) — the same verb the module popup uses. */
.ep-status { margin: 0 0 14px; }
.ep-status-pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700;
  letter-spacing: 0.02em; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--w-line);
  background: var(--w-page); color: var(--w-ink-3); white-space: nowrap; }
.ep-status-pill svg { width: 13px; height: 13px; }
.ep-status.is-done .ep-status-pill { color: var(--c-deep); background: var(--c-tint); border-color: var(--c-line); }
.ep-status.is-todo .ep-status-pill { color: var(--w-ink-3); }
.ep-status.is-dev .ep-status-pill { color: var(--w-ink-4); }
/* The facts grid — type · length/time · due. Each fact is a labelled k/v pair, wrapping cleanly on narrow. */
.ep-facts { display: flex; flex-wrap: wrap; gap: 8px 10px; margin: 0 0 14px; }
.ep-fact { display: flex; flex-direction: column; gap: 1px; min-width: 0; padding: 8px 12px;
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: var(--radius-sm); flex: 1 1 auto; }
.ep-fact-k { font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--w-ink-4); }
.ep-fact-v { font-size: 13px; font-weight: 600; color: var(--w-ink); overflow-wrap: anywhere; }
.ep-fact-v.is-overdue { color: var(--c-deep); }
/* The completion-criterion line (scroll-to-end / submit / watch) — quiet, beneath the facts. */
.ep-crit { font-size: 12.5px; color: var(--w-ink-3); line-height: 1.5; margin: 0 0 12px; }
/* The "what opens" explainer — a small icon tile + the plain sentence. */
.ep-explain { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; line-height: 1.5;
  color: var(--w-ink-2); margin: 0; padding: 12px 13px; background: var(--c-tint);
  border: 1px solid var(--c-line); border-radius: var(--radius-sm); }
.ep-explain-ic { flex: none; display: inline-flex; color: var(--c-deep); margin-top: 1px; }
.ep-explain-ic svg { width: 17px; height: 17px; }
.ep-dev { font-size: 12.5px; color: var(--w-ink-3); line-height: 1.5; margin: 12px 0 0; }
.ep-foot { display: flex; gap: 10px; padding: 0 18px 18px; flex-wrap: wrap; }
.ep-foot .btn-coral, .ep-foot .btn-ghost-coral { flex: 1 1 auto; min-height: 44px; justify-content: center; }
@media (max-width: 640px) {
  .ep-foot .btn-coral, .ep-foot .btn-ghost-coral { flex: 1 1 100%; }
}

/* ════════ §3B — THE RIGHT-SIDE NOTES DRAWER + its topbar TOGGLE (Felipe 2026-06-01) ════════
   A slide-in panel on the RIGHT listing all the user's highlights/notes in order; click a note to jump to it
   in the reader. Closed by default, opens on the topbar "Notes" toggle. Theme-variable driven (every skin/
   tone), ≥44px controls, AA. Mobile = a full-height drawer pinned to the right edge (near-full-width). */

/* The topbar TOGGLE — a quiet ghost control beside the account pill. Pressed state when the drawer is open. */
.cc-notes-toggle { display: inline-flex; align-items: center; gap: 7px; min-height: 40px; padding: 7px 13px;
  margin-right: 10px; border: 1px solid var(--border, #e6ebf1); border-radius: 999px; background: var(--bg, #fff);
  color: var(--ink-2, #44484f); font-family: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  white-space: nowrap; transition: background 150ms ease, color 150ms ease, border-color 150ms ease; }
.cc-notes-toggle svg { flex: none; }
.cc-notes-toggle:hover { color: var(--coral-text, #a8472a); border-color: var(--coral-line, #f0d6cb);
  background: var(--coral-tint, #fdf3ee); }
.cc-notes-toggle:focus-visible { outline: 2px solid var(--coral-deep, #B8553A); outline-offset: 2px; }
.cc-notes-toggle.is-open { color: var(--coral-text, #a8472a); border-color: var(--coral-line, #f0d6cb);
  background: var(--coral-tint, #fdf3ee); }
@media (max-width: 760px) {
  .cc-notes-toggle { min-width: 44px; min-height: 44px; justify-content: center; padding: 8px 11px; }
  .cc-notes-toggle .cc-notes-toggle-label { display: none; }  /* icon-only on narrow phones (≥44px target) */
}

/* The drawer shell — fixed, full-height, over everything; a scrim dims the page behind. */
.ndr-wrap { position: fixed; inset: 0; z-index: 260; }
.ndr-wrap[hidden] { display: none; }
.ndr-scrim { position: absolute; inset: 0; background: rgba(20, 22, 28, 0.34); opacity: 0;
  transition: opacity 220ms var(--ease-out, ease); }
.ndr-wrap.show .ndr-scrim { opacity: 1; }
.ndr-panel { position: absolute; top: 0; right: 0; bottom: 0; width: 380px; max-width: 92vw; display: flex;
  flex-direction: column; background: var(--w-card, #fff); border-left: 1px solid var(--w-line, #e6ebf1);
  box-shadow: -18px 0 48px rgba(20, 22, 28, 0.14); transform: translateX(100%);
  transition: transform 240ms var(--ease-out, cubic-bezier(.22,.61,.36,1)); }
.ndr-wrap.show .ndr-panel { transform: translateX(0); }
.ndr-panel:focus { outline: none; }
.ndr-head { flex: none; display: flex; align-items: flex-start; gap: 12px; padding: 18px 18px 14px;
  border-bottom: 1px solid var(--w-line, #e6ebf1); }
.ndr-head-tx { flex: 1; min-width: 0; }
.ndr-title { font-size: 17px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink, #1a1d24); margin: 0; }
.ndr-count { display: block; font-size: 11.5px; font-weight: 600; color: var(--w-ink-4, #8a909a); margin-top: 2px; }
.ndr-x { flex: none; width: 40px; height: 40px; min-height: 40px; border: 0; border-radius: 9px;
  background: transparent; color: var(--w-ink-3, #6b7280); cursor: pointer; display: flex; align-items: center;
  justify-content: center; }
.ndr-x:hover { background: var(--w-page, #f6f7f9); color: var(--w-ink, #1a1d24); }
.ndr-x:focus-visible { outline: 2px solid var(--coral-deep, #B8553A); outline-offset: 2px; }
.ndr-body { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 14px 8px; -webkit-overflow-scrolling: touch; }
.ndr-loading { color: var(--w-ink-3, #6b7280); font-size: 13px; padding: 18px 4px; }
.ndr-course { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--w-ink-4, #8a909a); margin: 14px 4px 6px; }
.ndr-ch { margin: 0 0 14px; }
.ndr-ch-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 7px;
  padding: 0 4px; }
.ndr-ch-title { font-size: 13px; font-weight: 700; color: var(--w-ink, #1a1d24); letter-spacing: -0.01em;
  overflow-wrap: anywhere; }
.ndr-ch-n { flex: none; font-size: 10.5px; font-weight: 700; color: var(--c-deep, #B8553A);
  background: var(--c-tint, #fdf3ee); border-radius: 999px; padding: 1px 7px; }
/* A note row = a JUMP button (the whole card is clickable → reader at that chapter). */
.ndr-note { display: block; width: 100%; text-align: left; min-height: 44px; padding: 11px 12px; margin: 0 0 8px;
  border: 1px solid var(--w-line, #e6ebf1); border-radius: var(--radius-sm, 10px); background: var(--w-page, #f8f9fb);
  cursor: pointer; font-family: inherit; transition: border-color 150ms ease, background 150ms ease, box-shadow 150ms ease; }
.ndr-note:hover { border-color: var(--c-line, #f0d6cb); background: var(--w-card, #fff); box-shadow: var(--w-shadow, 0 2px 10px rgba(20,22,28,.06)); }
.ndr-note:focus-visible { outline: 2px solid var(--coral-deep, #B8553A); outline-offset: 2px; }
.ndr-note-q { display: block; font-size: 13px; line-height: 1.45; color: var(--w-ink, #1a1d24);
  border-left: 3px solid var(--c-deep, #B8553A); padding-left: 9px; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.ndr-note-n { display: block; font-size: 12.5px; line-height: 1.45; color: var(--w-ink-2, #44484f); margin-top: 6px;
  overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ndr-note-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; }
.ndr-note-date { font-size: 11px; color: var(--w-ink-4, #8a909a); }
.ndr-note-go { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 700;
  color: var(--c-deep, #B8553A); margin-left: auto; }
.ndr-note-go svg { width: 13px; height: 13px; }
.ndr-empty { text-align: center; padding: 32px 18px; color: var(--w-ink-3, #6b7280); }
.ndr-empty-ic { width: 40px; height: 40px; margin: 0 auto 10px; color: var(--w-ink-4, #8a909a); }
.ndr-empty-ic svg { width: 40px; height: 40px; }
.ndr-empty b { color: var(--w-ink, #1a1d24); }
.ndr-empty-sub { font-size: 12.5px; line-height: 1.5; margin: 6px 0 0; }
.ndr-foot { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--w-line, #e6ebf1); }
.ndr-foot .ndr-hub { width: 100%; min-height: 44px; display: inline-flex; align-items: center;
  justify-content: center; gap: 6px; }
@media (max-width: 560px) {
  /* Full-height drawer near-full-width on a phone (a right-anchored sheet). */
  .ndr-panel { width: 100%; max-width: 100vw; border-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ndr-scrim, .ndr-panel { transition: none; }
}

/* ════════ MY-NOTES HUB SHELL — multi-mode learning hub (Notes · Canvas · Export) (Felipe 2026-06-01) ════════
   One surface (#notes) with a segmented MODE SWITCH at the top + a persistent left RAIL beside the stage. All
   theme-variable driven (every skin/tone), ≥44px controls, AA. Mobile: the rail collapses ABOVE the stage
   (the canvas drops to view/pan there); the mode switch stays a full-width segmented row. */

/* The MODE SWITCH — a segmented control (tablist). The active segment is a coral-tinted raised pill. */
.hub-modeswitch { display: inline-flex; gap: 4px; padding: 4px; margin: 4px 0 18px; border-radius: var(--radius);
  background: var(--w-page); border: 1px solid var(--w-line); max-width: 100%; flex-wrap: wrap; }
.hub-mode-btn { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 18px;
  border: 0; border-radius: calc(var(--radius) - 3px); background: transparent; cursor: pointer; font-family: var(--font);
  font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink-3); white-space: nowrap;
  transition: background 150ms var(--ease-out), color 150ms var(--ease-out), box-shadow 150ms var(--ease-out); }
.hub-mode-btn .hub-mode-ic { display: inline-flex; }
.hub-mode-btn .hub-mode-ic svg { width: 16px; height: 16px; }
.hub-mode-btn:hover { color: var(--w-ink); }
.hub-mode-btn.on { background: var(--w-card); color: var(--c-text); box-shadow: var(--w-shadow); }
.hub-mode-btn:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }

/* The SHELL: rail | stage. The rail is a sticky side panel; the stage fills the rest. */
.hub-shell { display: grid; grid-template-columns: 264px minmax(0, 1fr); gap: 22px; align-items: start; }
.hub-rail { position: sticky; top: 12px; min-width: 0; padding: 6px; border: 1px solid var(--w-line);
  border-radius: var(--radius-lg); background: var(--w-card); max-height: calc(100vh - 120px); overflow-y: auto;
  -webkit-overflow-scrolling: touch; }
.hub-stage { min-width: 0; }
.hub-rail-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 9px 10px 7px; }
.hub-rail-head-2 { margin-top: 8px; border-top: 1px solid var(--w-line); padding-top: 12px; }
.hub-rail-title { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--w-ink-4); }
.hub-rail-n { font-size: 11px; font-weight: 700; color: var(--c-deep); background: var(--c-tint);
  border: 1px solid var(--c-line); border-radius: 999px; padding: 1px 8px; }
.hub-rail-list { display: flex; flex-direction: column; gap: 2px; }
.hub-rail-course { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--w-ink-4); padding: 8px 10px 4px; }
.hub-rail-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%;
  min-height: 44px; padding: 9px 11px; border: 0; border-radius: 10px; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 13.5px; font-weight: 600; color: var(--w-ink-2); text-align: left;
  transition: background 130ms var(--ease-out), color 130ms var(--ease-out); }
.hub-rail-item:hover { background: var(--w-page); color: var(--w-ink); }
.hub-rail-item.on { background: var(--c-tint); color: var(--c-text); }
.hub-rail-item:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.hub-rail-lab { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-rail-c { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-4);
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: 999px; padding: 1px 7px; }
.hub-rail-item.on .hub-rail-c { color: var(--c-text); background: var(--c-tint2, var(--c-tint)); border-color: var(--c-line); }
.hub-rail-empty { font-size: 12.5px; line-height: 1.5; color: var(--w-ink-3); padding: 10px 11px 14px; margin: 0; }
.hub-rail-note { font-size: 12.5px; line-height: 1.5; color: var(--w-ink-3); padding: 6px 11px 12px; margin: 0; }
.hub-rail-note .btn-ghost-coral { margin-top: 8px; }
/* Open-source credit (MIT acknowledgment for the Excalidraw/React canvas). Quiet, set off by a hairline. */
.hub-rail-credit { font-size: 11.5px; line-height: 1.5; color: var(--w-ink-3); padding: 10px 11px 4px;
  margin: 8px 0 0; border-top: 1px solid var(--w-line, var(--c-line)); }
.hub-rail-credit a { color: var(--coral-deep, #B8553A); text-decoration: underline; }
.hub-rail-credit a:hover { text-decoration: none; }
/* Add-a-chapter-note composer (My Notes hub) — a collapsed dashed button that expands to a chapter picker + textarea. */
.notes-add { margin: 0 0 14px; }
.notes-add-toggle { display: inline-flex; align-items: center; gap: 7px; border: 1.5px dashed var(--border-strong, #d9d1c4);
  background: transparent; color: var(--coral-deep, #B8553A); font-weight: 700; font-size: 13.5px; border-radius: 10px;
  padding: 10px 14px; cursor: pointer; min-height: 40px; }
.notes-add-toggle:hover { background: var(--c-tint, #fbeee7); border-color: var(--coral-deep, #B8553A); }
.notes-add-form { margin-top: 10px; border: 1px solid var(--border-strong, #d9d1c4); border-radius: 12px; padding: 12px;
  background: var(--w-page, #fff); max-width: 560px; }
.notes-add-lab { display: block; font-size: 12px; font-weight: 700; color: var(--ink-2, #5f574c); margin: 0 0 6px; }
.notes-add-ch { width: 100%; box-sizing: border-box; margin: 0 0 8px; border: 1px solid var(--border-strong, #d9d1c4);
  border-radius: 8px; padding: 8px 10px; font-size: 13.5px; background: #fff; color: var(--ink, #1c1a17); min-height: 40px; }
.notes-add-text { width: 100%; box-sizing: border-box; min-height: 70px; resize: vertical;
  border: 1px solid var(--border-strong, #d9d1c4); border-radius: 8px; padding: 9px 11px;
  font: 400 14px/1.5 inherit; color: var(--ink, #1c1a17); background: #fff; }
.notes-add-actions { display: flex; align-items: center; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.notes-add-msg { font-size: 12px; color: var(--ink-3, #8b8276); }
/* Live mic level meter (voice notes) — bars drawn by an AnalyserNode while recording. */
.hub-audio-meter { display: block; width: 100%; max-width: 480px; height: 48px; margin: 8px auto 0; border-radius: 9px;
  background: var(--c-tint, #fbeee7); border: 1px solid var(--c-line, #e8e2d8); }
.hub-audio-meter[hidden] { display: none; }
.hub-rail-flash { font-size: 12.5px; line-height: 1.45; color: var(--c-text); background: var(--c-tint);
  border: 1px solid var(--c-line); border-radius: 8px; padding: 8px 10px; margin: 2px 4px 8px; }

/* New-board button (in the Boards rail head). */
.hub-newboard { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 7px 11px;
  border: 1px solid var(--c-line); border-radius: 9px; background: var(--c-tint); color: var(--c-text);
  cursor: pointer; font-family: var(--font); font-size: 12.5px; font-weight: 700; white-space: nowrap;
  transition: background 130ms var(--ease-out), border-color 130ms var(--ease-out); }
.hub-newboard:hover { background: var(--c-tint2, var(--c-tint)); border-color: var(--c-deep); }
.hub-newboard:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.hub-newboard.loading { opacity: 0.6; pointer-events: none; }

/* The HIGHLIGHTS drag-source (Canvas rail) — each card is draggable; a "+ to canvas" button is the no-drag path. */
.hub-hi-list { display: flex; flex-direction: column; gap: 7px; padding: 2px 6px 8px; }
.hub-hi { padding: 9px 10px; border: 1px solid var(--w-line); border-radius: 10px; background: var(--w-page);
  cursor: grab; transition: border-color 130ms var(--ease-out), box-shadow 130ms var(--ease-out); }
.hub-hi:hover { border-color: var(--c-line); box-shadow: var(--w-shadow); }
.hub-hi.is-dragging { opacity: 0.5; cursor: grabbing; }
.hub-hi-q { display: block; font-size: 12.5px; line-height: 1.45; color: var(--w-ink); border-left: 3px solid var(--c-deep);
  padding-left: 8px; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.hub-hi-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 7px; }
.hub-hi-ch { font-size: 11px; color: var(--w-ink-4); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-hi-add { flex: none; min-height: 30px; padding: 5px 9px; border: 1px solid var(--c-line); border-radius: 8px;
  background: var(--w-card); color: var(--c-deep); cursor: pointer; font-family: var(--font); font-size: 11.5px; font-weight: 700; }
.hub-hi-add:hover { background: var(--c-tint); }
.hub-hi-add:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }

/* The CANVAS stage: the mount fills it; a drop-target ring appears while dragging a highlight over it. */
.hub-canvas-mount { width: 100%; min-height: 560px; height: 64vh; border: 1px solid var(--w-line);
  border-radius: var(--radius-lg); background: var(--w-card); overflow: hidden; }
.hub-stage.is-drop { outline: 2px dashed var(--c-deep); outline-offset: 4px; border-radius: var(--radius-lg); }
.hub-canvas-empty { text-align: center; padding: 48px 24px; border: 1px dashed var(--w-line-2, var(--w-line));
  border-radius: var(--radius-lg); background: var(--w-card); }
.hub-canvas-empty .iax-empty-ic { width: 44px; height: 44px; margin: 0 auto 12px; color: var(--c-deep); }
.hub-canvas-empty .iax-empty-ic svg { width: 44px; height: 44px; }
.hub-canvas-empty h3 { font-size: 18px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink); margin: 0 0 6px; }
.hub-canvas-empty p { font-size: 13.5px; line-height: 1.55; color: var(--w-ink-2); margin: 0 auto 16px; max-width: 46ch; }

/* EXPORT stage: two cards (notes study sheet + board image). */
.hub-export { display: flex; flex-direction: column; gap: 16px; max-width: 640px; }
.hub-exp-card { padding: 18px 20px; border: 1px solid var(--w-line); border-radius: var(--radius-lg); background: var(--w-card); }
.hub-exp-card h3 { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; color: var(--w-ink); margin: 0 0 4px; }
.hub-exp-sub { font-size: 13px; line-height: 1.5; color: var(--w-ink-2); margin: 0 0 14px; }
.hub-exp-row { display: flex; gap: 10px; flex-wrap: wrap; }
.hub-exp-row .btn-coral, .hub-exp-row .btn-ghost-coral { min-height: 44px; }
.hub-exp-msg { font-size: 12.5px; color: var(--c-deep); margin: 10px 0 0; }

/* SCHEDULE stage (§SCHEDULE) — the chronological buckets of every due-dated assignment/quiz across the
   user's journeys. Hairline-separated rows, a coral-deep "overdue" word (SOFT — no lock), a mono date token,
   and a coral "Open" button reusing the in-shell scoped reader. Matches the Assignments&grades row language. */
.hub-schedule { display: flex; flex-direction: column; gap: 22px; max-width: 720px; }
.sch-bucket { display: flex; flex-direction: column; }
.sch-bucket-head { display: flex; align-items: baseline; gap: 9px; margin: 0 0 4px; }
.sch-bucket-h { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  font-family: var(--font-mono); color: var(--w-ink-4, #646d82); margin: 0; }
.sch-bucket-h.is-overdue { color: var(--c-deep, #B8553A); }
.sch-bucket-n { font-size: 11px; font-weight: 700; color: var(--c-deep, #B8553A); background: var(--c-tint, #fcefe9);
  border: 1px solid var(--c-line, rgba(218,119,86,.26)); border-radius: 999px; padding: 1px 8px; }
.sch-rows { display: flex; flex-direction: column; }
.sch-row { display: flex; align-items: center; gap: 12px; padding: 12px 4px;
  border-top: 1px solid var(--w-line, #e7ebf0); min-width: 0; }
.sch-row:first-child { border-top: 0; }
.sch-ic { flex: none; width: 22px; height: 22px; color: var(--c-text, #a8472a); }
.sch-ic svg { width: 22px; height: 22px; }
.sch-row.is-overdue .sch-ic { color: var(--c-deep, #B8553A); }
.sch-main { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
.sch-title { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink, #1a1f2e);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sch-meta { font-size: 11px; font-weight: 600; color: var(--w-ink-4, #646d82); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sch-dot { color: var(--w-ink-4, #646d82); }
.sch-due { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  color: var(--c-text, #a8472a); white-space: nowrap; }
.sch-due.is-overdue { color: var(--c-deep, #B8553A); font-weight: 700; }
.sch-action { flex: none; }
.sch-action .btn-coral { min-height: 36px; }
.sch-na { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-4, #646d82); }
.sch-ics { margin-top: 8px; }
@media (max-width: 640px) {
  .sch-row { flex-wrap: wrap; }
  .sch-due { order: 3; }
  .sch-action { order: 4; margin-left: auto; }
}

/* ════════ CANVAS ACTION TOOLBAR — note-specific conveniences above an open board ════════ */
/* Small themed buttons that wire to ccHubCanvas (seed/connect/frame). Sits ABOVE the mount so it never
   overlaps Excalidraw's own toolbar. Wraps on a phone; each button ≥36px tall, AA, focus-visible. */
.hub-canvas-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; }
.hub-cbtn { display: inline-flex; align-items: center; gap: 7px; min-height: 38px; padding: 7px 13px;
  border: 1px solid var(--c-line); border-radius: 10px; background: var(--w-card); color: var(--c-text);
  cursor: pointer; font-family: var(--font); font-size: 13px; font-weight: 700; letter-spacing: -0.01em;
  white-space: nowrap; transition: background 130ms var(--ease-out), border-color 130ms var(--ease-out); }
.hub-cbtn svg { flex: none; color: var(--c-deep); }
.hub-cbtn:hover:not(:disabled) { background: var(--c-tint); border-color: var(--c-deep); }
.hub-cbtn:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.hub-cbtn:disabled { opacity: 0.5; cursor: default; }
.hub-cbtn-seed { background: var(--c-tint); }
.hub-cbtn-seed:hover:not(:disabled) { background: var(--c-tint2, var(--c-tint)); }
.hub-canvas-bar-msg { font-size: 12.5px; font-weight: 600; color: var(--c-deep); padding-left: 2px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* ════════ AUDIO (voice notes) — record panel + transcript cards ════════ */
.hub-audio { display: flex; flex-direction: column; gap: 20px; }
.hub-audio-panel { border: 1px solid var(--w-line); border-radius: var(--radius-lg); background: var(--w-card);
  padding: 20px; display: flex; flex-direction: column; gap: 14px; }
/* The chapter the voice note attaches to. */
.hub-audio-chsel { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hub-audio-chsel-lab { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--w-ink-4); }
.hub-audio-chapter { min-height: 40px; padding: 8px 12px; border: 1px solid var(--w-line); border-radius: 10px;
  background: var(--w-page); color: var(--w-ink); font-family: var(--font); font-size: 13.5px; font-weight: 600;
  max-width: 100%; cursor: pointer; }
.hub-audio-chapter:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
/* The record/stop control: a circular mic button (≥56px) + a timer + a one-line hint. */
.hub-audio-controls { display: flex; align-items: center; gap: 16px; }
.hub-audio-btn { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  flex: none; width: 84px; min-height: 84px; padding: 8px; border: 1px solid var(--c-line); border-radius: 16px;
  background: var(--c-tint); color: var(--c-deep); cursor: pointer; font-family: var(--font); font-weight: 800;
  transition: background 140ms var(--ease-out), border-color 140ms var(--ease-out), transform 140ms var(--ease-out); }
.hub-audio-btn:hover:not(:disabled) { background: var(--c-tint2, var(--c-tint)); border-color: var(--c-deep); }
.hub-audio-btn:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 3px; }
.hub-audio-btn:disabled { cursor: default; opacity: 0.85; }
.hub-audio-btn-ic { display: inline-flex; }
.hub-audio-btn-lab { font-size: 12.5px; letter-spacing: -0.01em; }
/* Recording state: a solid coral button with a soft pulse so it's unmistakably live. */
.hub-audio-panel.is-recording .hub-audio-btn { background: var(--c-deep); color: #fff; border-color: var(--c-deep);
  animation: ccAudioPulse 1.6s var(--ease-out) infinite; }
.hub-audio-panel.is-transcribing .hub-audio-btn { background: var(--w-page); color: var(--c-deep); }
@keyframes ccAudioPulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--c-line); }
  50% { box-shadow: 0 0 0 7px rgba(218, 119, 86, 0.12); }
}
.hub-audio-spin { animation: ccAudioSpin 0.9s linear infinite; }
@keyframes ccAudioSpin { to { transform: rotate(360deg); } }
.hub-audio-meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.hub-audio-timer { font-size: 22px; font-weight: 700; color: var(--w-ink-4); letter-spacing: 0.02em; }
.hub-audio-timer.on { color: var(--c-deep); }
.hub-audio-hint { font-size: 13px; line-height: 1.45; color: var(--w-ink-2); }
.hub-audio-warn { font-size: 12.5px; line-height: 1.45; color: var(--c-deep); background: var(--c-tint);
  border: 1px solid var(--c-line); border-radius: 9px; padding: 8px 11px; margin: 0; }
.hub-audio-err { font-size: 13px; line-height: 1.5; color: #B8553A; background: var(--c-tint);
  border: 1px solid var(--c-line); border-radius: 9px; padding: 9px 12px; margin: 0; }
/* The graceful states (unsupported / not-enabled) reuse the panel; centered + a quiet icon. */
.hub-audio-state { text-align: center; align-items: center; padding: 36px 24px; }
.hub-audio-state-ic { width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-lg); background: var(--c-tint); color: var(--c-deep); margin-bottom: 4px; }
.hub-audio-state-ic svg { width: 26px; height: 26px; }
.hub-audio-state h3 { font-size: 17px; font-weight: 800; letter-spacing: -0.01em; color: var(--w-ink); margin: 0; }
.hub-audio-state p { font-size: 13.5px; line-height: 1.55; color: var(--w-ink-2); margin: 0; max-width: 46ch; }
.hub-audio-state .btn-ghost-coral { min-height: 44px; margin-top: 4px; }
/* The transcript list. */
.hub-audio-list-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0 0 12px; }
.hub-audio-list-head h3 { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; color: var(--w-ink); margin: 0; }
.hub-audio-list-n { font-size: 12px; font-weight: 600; color: var(--w-ink-4); }
.hub-audio-empty { padding: 36px 24px; }
/* The native <audio> player on a voice-note card. */
.note-audio { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 10px;
  padding: 9px 11px; border: 1px solid var(--w-line); border-radius: 11px; background: var(--w-page); }
.note-audio-badge { display: inline-flex; align-items: center; gap: 6px; flex: none; font-size: 11.5px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--c-deep); }
.note-audio-badge svg { width: 14px; height: 14px; }
.note-audio-el { flex: 1 1 220px; min-width: 0; height: 38px; max-width: 100%; }
.note-audio-noaudio { font-size: 12px; color: var(--w-ink-4); font-style: italic; }
.note-card.is-flash { animation: ccNoteFlash 1.1s var(--ease-out); }
@keyframes ccNoteFlash {
  0% { box-shadow: 0 0 0 2px var(--c-deep); background: var(--c-tint); }
  100% { box-shadow: none; }
}

/* MOBILE — stack the rail above the stage; the canvas mount shrinks; the mode switch fills the row. */
@media (max-width: 760px) {
  .hub-shell { grid-template-columns: 1fr; gap: 16px; }
  .hub-rail { position: static; max-height: 320px; }
  .hub-modeswitch { display: flex; width: 100%; flex-wrap: wrap; }
  .hub-mode-btn { flex: 1 1 0; justify-content: center; padding: 8px 10px; min-width: 72px; }
  .hub-canvas-mount { min-height: 420px; height: 56vh; }
  .hub-cbtn { flex: 1 1 auto; justify-content: center; }
  .hub-cbtn span { overflow: hidden; text-overflow: ellipsis; }
  .hub-audio-controls { flex-wrap: wrap; }
}
@media (prefers-reduced-motion: reduce) {
  .hub-mode-btn, .hub-rail-item, .hub-hi, .hub-newboard, .hub-hi-add, .hub-cbtn, .hub-audio-btn { transition: none; }
  .hub-audio-panel.is-recording .hub-audio-btn, .hub-audio-spin, .note-card.is-flash { animation: none; }
}

/* ════════ WAVE E2 — Explore by ELEMENT GROUP (scrollable tab strip + element cards + Teaching Resources) ════════ */

/* The tab strip SCROLLS horizontally (many element-type groups never overflow the page). The wrapper is the
   scroll container (overflow-x:auto, clipped vertically); the strip itself is nowrap. A thin fade hints at
   more tabs off-screen. Every tab stays ≥44px (touch). The page never scrolls sideways (the wrap contains it). */
.iax-tabwrap { position: relative; margin: 0 0 18px; }
.iax-tabs-scroll { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; margin: 0; scrollbar-width: thin;
  -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; padding-bottom: 1px; }
.iax-tabs-scroll::-webkit-scrollbar { height: 5px; }
.iax-tabs-scroll::-webkit-scrollbar-thumb { background: var(--w-line-2); border-radius: 999px; }
.iax-tabs-scroll .iax-tab { flex: 0 0 auto; white-space: nowrap; scroll-snap-align: start; }

/* An ELEMENT card (an Explore element-type group lists these). Reuses the V2 card chrome; the body names the
   element + its type pill. An in-dev card is greyed + not openable; a locked card shows the lock affordance. */
.iax-el-card .iax-body { gap: 11px; }
.iax-el-card-h { margin: 0; }
.iax-el-card-t { font-size: 14px; font-weight: 700; color: var(--w-ink); line-height: 1.32; letter-spacing: -0.01em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.iax-el-card.is-dev { opacity: 0.66; }
.iax-el-card.is-dev .iax-cover { filter: saturate(0.55) brightness(0.98); }
.iax-el-card.is-dev { cursor: default; }
.iax-el-card.is-dev:active { transform: none; }

/* ── Teaching Resources (STAFF ONLY) — a visually distinct section beneath the student groups. A coral-tinted
      eyebrow + heading set it apart; its own scrollable tab strip lists the instructor-only groups. A student
      NEVER receives this block (the backend strips instructor-only elements; the JS also guards on isStaff). ── */
.iax-teach { margin: 32px 0 0; padding: 22px 20px 6px; border: 1px solid var(--c-line);
  border-radius: var(--radius-lg); background:
    linear-gradient(180deg, var(--c-tint) 0%, rgba(255,255,255,0) 120px), var(--w-card); }
.iax-teach-head { margin: 0 0 16px; }
.iax-teach-eyebrow { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--c-deep);
  background: var(--c-tint2); border: 1px solid var(--c-line); border-radius: 999px; padding: 4px 11px; }
.iax-teach-eyebrow svg { width: 13px; height: 13px; }
.iax-teach-head h2 { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; color: var(--w-ink); margin: 11px 0 6px; }
.iax-teach-head p { font-size: 13.5px; color: var(--w-ink-2); line-height: 1.55; margin: 0; max-width: 62ch; }
.iax-teach-tabs { margin-bottom: 14px; }

/* ════════════════════════════════════════════════════════════════════════
   EXPLORE MASTER SPLIT (§2, 2026-05-31) — "Courseware" vs "Teaching Resources",
   a top-level split (like the admin top-bar) ABOVE the search/View/nav controls.
   Teaching Resources is STAFF-ONLY (the button only renders for staff). Plus the
   NAVIGATION axis: the element-type nav renders as TOP TABS or a LEFT SUB-NAV rail.
   All theme-variable driven (every skin) + mobile-safe.
   ════════════════════════════════════════════════════════════════════════ */
.iax-master { display: inline-flex; gap: 4px; padding: 4px; margin: 4px 0 18px; border-radius: var(--radius);
  background: var(--w-page); border: 1px solid var(--w-line); max-width: 100%; flex-wrap: wrap; }
.iax-master-btn { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 16px;
  border: 0; border-radius: calc(var(--radius) - 3px); background: transparent; cursor: pointer; font-family: var(--font);
  font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink-3); white-space: nowrap;
  transition: background 150ms var(--ease-out), color 150ms var(--ease-out), box-shadow 150ms var(--ease-out); }
.iax-master-btn svg { width: 16px; height: 16px; }
.iax-master-btn:hover { color: var(--w-ink); }
.iax-master-btn.on { background: var(--w-card); color: var(--c-text); box-shadow: var(--w-shadow); }
.iax-master-btn:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
/* The one-line signpost above each master section's nav. */
.iax-signpost { font-size: 13px; color: var(--w-ink-3); line-height: 1.5; margin: 0 0 16px; max-width: 72ch; }
.iax-signpost-teach { display: flex; align-items: center; gap: 7px; color: var(--c-text); }
.iax-signpost-teach svg { width: 15px; height: 15px; flex: none; }
.iax-master-section[hidden] { display: none; }
/* When showing Teaching Resources, keep the distinct coral-tinted shell (reuses .iax-teach base above). */
.iax-master-section.iax-teach { margin: 4px 0 0; }

/* ── THE LEFT SUB-NAV rail (the element-type nav as a vertical list). ── */
.iax-browse-cols { display: block; }
.iax-subnav { display: none; }   /* hidden in TABS mode (the default) */
.iax-subnav-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%;
  min-height: 44px; padding: 9px 12px; border: 0; border-radius: 10px; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 14px; font-weight: 600; color: var(--w-ink-3); text-align: left;
  transition: background 130ms var(--ease-out), color 130ms var(--ease-out); }
.iax-subnav-item:hover { background: var(--w-page); color: var(--w-ink); }
.iax-subnav-item.on { background: var(--c-tint); color: var(--c-text); }
.iax-subnav-item:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.iax-subnav-lab { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iax-subnav-n { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-4);
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: 999px; padding: 1px 7px; }
.iax-subnav-item.on .iax-subnav-n { color: var(--c-text); background: var(--c-tint2); border-color: var(--c-line); }

/* NAV = TABS (default): the top tab strip shows; the sub-nav rail is hidden; columns are a single column. */
.iax-browse[data-nav="tabs"] > .iax-tabwrap { display: block; }
.iax-browse[data-nav="tabs"] .iax-subnav { display: none; }
/* NAV = SUB-NAV: hide the top tab strip; show the rail beside the panes (2-col on wide, stacked on phone). */
.iax-browse[data-nav="subnav"] > .iax-tabwrap { display: none; }
.iax-browse[data-nav="subnav"] .iax-browse-cols { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 24px; align-items: start; }
.iax-browse[data-nav="subnav"] .iax-subnav { display: flex; flex-direction: column; gap: 3px; position: sticky; top: 12px;
  padding: 4px; border: 1px solid var(--w-line); border-radius: var(--radius); background: var(--w-card); }
/* By-module mode hides BOTH the top tabs AND the sub-nav rail (it's a by-type lens); the by-module pane shows. */
.iax-browse[data-groupby="module"] .iax-subnav { display: none; }
.iax-browse[data-groupby="module"] .iax-browse-cols { display: block; }

/* ════════════════════════════════════════════════════════════════════════
   EXPLORE-VIEW (2026-05-31) — the user-chosen LAYOUT for Explore (grid / list /
   gallery), DENSITY (comfortable / compact), GROUP-BY (type / module). Mirrors the
   Dashboard view switcher; persisted as cc-explore-view. Every surface uses the
   theme variables (works in ALL themes/styles — no hardcoded colors), V2 aesthetic,
   Emil motion (<300ms, transform/opacity, reduced-motion settles), mobile-safe.
   ════════════════════════════════════════════════════════════════════════ */

/* The tools row: search on the left, the "View ▾" picker on the right (top row), chips below. */
.iax-tools-top { display: flex; align-items: center; gap: 12px; min-width: 0; }
.iax-tools-top .iax-search { flex: 1; min-width: 0; }

/* ── THE "View ▾" PICKER (an Emil popover; mirrors the dashboard .dv-pick) ── */
.xv-pick { position: relative; flex: none; }
.xv-pick-trigger { display: inline-flex; align-items: center; gap: 8px; min-height: 46px; padding: 8px 13px;
  border-radius: var(--radius); border: var(--border-weight) solid var(--w-line-2); background: var(--w-card); cursor: pointer;
  font-family: var(--font); font-size: 13.5px; font-weight: 650; color: var(--w-ink); box-shadow: var(--w-shadow);
  transition: border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out), transform 120ms var(--ease-out); }
.xv-pick-trigger:hover { border-color: var(--c-line); box-shadow: var(--w-shadow-lift); }
.xv-pick-trigger:active { transform: scale(0.985); }
.xv-pick-trigger:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.xv-pick-trigger .xv-pick-ic { display: inline-flex; color: var(--w-ink-3); }
.xv-pick-trigger .xv-pick-ic svg { width: 16px; height: 16px; }
.xv-pick-cur { white-space: nowrap; }
.xv-caret { width: 15px; height: 15px; color: var(--w-ink-4); transition: transform 200ms var(--ease-move); }
.xv-pick[data-open="true"] .xv-caret { transform: rotate(180deg); }
.xv-pick-menu { position: absolute; top: calc(100% + 8px); right: 0; min-width: 224px; max-width: calc(100vw - 24px);
  background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3, 0 18px 48px rgba(20,30,50,.16)); padding: 7px; transform-origin: top right; opacity: 0;
  transform: scale(0.97) translateY(-6px); pointer-events: none; z-index: 60;
  transition: opacity 180ms var(--ease-out), transform 200ms var(--ease-out); }
.xv-pick[data-open="true"] .xv-pick-menu { opacity: 1; transform: none; pointer-events: auto; }
.xv-pick-head { font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--w-ink-4); margin: 6px 9px 4px; }
.xv-pick-head:first-child { margin-top: 2px; }
.xv-pick-div { height: 1px; background: var(--w-line); margin: 6px 4px; }
.xv-pick-row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 42px; text-align: left;
  padding: 9px 10px; border: 0; border-radius: 10px; background: transparent; cursor: pointer; font-family: var(--font);
  font-size: 13.5px; font-weight: 600; color: var(--w-ink); transition: background 130ms var(--ease-out); }
.xv-pick-row:hover { background: var(--w-page); }
.xv-pick-row[aria-checked="true"] { background: var(--c-tint); color: var(--c-text); }
.xv-pick-row:focus-visible { outline: 2px solid var(--c-deep); outline-offset: -2px; }
.xv-pick-row .xv-pick-ic { flex: none; display: inline-flex; color: var(--w-ink-3); }
.xv-pick-row[aria-checked="true"] .xv-pick-ic { color: var(--c-deep); }
.xv-pick-row .xv-pick-ic svg { width: 16px; height: 16px; }
.xv-pick-lbl { flex: 1; min-width: 0; }
.xv-pick-ck { flex: none; width: 16px; height: 16px; color: var(--c-deep); display: inline-flex; }
.xv-pick-ck svg { width: 16px; height: 16px; }

/* ── GROUP-BY = MODULE: hide the type-tab strip (it's a by-type lens); the by-module pane shows instead. The
      doubled attribute selector raises specificity so it beats the nav=tabs "show tabwrap" rule above. ── */
.iax-browse[data-groupby="module"][data-groupby] > .iax-tabwrap { display: none; }

/* ── LAYOUT modifiers on a grid (data-layout). GRID = the default auto-fill cards. GALLERY = wider cards with
      a taller cover. LIST = a single column of compact rows (the grid becomes a flex column). ── */
.iax-grid[data-layout="gallery"] { grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: 20px; }
.iax-grid[data-layout="gallery"] .iax-cover { height: 150px; }
.iax-grid[data-layout="gallery"] .iax-cover-title { font-size: 17px; }
.iax-grid[data-layout="list"] { display: flex; flex-direction: column; gap: 8px; }

/* DENSITY = compact: tighter gaps + smaller card bodies/covers (grid + gallery); tighter rows (list). */
.iax-grid[data-density="compact"] { gap: 11px; }
.iax-grid[data-density="compact"][data-layout="grid"] { grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); }
.iax-grid[data-density="compact"] .iax-cover { height: 76px; padding: 10px 12px; }
.iax-grid[data-density="compact"] .iax-body { padding: 10px 12px 11px; gap: 7px; }
.iax-grid[data-density="compact"][data-layout="gallery"] .iax-cover { height: 124px; }
.iax-grid[data-density="compact"][data-layout="list"] { gap: 5px; }

/* ── A COMPACT LIST ROW (.iax-row) — icon + title + module/meta + coverage chip + open/locked. Dense, scannable,
      one per line; great on mobile. Reuses the .iax-el-card/.iax-mod data-attrs so JS wires it identically. ── */
.iax-row { display: flex; align-items: center; gap: 13px; min-width: 0; padding: 13px 15px; background: var(--w-card);
  border: 1px solid var(--w-line); border-radius: var(--radius); text-decoration: none; color: var(--w-ink);
  opacity: 0; transform: translateY(6px);
  transition: opacity 260ms var(--ease-out), transform 260ms var(--ease-out),
    box-shadow 150ms var(--ease-out), border-color 150ms var(--ease-out); }
.iax-row.iax-in { opacity: 1; transform: none; }
.iax-row[role="button"] { cursor: pointer; }
.iax-row:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .iax-row[role="button"]:hover { box-shadow: var(--shadow-2); border-color: var(--c-line); }
}
.iax-row[role="button"]:active { transform: scale(0.995); }
.iax-row.is-dev { opacity: 1; }
.iax-row.is-dev .iax-row-ic, .iax-row.is-dev .iax-row-title { opacity: 0.62; }
.iax-row.is-locked .iax-row-ic { opacity: 0.78; }
.iax-grid[data-density="compact"] .iax-row { padding: 9px 13px; gap: 11px; }
.iax-row-ic { flex: none; width: 34px; height: 34px; border-radius: var(--radius-sm); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-row-ic svg { width: 17px; height: 17px; }
.iax-grid[data-density="compact"] .iax-row-ic { width: 30px; height: 30px; }
.iax-grid[data-density="compact"] .iax-row-ic svg { width: 15px; height: 15px; }
.iax-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.iax-row-title { font-size: 14.5px; font-weight: 650; color: var(--w-ink); letter-spacing: -0.01em; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iax-grid[data-density="compact"] .iax-row-title { font-size: 13.5px; }
.iax-row-sub { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 12px; color: var(--w-ink-3);
  overflow: hidden; }
.iax-row-mod, .iax-row-type, .iax-row-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.iax-row-mod { font-weight: 600; color: var(--w-ink-2); flex: 0 1 auto; }
.iax-row-meta { flex: 0 1 auto; }
.iax-row-dot { flex: none; color: var(--w-ink-4); }
.iax-row-cov { flex: none; font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--w-ink-3); background: var(--w-page); border: 1px solid var(--w-line);
  border-radius: 999px; padding: 4px 10px; white-space: nowrap; }
.iax-row-open { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 700;
  color: var(--c-text); white-space: nowrap; }
.iax-row-state { flex: none; display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono);
  font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--w-ink-4); white-space: nowrap; }
.iax-row-state svg, .iax-row-open svg { width: 13px; height: 13px; }

/* ── BY-MODULE: one section per module (its head + a grid of its elements in the chosen layout). ── */
.iax-bymod-list { display: flex; flex-direction: column; gap: 22px; }
.iax-bymod-list[data-density="compact"] { gap: 15px; }
.iax-modsec { min-width: 0; }
.iax-modsec-head { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; cursor: pointer;
  background: transparent; border: 0; border-bottom: 1px solid var(--w-line); padding: 4px 2px 11px; margin: 0 0 14px;
  min-height: 44px; transition: border-color 140ms var(--ease-out); }
.iax-modsec-head:hover { border-color: var(--c-line); }
.iax-modsec-head:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; border-radius: 6px; }
.iax-modsec-ic { flex: none; width: 32px; height: 32px; border-radius: var(--radius-sm); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-modsec-ic svg { width: 16px; height: 16px; }
.iax-modsec-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.iax-modsec-cov { font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--w-ink-4); }
.iax-modsec-h { font-size: 16px; font-weight: 750; letter-spacing: -0.02em; color: var(--w-ink); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iax-modsec-n { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-3); }
.iax-modsec-lock { flex: none; display: inline-flex; color: var(--w-ink-4); }
.iax-modsec-lock svg { width: 15px; height: 15px; }

/* ════════ My Journeys / My Coursepacks ════════ */
.iax-create-row { margin: 0 0 18px; }
.iax-build, .iax-build2 { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; }
.iax-build-host:not([hidden]) { margin: 0 0 24px; }
.iax-pack { padding: 0; }
.iax-pack-top { display: flex; align-items: flex-start; gap: 12px; padding: 16px 16px 0; }
.iax-pack-ic { flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-pack-ic svg { width: 20px; height: 20px; }
.iax-pack-h { min-width: 0; flex: 1; }
.iax-pack-h h3 { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0; line-height: 1.25;
  overflow-wrap: anywhere; }
.iax-pack-meta { font-family: var(--font-mono); font-size: 11.5px; color: var(--w-ink-3); margin: 4px 0 0; }
.iax-pack-badge { display: inline-flex; align-items: center; gap: 6px; margin: 12px 16px 0; align-self: flex-start;
  font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--w-ink-3); background: var(--w-page); border: 1px solid var(--w-line); border-radius: 999px; padding: 4px 11px; }
.iax-pack-badge.assigned { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); }
.iax-pack-badge svg { width: 12px; height: 12px; }
.iax-pack-actions { display: flex; gap: 8px; flex-wrap: wrap; padding: 14px 16px 16px; margin-top: auto; }
.iax-pack-actions .btn-coral, .iax-pack-actions .btn-ghost-coral { min-height: 38px; }
/* P4 — when a pack is assigned to several courses, list their registrar names under the badge. */
.iax-pack-assignees { font-size: 12px; color: var(--w-ink-3); line-height: 1.5; margin: 6px 16px 0;
  overflow-wrap: anywhere; }

/* ── WAVE 2 PART A — "My Journeys" coupling badges (JOURNEY ↔ COURSE COUPLING). A COURSE journey (a class
   you're enrolled in / teach) wears a coral "Course" badge + the registrar identity; a PERSONAL journey
   wears a neutral "Personal" badge + the pack name. One coral, depth-only (no 2nd hue), AA. ── */
/* the CARD form (.iax-pack.iax-mj) stacks; the LIST-ROW form (.iax-mj-row) is a row (styled below). */
.iax-pack.iax-mj { display: flex; flex-direction: column; }
.iax-pack-badge.mj-course { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); }
.iax-pack-badge.mj-personal { color: var(--w-ink-3); background: var(--w-page); border-color: var(--w-line); }
.iax-pack-badge.mj-course svg { width: 12px; height: 12px; }
/* A course journey's cover icon reads as a class (the cap), tinted coral like the personal compass. */
.iax-pack.iax-mj.is-course .iax-pack-ic { color: var(--c-deep); }
/* the instructor / meeting sub-line under a course-journey card. */
.iax-mj-line { font-size: 13px; color: var(--w-ink-2); margin: 8px 16px 0; line-height: 1.45; }

/* ── MY JOURNEYS "View ▾" (2026-05-31) — a thin tools row above the grid (count + the shared .xv-pick
   popover), the CARD↔LIST layout, and the SORT. The grid is .iax-jgrid (card = grid columns; list = a stacked
   column of .iax-mj-row). Reuses the .xv-pick popover + the .iax-row primitives, so it is themed in every
   theme/style + mobile-safe by construction, matching Explore/Dashboard. ── */
.mjv-tools { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 14px; min-width: 0; }
.mjv-tools-count { flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 11.5px; font-weight: 600;
  letter-spacing: 0.04em; color: var(--w-ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* LIST layout — the journeys stack as compact rows (not a card grid). */
.iax-jgrid[data-layout="list"] { display: flex; flex-direction: column; gap: 9px; }
/* A My-Journeys LIST ROW — icon + title/sub + badge + (optional) % chip + actions, on the shared .iax-row. */
.iax-mj-row { display: flex; align-items: center; gap: 13px; min-width: 0; }
.iax-mj-row .iax-row-ic { color: var(--c-deep); }
.mjr-badge { flex: none; display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; border-radius: 999px;
  padding: 4px 10px; color: var(--w-ink-3); background: var(--w-page); border: 1px solid var(--w-line); }
.mjr-badge.mj-course { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); }
.mjr-badge svg { width: 11px; height: 11px; }
.mjr-pct { flex: none; font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: var(--c-deep);
  background: var(--c-tint); border: 1px solid var(--c-line); border-radius: 999px; padding: 3px 9px; }
.mjr-actions { flex: none; display: inline-flex; align-items: center; gap: 8px; }
.mjr-actions .btn-coral, .mjr-actions .btn-ghost-coral { min-height: 38px; }
/* On a phone the row wraps so nothing overflows 390 — the badge/pct/actions drop to a second line, full width. */
@media (max-width: 560px) {
  .iax-mj-row { flex-wrap: wrap; }
  .iax-mj-row .iax-row-main { flex: 1 1 100%; }
  .mjr-actions { margin-left: auto; }
}

/* ── P2 — Assign-to-a-course section picker (rendered in the shared .iax-overlay/.iax-modal). ── */
.iax-assign { padding: 22px 22px 18px; }
.iax-assign-head { margin: 0 0 16px; }
.iax-assign-eyebrow { font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--c-text); margin: 0 0 6px; }
.iax-assign-head h3 { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0;
  line-height: 1.25; overflow-wrap: anywhere; }
.iax-assign-lead { font-size: 13.5px; color: var(--w-ink-3); line-height: 1.55; margin: 8px 0 0; }
.iax-assign-list { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; }
.iax-assign-row { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 10px 14px;
  background: var(--w-page); border: 1px solid var(--w-line); border-radius: var(--radius); }
.iax-assign-row-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.iax-assign-row-title { font-size: 14.5px; font-weight: 600; color: var(--w-ink); overflow-wrap: anywhere; line-height: 1.3; }
.iax-assign-row-sub { font-family: var(--font-mono); font-size: 11.5px; color: var(--w-ink-3); overflow-wrap: anywhere; }
.iax-assign-row .btn-coral.sm { flex: none; min-height: 44px; }
.iax-assign-here { flex: none; display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--c-text);
  background: var(--c-tint); border: 1px solid var(--c-line); border-radius: 999px; padding: 7px 12px; }
.iax-assign-here svg { width: 13px; height: 13px; }
.iax-assign-empty { font-size: 13.5px; color: var(--w-ink-3); line-height: 1.55; margin: 0 0 16px;
  padding: 16px; background: var(--w-page); border: 1px dashed var(--w-line-2); border-radius: 12px; text-align: center; }
.iax-assign-foot { display: flex; }
.iax-assign-foot .btn-ghost-coral { flex: 1; min-height: 46px; justify-content: center; }
.iax-assign-msg { font-size: 12.5px; line-height: 1.5; margin: 12px 0 0; min-height: 0; }
.iax-assign-msg.show { min-height: 1.2em; }
.iax-assign-msg.ok { color: var(--c-text); }
.iax-assign-msg.err { color: #b03a2e; }
@media (max-width: 640px) {
  .iax-assign { padding: 18px 16px 16px; }
  /* On a phone, stack the action below the registrar line so the tap target is full-width. */
  .iax-assign-row { flex-wrap: wrap; }
  .iax-assign-row .btn-coral.sm { flex: 1 1 100%; }
  .iax-assign-here { align-self: flex-start; }
}
/* let the picker rows + their children shrink (no horizontal overflow). */
.iax-assign-row > *, .iax-assign-list > * { min-width: 0; }

/* ── FIX 4 — DELETE COURSE (destructive button + the typed-confirm dialog) ──
   A restrained brick-red is the accessible convention for a destructive action (used ONLY here, never as a
   content hue). The ghost form sits quietly on the taught card; the solid form is the armed dialog button. */
.btn-danger, .btn-danger-ghost { display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 600; font-size: 14px; line-height: 1; cursor: pointer; border-radius: var(--radius-sm);
  padding: 10px 17px; min-height: 40px; border: 1px solid transparent;
  transition: background 150ms var(--ease-out), border-color 150ms var(--ease-out), color 150ms var(--ease-out); }
.btn-danger.sm, .btn-danger-ghost.sm { padding: 8px 14px; font-size: 13px; min-height: 34px; }
.btn-danger { background: #b03a2e; color: #fff; border-color: #b03a2e; }
.btn-danger:hover { background: #97311f; border-color: #97311f; }
.btn-danger:disabled { background: var(--w-line-2); border-color: var(--w-line-2); color: var(--w-ink-3); cursor: default; }
.btn-danger-ghost { background: transparent; color: #b03a2e; border-color: var(--w-line-2); }
.btn-danger-ghost:hover { background: rgba(176,58,46,0.08); border-color: #b03a2e; }
.btn-danger:focus-visible, .btn-danger-ghost:focus-visible { outline: 2px solid #b03a2e; outline-offset: 2px; }
.iax-delcourse { padding: 22px 22px 18px; }
.iax-delcourse h3 { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 6px 0 0;
  line-height: 1.25; overflow-wrap: anywhere; }
.iax-delcourse-lead { font-size: 13.5px; color: var(--w-ink-2); line-height: 1.55; margin: 10px 0 16px; }
.iax-delcourse-confirm { display: flex; flex-direction: column; gap: 7px; font-size: 13px; color: var(--w-ink-2); margin: 0 0 16px; }
.iax-delcourse-confirm input { font: inherit; font-size: 15px; letter-spacing: 0.04em; padding: 11px 13px; min-height: 44px;
  border: 1px solid var(--w-line); border-radius: var(--radius-sm); background: var(--w-page); color: var(--w-ink); }
.iax-delcourse-confirm input:focus-visible { outline: 2px solid #b03a2e; outline-offset: 1px; border-color: #b03a2e; }
.iax-delcourse-foot { display: flex; gap: 10px; }
.iax-delcourse-foot .btn-ghost-coral, .iax-delcourse-foot .btn-danger { flex: 1; min-height: 46px; }
@media (max-width: 640px) {
  .iax-delcourse { padding: 18px 16px 16px; }
  .iax-delcourse-foot { flex-wrap: wrap; }
  .iax-delcourse-foot .btn-ghost-coral, .iax-delcourse-foot .btn-danger { flex: 1 1 100%; }
}

/* ── My Courses ── */
.iax-section { margin: 0 0 28px; }
.iax-section-h { font-size: 13px; font-family: var(--font-mono); font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--c-text); margin: 0 0 14px; }

/* FIX 2 (Felipe 2026-05-31) — the "Create a course" card that LEADS the Teaching section (above the taught
   list, so an instructor sees it without scrolling). A prominent coral-tinted card with a plus glyph; the
   composer mounts into .iax-create-host directly beneath it. Themed via tokens (one coral, AA), ≥44px tap. */
.iax-create-card { display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px 18px; margin: 0 0 14px; min-height: 64px; cursor: pointer;
  background: var(--c-tint); border: 1px solid var(--c-line); border-radius: var(--radius);
  color: var(--w-ink); transition: background 150ms var(--ease-out), border-color 150ms var(--ease-out), box-shadow 150ms var(--ease-out); }
.iax-create-card:hover { background: var(--c-tint-2, var(--c-tint)); border-color: var(--c-deep); box-shadow: var(--shadow-coral); }
.iax-create-card:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.iax-create-card-ic { flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--c-deep);
  border: 1px solid var(--c-deep); display: flex; align-items: center; justify-content: center; color: #fff; }
.iax-create-card-ic svg { width: 20px; height: 20px; }
.iax-create-card-txt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.iax-create-card-h { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); line-height: 1.25; }
.iax-create-card-sub { font-size: 13px; color: var(--w-ink-2); line-height: 1.45; }
.iax-create-host:not([hidden]) { margin: 0 0 22px; }

.iax-course { padding: 0; }
.iax-course-top { display: flex; align-items: flex-start; gap: 12px; padding: 16px 16px 0; }
.iax-course-ic { flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-course-ic svg { width: 20px; height: 20px; }
.iax-course-h { min-width: 0; flex: 1; }
.iax-course-h h3 { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0; line-height: 1.25;
  overflow-wrap: anywhere; }
.iax-course-meta { font-family: var(--font-mono); font-size: 11.5px; color: var(--w-ink-3); margin: 4px 0 0; }
/* "Taught by {instructor}" sub-line on an enrolled course card (mirrors My Journeys' .iax-mj-line), so a
   student scanning My Courses sees who teaches each class (INTUITIVENESS FIX 2026-05-31). */
.iax-course-taught { font-size: 13px; color: var(--w-ink-2); margin: 10px 16px 0; line-height: 1.45; }
.iax-course-pack { font-size: 12.5px; color: var(--w-ink-2); margin: 10px 16px 0;
  padding: 8px 11px; background: var(--w-page); border: 1px solid var(--w-line); border-radius: var(--radius-sm); }
/* FIX #2 — a taught section with NO assigned coursepack: a coral-tinted "needs a path" note (distinct from
   the neutral pack box) so the instructor sees, at a glance, that this course still needs a course path. */
.iax-course-nopath { color: var(--c-text); background: var(--c-tint); border-color: var(--c-line); font-weight: 600; }
.iax-course.is-nopath { border-color: var(--c-line); }
.iax-course .iax-pack-badge { margin-top: 12px; }
.iax-course .iax-pack-actions { padding-top: 14px; }

/* ── Empty states ── */
.iax-empty { text-align: center; padding: 48px 24px; background: var(--w-card); border: 1px dashed var(--w-line-2);
  border-radius: var(--radius-lg); }
.iax-empty-ic { width: 56px; height: 56px; margin: 0 auto 16px; border-radius: var(--radius-lg); background: var(--c-tint);
  border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; color: var(--c-deep); }
.iax-empty-ic svg { width: 28px; height: 28px; }
.iax-empty h3 { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0 0 8px; }
.iax-empty p { font-size: 14px; color: var(--w-ink-3); line-height: 1.55; max-width: 42ch; margin: 0 auto 20px; }
.iax-empty-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.iax-empty .btn-coral, .iax-empty .btn-ghost-coral, .iax-empty-actions a { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; }

/* ── Reduced motion: settle every entrance/overlay to its final state (no transform motion). ── */
@media (prefers-reduced-motion: reduce) {
  .iax-card { opacity: 1; transform: none; transition: box-shadow 160ms var(--ease-out), border-color 160ms var(--ease-out); }
  .iax-card.iax-in { transform: none; }
  .iax-card[role="button"]:active, a.iax-card:active, .iax-bookrow:active { transform: none; }
  /* the Explore list rows + the View picker settle too (entrance, popover, caret). */
  .iax-row { opacity: 1; transform: none; transition: box-shadow 150ms var(--ease-out), border-color 150ms var(--ease-out); }
  .iax-row.iax-in { transform: none; }
  .iax-row[role="button"]:active { transform: none; }
  .xv-pick-menu { transition: opacity 120ms linear; transform: none; }
  .xv-pick[data-open="true"] .xv-pick-menu { transform: none; }
  .xv-caret, .xv-pick-trigger { transition: none; }
  .iax-modal { transition: opacity 120ms linear; transform: none; }
  .iax-overlay.show .iax-modal { transform: none; }
  @media (hover: hover) and (pointer: fine) {
    .iax-card[role="button"]:hover, a.iax-card:hover { transform: none; }
  }
}

/* ── Mobile: 1-column cards, comfortable tap targets, bottom-sheet overlay, no overflow. ── */
@media (max-width: 640px) {
  .iax-grid, .iax-cgrid, .iax-jgrid { grid-template-columns: 1fr; gap: 13px; }
  /* Force every layout to one column on a phone (gallery's wider min-width would otherwise overflow). The
     LIST layout (flex column) is unaffected + reads especially well here. */
  .iax-grid[data-layout="grid"], .iax-grid[data-layout="gallery"],
  .iax-grid[data-density="compact"][data-layout="grid"] { grid-template-columns: 1fr; }
  .iax-grid[data-layout="gallery"] .iax-cover { height: 132px; }
  /* The "View ▾" picker drops to its own full-width row under the search (no cramped two-up at 390). */
  .iax-tools-top { flex-wrap: wrap; }
  .iax-tools-top .iax-search { flex: 1 1 100%; }
  .xv-pick { flex: 1 1 100%; }
  .xv-pick-trigger { width: 100%; justify-content: center; }
  .xv-pick-menu { left: 0; right: 0; min-width: 0; transform-origin: top center; }
  .iax-row { padding: 12px 13px; }
  .iax-row-cov { display: none; }   /* the coverage chip is redundant on a narrow row; the title+module carry it */
  .iax-modsec-h { font-size: 15px; }
  .iax-tab { margin-right: 10px; font-size: 14px; }
  /* Filter chips meet the 44px tap floor on a phone (WCAG/HIG), not the desktop 38px. */
  .iax-chip { min-height: 44px; padding: 10px 16px; }
  .iax-bookrow { padding: 13px 14px; gap: 12px; }
  .iax-pack-actions .btn-coral, .iax-pack-actions .btn-ghost-coral,
  .iax-course .btn-coral, .iax-course .btn-ghost-coral { min-height: 44px; flex: 1 1 auto; justify-content: center; }
  /* Overlay becomes a bottom sheet (thumb-reachable, never clips); scales up from the bottom. */
  .iax-overlay { align-items: flex-end; padding: 0; }
  .iax-modal { max-width: 100%; max-height: 90dvh; border-radius: 18px 18px 0 0;
    transform: translateY(12px); padding-bottom: env(safe-area-inset-bottom); }
  .iax-overlay.show .iax-modal { transform: none; }
  .iax-modal-foot .btn-coral, .iax-modal-foot .btn-ghost-coral { flex: 1 1 100%; }
  /* The close glyph meets the 44px tap floor on a phone (WCAG 2.5.5 / HIG), not the desktop 36px. */
  .iax-modal-x { width: 44px; height: 44px; font-size: 24px; }
  /* The Teaching Resources section: tighter padding on a phone; its tab strip scrolls like the main one. */
  .iax-teach { padding: 18px 14px 4px; margin-top: 26px; }
  .iax-teach-head h2 { font-size: 19px; }
}

/* Stage B flex/grid children: let them shrink below content (kill silent horizontal overflow). */
.iax-grid > *, .iax-tools > *, .iax-tools-top > *, .iax-chips > *, .iax-pack-actions > *, .iax-empty-actions > *,
.iax-bookrow > *, .iax-foot > *, .iax-modal-foot > *, .iax-ellist > *, .iax-elrow > *,
.iax-row > *, .iax-row-main > *, .iax-modsec-head > *, .iax-modsec-tx > * { min-width: 0; }
.app-panel[data-panel="explore"], .app-panel[data-panel="journeys"], .app-panel[data-panel="courses"] { overflow-x: clip; }

/* ════════════════════════════════════════════════════════════════════════
   LMS WAVE 1 (Felipe 2026-06-01) — ESTIMATED TIME · OBJECTIVES · DUE DATES · UP-NEXT
   Every selector here styles an OPTIONAL element that the JS renders only when its
   data exists, so an untimed / objective-less / undated course shows none of this.
   All claim-bearing color is the coral family (--c-text / --c-deep) on neutrals;
   the "overdue" soft state is a coral-deep word, never a second hue (no red).
   ════════════════════════════════════════════════════════════════════════ */

/* ESTIMATED TIME — the module-sum chip on a ladder row (in .jmeta), the per-element
   chip on an element-action row, the hero "min left", the popup module total. A
   quiet mono token, neutral by default. */
.jtime { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-3);
  white-space: nowrap; }
.jmeta .jtime::before { content: ""; }
.jelr-time { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; color: var(--w-ink-3);
  white-space: nowrap; margin-left: 8px; flex: none; }
.hero-left { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; color: var(--c-text);
  margin-top: 4px; }
.ov-cont-left { color: var(--c-text); font-weight: 600; }
.ov-cont-dot { color: var(--w-ink-4); }
.mpp-h5row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 14px 0 0; }
.mpp-h5row .mpp-h5 { margin: 0; }
.mpp-modtime { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--w-ink-3);
  white-space: nowrap; flex: none; }
.journey[data-density="minimal"] .jtime { font-size: 10px; }
.journey[data-density="compact"] .jtime { font-size: 10.5px; }

/* UP-NEXT marker + inline completion criterion (§4). A small coral-tint pill on the
   first incomplete module's title + a one-line criterion under the active row. */
.jupnext { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: 9.5px;
  font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-deep);
  background: var(--c-tint); border: 1px solid var(--c-line, rgba(218,119,86,0.28)); border-radius: 6px;
  padding: 2px 7px; margin-left: 9px; vertical-align: middle; white-space: nowrap; }
.jcrit { display: block; font-size: 12px; color: var(--w-ink-3); margin-top: 4px; }
.jcrit::before { content: "→ "; color: var(--c-text); font-weight: 700; }
.ov-cont-crit { display: block; font-size: 12.5px; color: var(--w-ink-3); margin-top: 2px; }
.ov-cont-crit::before { content: "→ "; color: var(--c-text); font-weight: 700; }
.journey[data-density="minimal"] .jcrit, .journey[data-density="compact"] .jcrit { display: none; }

/* DUE DATES (§3) — the dated "Due soon" chip on the Overview list + the assignment-row
   chip in Assignments & grades + the popup element row. A coral-tint date token; the
   past-due (incomplete) "overdue" state is a quiet coral-deep word (SOFT, no lock). */
.ov-due-date, .ag-due, .mpp-elrow-due { font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  color: var(--c-text); white-space: nowrap; }
.ov-due-dot, .ag-meta-dot { color: var(--w-ink-4); }
.ov-due-date.is-overdue, .ag-due.is-overdue, .mpp-elrow-due.is-overdue { color: var(--c-deep); font-weight: 700; }
.mpp-elrow-due { display: inline; }

/* OBJECTIVES (§2) — the "In this module, you'll be able to…" bullet list in the
   module-progress popup. A tinted card with a small mono heading + a tidy list. */
.mpp-obj { margin: 14px 0 0; padding: 13px 15px; border-radius: var(--radius-sm);
  background: var(--c-tint); border: 1px solid var(--c-line); }
.mpp-obj .mpp-h5 { margin: 0 0 8px; color: var(--c-deep); }
.mpp-obj-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px; }
.mpp-obj-list li { font-size: 13px; line-height: 1.45; color: var(--w-ink-2); }

/* ════════════════════════════════════════════════════════════════════════
   MY NOTES HUB (LMS roadmap Wave 2 #5) — the highlights/notes study artifact at
   /app#notes. Themed entirely through the V2 tokens (--w-* surfaces, the coral
   --c-* family for the one claim-bearing hue), so it follows every skin/tone via
   CSS variables. AA, mobile-safe, ≥44px tap targets. No second hue, no emoji.
   ════════════════════════════════════════════════════════════════════════ */

/* The toolbar above the list: the note count (mono) + Export / Print actions. */
.notes-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin: 0 0 18px; }
.notes-count { font-size: 12.5px; font-weight: 600; color: var(--w-ink-3); }
.notes-tools { display: flex; gap: 9px; flex-wrap: wrap; }
.notes-tools .btn-ghost-coral { display: inline-flex; align-items: center; gap: 7px; min-height: 38px; }
.notes-tools .btn-ghost-coral svg { width: 16px; height: 16px; flex: none; }

.notes-list { display: flex; flex-direction: column; gap: 8px; }
.note-course { display: flex; flex-direction: column; gap: 4px; }
/* The course heading (only shown when >1 course). */
.note-course-head { font-size: 13px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--c-text); margin: 18px 0 8px; font-family: var(--font-mono); }
.note-course:first-child .note-course-head { margin-top: 0; }

/* A chapter group: a heading + a "Jump to chapter" link, then the note cards. */
.note-chapter { margin: 0 0 26px; border-radius: var(--radius); transition: background 200ms var(--ease-out); }
/* Hub-rail "scroll to chapter" flash — a brief coral wash so the jumped-to chapter is obvious. */
.note-chapter.is-flash { background: var(--c-tint); }
@media (prefers-reduced-motion: reduce) { .note-chapter { transition: none; } }
.note-ch-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin: 0 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--w-line); }
.note-ch-head h3 { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; color: var(--w-ink); margin: 0; }
/* "Jump to chapter": a quiet coral-text link (AA #a8472a on surface), arrow glyph. */
.note-jump { display: inline-flex; align-items: center; gap: 6px; flex: none; font-size: 13px; font-weight: 600;
  color: var(--c-text); text-decoration: none; border-radius: 7px; padding: 6px 8px; min-height: 32px; }
.note-jump:hover { background: var(--c-tint); color: var(--c-text); text-decoration: none; }
.note-jump:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.note-jump svg { width: 15px; height: 15px; flex: none; }

.note-cards { display: flex; flex-direction: column; gap: 12px; }

/* A note card: the coral-marked quote, the annotation (editable), the date + actions. */
.note-card { background: var(--w-card); border: 1px solid var(--w-line); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-1); }
/* The highlighted QUOTE — a coral-marked blockquote (the highlight made visible). */
.note-quote { margin: 0 0 12px; padding: 4px 0 4px 14px; border-left: 3px solid var(--c-coral);
  background: var(--c-wash, rgba(218,119,86,0.07)); border-radius: 0 8px 8px 0;
  font-size: 14.5px; line-height: 1.55; color: var(--w-ink); font-style: normal; }
.note-body { margin: 0; }
.note-text { font-size: 14px; line-height: 1.55; color: var(--w-ink-2); margin: 0; white-space: pre-wrap; }
.note-text.note-empty-note { color: var(--w-ink-4); font-style: italic; }

/* Inline editor for the annotation. */
.note-edit { margin-top: 4px; }
.note-edit-ta { width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 14px; line-height: 1.5;
  color: var(--w-ink); background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: var(--radius-sm);
  padding: 10px 12px; resize: vertical; min-height: 64px; }
.note-edit-ta:focus { outline: 2px solid var(--c-deep); outline-offset: 1px; border-color: var(--c-deep); }
.note-edit-actions { display: flex; gap: 9px; margin-top: 10px; }

/* The footer row: date (left) + Edit / Delete actions (right). */
.note-meta { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 14px; flex-wrap: wrap; }
.note-date { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; color: var(--w-ink-4); }
.note-actions { display: flex; gap: 6px; flex: none; }
.note-act { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 7px 11px;
  font-family: var(--font); font-size: 13px; font-weight: 600; cursor: pointer; color: var(--w-ink-2);
  background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: 8px; }
.note-act svg { width: 15px; height: 15px; flex: none; stroke: currentColor; }
.note-act:hover { border-color: var(--c-text); color: var(--c-text); background: var(--c-tint); }
.note-act:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
/* The delete button's ARMED (confirm) state — a coral-deep word, no second hue. */
.note-del-btn.is-armed { color: #fff; background: var(--c-deep); border-color: var(--c-deep); }
.note-del-btn.is-armed:hover { background: var(--c-text); border-color: var(--c-text); color: #fff; }

.note-msg { font-family: var(--font-mono); font-size: 12px; color: var(--w-ink-3); margin: 10px 0 0; }
.note-msg.err { color: var(--c-text); }

/* Mobile: the chapter head stacks the jump link, and the action buttons get the 44px tap floor. */
@media (max-width: 640px) {
  .note-ch-head { gap: 8px; }
  .note-card { padding: 14px 15px; }
  .note-act { min-height: 44px; padding: 10px 13px; }
  .note-jump { min-height: 44px; padding: 9px 11px; }
  .notes-tools { width: 100%; }
  .notes-tools .btn-ghost-coral { flex: 1; justify-content: center; min-height: 44px; }
  .note-meta { gap: 8px; }
}

/* ============================================================================
   NOTES ORGANIZATION LAYER — TAGS · LINKS/BACKLINKS · COLOR MEANINGS · FILTERS
   (Felipe 2026-06-01; NOTES-ANNOTATION-BEST-PRACTICES §1 colors + §3 tags/links)
   Lives in the My-Notes HUB only (the reader stays clean). Themed via the dashboard
   tokens (--w-*/--c-*) so every skin/tone inherits; chips/filters WRAP; controls
   keep a comfortable tap target (≥36px desktop, ≥44px mobile); AA contrast (coral
   text = --c-text #a8472a on surface; the 6 highlight swatches mirror the reader).
   ============================================================================ */

/* The 6 highlight-color swatch fills — mirror the reader's light-mode tints (content.ts HIGHLIGHT_COLORS) so
   a legend swatch reads the SAME color as the on-page highlight. Each swatch = a soft fill + a stronger ring. */
/* CANONICAL palette — the SINGLE source of truth shared with the reader: --hl-bg == content.ts MARKTINT (the
   on-page mark wash), --hl-line == content.ts SWATCHCOL (the bright swatch face). So the hub legend chip reads
   the EXACT same color as the on-page highlight, the in-prose popover swatch, and the panel dot (was a darker
   #B8553A coral here, which made the "same" color look like three different oranges across surfaces). */
.note-sw { display: inline-block; width: 14px; height: 14px; flex: none; border-radius: 5px;
  background: var(--hl-bg, rgba(226,103,74,0.30)); box-shadow: inset 0 0 0 1.5px var(--hl-line, #E2674A); }
.note-sw-coral  { --hl-bg: rgba(226,103,74,0.30); --hl-line: #E2674A; }
.note-sw-yellow { --hl-bg: rgba(235,180,0,0.34);  --hl-line: #EBB400; }
.note-sw-blue   { --hl-bg: rgba(59,130,246,0.26); --hl-line: #3B82F6; }
.note-sw-green  { --hl-bg: rgba(31,164,99,0.28);  --hl-line: #1FA463; }
.note-sw-pink   { --hl-bg: rgba(224,72,154,0.26); --hl-line: #E0489A; }
.note-sw-purple { --hl-bg: rgba(139,92,246,0.28); --hl-line: #8B5CF6; }

/* ── THE FILTER BAR (tag rail + color filter + legend editor) ── */
.notes-filterbar { display: flex; flex-direction: column; gap: 10px; margin: 0 0 18px;
  padding: 12px 14px; border: 1px solid var(--w-line); border-radius: var(--radius-lg); background: var(--w-card-2, var(--w-card)); }
.notes-filter-row { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.notes-filter-lab { flex: none; min-width: 46px; padding-top: 7px; font-family: var(--font-mono); font-size: 10.5px;
  font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--w-ink-4); }
.notes-tagrail, .notes-colorrail { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; min-width: 0; }

/* A tag filter chip ("All" + each distinct tag). Pressed = coral tint. */
.notes-tagchip { display: inline-flex; align-items: center; gap: 5px; min-height: 32px; padding: 5px 11px;
  border: 1px solid var(--w-line-2); border-radius: 999px; background: var(--w-card); cursor: pointer;
  font-family: var(--font); font-size: 12.5px; font-weight: 600; color: var(--w-ink-2);
  transition: background 130ms var(--ease-out), border-color 130ms var(--ease-out), color 130ms var(--ease-out); }
.notes-tagchip svg { color: var(--w-ink-4); }
.notes-tagchip:hover { border-color: var(--c-line); color: var(--w-ink); }
.notes-tagchip.on { background: var(--c-tint); border-color: var(--c-line); color: var(--c-text); }
.notes-tagchip.on svg { color: var(--c-text); }
.notes-tagchip:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }

/* A color filter chip ("All" + a swatch per color; the legend name shows when set). */
.notes-colorchip { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 5px 10px;
  border: 1px solid var(--w-line-2); border-radius: 999px; background: var(--w-card); cursor: pointer;
  font-family: var(--font); font-size: 12.5px; font-weight: 600; color: var(--w-ink-2);
  transition: background 130ms var(--ease-out), border-color 130ms var(--ease-out); }
.notes-colorchip:hover { border-color: var(--c-line); color: var(--w-ink); }
.notes-colorchip.on { background: var(--c-tint); border-color: var(--c-deep); color: var(--c-text); }
.notes-colorchip:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.notes-colorchip-lab { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The "Name colors" toggle (opens the legend editor). */
.notes-legend-toggle { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 5px 11px;
  border: 1px dashed var(--w-line-2); border-radius: 999px; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 12px; font-weight: 700; color: var(--w-ink-3); margin-left: 2px; }
.notes-legend-toggle:hover { border-color: var(--c-line); color: var(--c-text); }
.notes-legend-toggle.on { border-style: solid; border-color: var(--c-line); color: var(--c-text); background: var(--c-tint); }
.notes-legend-toggle:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }

/* The collapsible color-LEGEND editor (name each color's meaning → localStorage). */
.notes-legend-edit { margin-top: 4px; padding: 12px 12px 6px; border: 1px solid var(--w-line); border-radius: var(--radius);
  background: var(--w-page); }
.notes-legend-help { font-size: 12px; line-height: 1.5; color: var(--w-ink-3); margin: 0 0 10px; }
.notes-legend-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.notes-legend-rowi { display: flex; align-items: center; gap: 8px; min-width: 0; }
.notes-legend-word { flex: none; width: 52px; font-size: 12px; font-weight: 700; color: var(--w-ink-2); }
.notes-legend-input { flex: 1 1 auto; min-width: 0; min-height: 36px; padding: 7px 10px; box-sizing: border-box;
  font-family: var(--font); font-size: 13px; color: var(--w-ink); background: var(--w-card);
  border: 1px solid var(--w-line-2); border-radius: var(--radius-sm); }
.notes-legend-input:focus { outline: 2px solid var(--c-deep); outline-offset: 1px; border-color: var(--c-deep); }

/* ── A NOTE CARD's color chip + tags + links ── */
.note-top { display: flex; align-items: center; justify-content: flex-end; margin: 0 0 8px; }
.note-colorchip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px 3px 7px; border-radius: 999px;
  background: var(--w-page); border: 1px solid var(--w-line); }
.note-colorchip-lab { font-size: 11px; font-weight: 700; color: var(--w-ink-3); letter-spacing: 0.01em; }

/* Tags on a card: removable chips + a quick-add input. */
.note-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 12px 0 0; }
.note-tag { display: inline-flex; align-items: center; gap: 5px; padding: 3px 5px 3px 9px; border-radius: 999px;
  background: var(--c-tint); border: 1px solid var(--c-line); color: var(--c-text); font-size: 12px; font-weight: 600; }
.note-tag svg { color: var(--c-text); opacity: 0.8; }
.note-tag-x { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border: 0; border-radius: 999px; background: transparent; color: var(--c-text); cursor: pointer; padding: 0; }
.note-tag-x:hover { background: var(--c-tint2, rgba(218,119,86,0.18)); }
.note-tag-x:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 1px; }
.note-tagadd { display: inline-flex; align-items: center; }
.note-tagadd-input { min-height: 30px; width: 92px; padding: 5px 10px; box-sizing: border-box;
  font-family: var(--font); font-size: 12.5px; color: var(--w-ink); background: var(--w-card);
  border: 1px dashed var(--w-line-2); border-radius: 999px; }
.note-tagadd-input::placeholder { color: var(--w-ink-4); }
.note-tagadd-input:focus { outline: none; width: 132px; border-style: solid; border-color: var(--c-deep); background: var(--w-card); }
@media (prefers-reduced-motion: no-preference) { .note-tagadd-input { transition: width 140ms var(--ease-out), border-color 140ms var(--ease-out); } }

/* Links / backlinks region on a card. */
.note-links { display: flex; flex-direction: column; gap: 10px; margin: 12px 0 0; padding: 11px 12px;
  border: 1px solid var(--w-line); border-radius: var(--radius); background: var(--w-page); }
.note-links-grp { display: flex; flex-direction: column; gap: 5px; }
.note-links-lab { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--w-ink-4); }
.note-link-row { display: flex; align-items: center; gap: 6px; }
.note-link-go { display: inline-flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; min-height: 34px;
  padding: 6px 10px; border: 1px solid var(--w-line); border-radius: 9px; background: var(--w-card); cursor: pointer;
  font-family: var(--font); font-size: 13px; font-weight: 600; color: var(--w-ink-2); text-align: left;
  transition: border-color 120ms var(--ease-out), background 120ms var(--ease-out); }
.note-link-go svg { flex: none; color: var(--c-text); }
.note-link-go:hover { border-color: var(--c-line); background: var(--c-tint); color: var(--c-text); }
.note-link-go:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.note-link-lab { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note-link-x { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 30px; height: 30px;
  border: 1px solid var(--w-line); border-radius: 8px; background: var(--w-card); color: var(--w-ink-3); cursor: pointer; }
.note-link-x:hover { border-color: var(--c-deep); color: var(--c-text); background: var(--c-tint); }
.note-link-x:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.note-link-x.loading { opacity: 0.5; pointer-events: none; }

/* The "Link" action button's open state. */
.note-link-btn.on { border-color: var(--c-deep); color: var(--c-text); background: var(--c-tint); }

/* The link picker (choose another note / a chapter). */
.note-linkpicker { margin: 12px 0 0; }
.note-lp { padding: 13px 14px; border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--c-tint); }
.note-lp-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.note-lp-title { font-size: 13px; font-weight: 700; color: var(--w-ink); }
.note-lp-modes { display: inline-flex; gap: 4px; padding: 3px; border-radius: 999px; background: var(--w-card); border: 1px solid var(--w-line); }
.note-lp-mode { min-height: 30px; padding: 5px 12px; border: 0; border-radius: 999px; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 12.5px; font-weight: 700; color: var(--w-ink-3); }
.note-lp-mode.on { background: var(--c-deep); color: #fff; }
.note-lp-mode:disabled { opacity: 0.4; cursor: not-allowed; }
.note-lp-mode:focus-visible { outline: 2px solid var(--c-deep); outline-offset: 2px; }
.note-lp-body { display: flex; flex-direction: column; gap: 10px; }
.note-lp select { width: 100%; min-height: 40px; padding: 8px 11px; box-sizing: border-box; font-family: var(--font);
  font-size: 13.5px; color: var(--w-ink); background: var(--w-card); border: 1px solid var(--w-line-2); border-radius: var(--radius-sm); }
.note-lp select:focus { outline: 2px solid var(--c-deep); outline-offset: 1px; border-color: var(--c-deep); }
.note-lp-empty { font-size: 13px; color: var(--w-ink-3); margin: 0; }
.note-lp-actions { display: flex; gap: 9px; flex-wrap: wrap; }
.note-lp-actions .btn-coral, .note-lp-actions .btn-ghost-coral { min-height: 40px; }
.note-lp-msg { font-family: var(--font-mono); font-size: 12px; color: var(--c-text); margin: 0; }

/* No-results state for a filter. */
.notes-noresults { margin-top: 8px; }

/* Mobile — the org controls keep the 44px floor and the legend grid + link rows go single-column. */
@media (max-width: 640px) {
  .notes-filterbar { padding: 11px 12px; }
  .notes-tagchip, .notes-colorchip, .notes-legend-toggle { min-height: 36px; }
  .notes-legend-grid { grid-template-columns: 1fr; }
  .note-tagadd-input { min-height: 36px; }
  .note-link-go, .note-link-x { min-height: 40px; }
  .note-link-x { width: 40px; height: 40px; }
  .note-tag-x { width: 24px; height: 24px; }
}

/* ── Co-authoring invite cards (Wave LAST) — a warm coral card on the dashboard home when an admin has invited
   this account to co-author a chapter. Theme-aware via the coral tokens (fallbacks for any skin without them). */
.coa-invites{display:flex;flex-direction:column;gap:10px;margin:0 0 18px}
.coa-invite-card{display:flex;align-items:center;gap:14px;background:var(--coral-tint,#fcefe9);border:1px solid var(--coral-line,#f0d6cb);border-radius:14px;padding:13px 15px;box-shadow:0 1px 2px rgba(16,24,40,.04)}
.coa-invite-ic{flex:none;width:38px;height:38px;border-radius:10px;background:var(--coral-deep,#B8553A);color:#fff;display:flex;align-items:center;justify-content:center}
.coa-invite-ic svg{width:19px;height:19px}
.coa-invite-body{flex:1;min-width:0}
.coa-invite-h{font:600 14.5px/1.3 'Inter',system-ui,sans-serif;color:var(--ink,#1a1f2e)}
.coa-invite-h b{color:var(--coral-text,#a8472a);font-weight:700}
.coa-invite-p{font:400 12.5px/1.45 'Inter',system-ui,sans-serif;color:var(--ink-3,#6b7280);margin-top:3px}
.coa-invite-btn{flex:none;border:0;border-radius:9px;background:var(--coral-deep,#B8553A);color:#fff;font:600 13px/1 'Inter',system-ui,sans-serif;padding:11px 15px;cursor:pointer;transition:transform .12s ease,filter .12s ease}
.coa-invite-btn:hover{filter:brightness(1.06)}
.coa-invite-btn:active{transform:scale(.97)}
.coa-invite-btn:focus-visible{outline:2px solid var(--coral-deep,#B8553A);outline-offset:2px}
@media (max-width:560px){.coa-invite-card{flex-wrap:wrap}.coa-invite-btn{width:100%}}
@media (prefers-reduced-motion:reduce){.coa-invite-btn{transition:none}}

/* Join-code chip on the teaching course card (#7 — was one click deeper in the workspace). Coral, theme-aware. */
.iax-course-join{display:flex;align-items:center;gap:8px;margin:8px 0 2px;flex-wrap:wrap}
.iax-course-join-lbl{font:600 11px/1 'Inter',system-ui,sans-serif;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3,#6b7280)}
.iax-course-join-code{font:600 13px/1 ui-monospace,monospace;letter-spacing:.12em;color:var(--coral-text,#a8472a);background:var(--coral-tint,#fcefe9);border:1px solid var(--coral-line,#f0d6cb);border-radius:7px;padding:4px 9px}
.iax-course-join-copy{border:1px solid var(--line,#e7ebf0);background:transparent;color:var(--ink-2,#43474f);font:600 11.5px/1 'Inter',system-ui,sans-serif;border-radius:7px;padding:5px 9px;cursor:pointer;transition:background .12s ease,transform .12s ease}
.iax-course-join-copy:hover{background:var(--hover,#f3f4f6)}
.iax-course-join-copy:active{transform:scale(.97)}
