/* ====================================================================
   AI Accelerator Learning Platform — Style Sheet
   learn.aiaccelerator.uk
   ================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');

/* ====================================================================
   1. CSS Custom Properties — Brand Variables
   ==================================================================== */

:root {
  /* Colours — Primary & Secondary */
  --color-primary: #1B2F3C;
  --color-accent-1: #00FFBC;
  --color-accent-2: #00B1FF;
  --color-white: #FFFFFF;
  --color-off-white: #F8F9FA;

  /* Extended Palette */
  --color-deep-cerulean: #0084B2;
  --color-malibu: #5CD5FF;
  --color-cornflower: #6161FF;
  --color-meadow: #17CE95;
  --color-moonraker: #C5B6F1;
  --color-sea-pink: #EFACA8;
  --color-surface-dark: #152532;

  /* Accessible Alternatives (light backgrounds) */
  --color-accent-1-accessible: #007A5E;
  --color-accent-2-accessible: #0071A1;

  /* Text & UI */
  --color-text-primary: #1B2F3C;
  --color-text-secondary: #575756;
  --color-text-muted: #6B7A88;
  --color-border: #E2E8F0;
  --color-border-dark: #1E3A4C;

  /* ─── V2 Functional Tokens (PRD §19.2, DESIGN.md §3.3) ───
     Functional, role-based names that the dark-theme block (added in
     the follow-up commit) will override. Light values match the
     platform's current rendering exactly — pure refactor, zero visual
     change. The prescriptive --color-* tokens above remain valid and
     are kept as aliases for any existing consumer. */
  --bg:             #F8F9FA;
  --bg-deep:        #F0F3F5;
  --surface:        #FFFFFF;
  --surface-hover:  #F8F9FA;
  --ink:            #1B2F3C;
  --ink-soft:       #5A6B7A;
  --ink-muted:      #8A98A4;
  --line:           #E2E8F0;
  --line-strong:    rgba(27, 47, 60, 0.18);
  --accent:         #007A5E;
  --accent-secondary: #00B1FF;
  --accent-cta:     #0084B2;
  --ink-on-accent:  #FFFFFF;
  --warn:           #FF5F5F;
  --warn-bg:        rgba(255, 95, 95, 0.08);
  --focus:          #0084B2;
  --shadow:         0 4px 18px rgba(27, 47, 60, 0.08);
  --shadow-strong:  0 12px 32px rgba(27, 47, 60, 0.16);

  /* Gradients (light) */
  --gradient-hero: linear-gradient(135deg, #111F28 0%, #1B2F3C 60%, #0A4A6B 100%);
  --gradient-accent: linear-gradient(135deg, #00FFBC 0%, #00B1FF 100%);
  --gradient-stat: linear-gradient(135deg, #1B2F3C 0%, #0A4A6B 100%);
  --gradient-card-hover: linear-gradient(135deg, rgba(0, 255, 188, 0.1) 0%, rgba(0, 177, 255, 0.1) 100%);

  /* Shadows */
  --shadow-sm: 0 1px 3px rgba(27, 47, 60, 0.08);
  --shadow-md: 0 4px 12px rgba(27, 47, 60, 0.12);
  --shadow-lg: 0 12px 40px rgba(27, 47, 60, 0.16);
  --shadow-glow: 0 0 40px rgba(0, 255, 188, 0.2);
  --shadow-glow-subtle: 0 0 20px rgba(0, 255, 188, 0.1);

  /* Typography */
  --font: 'Poppins', system-ui, -apple-system, sans-serif;
  --font-mono: 'Courier New', monospace;

  /* Layout */
  --max-width: 1280px;
  --sidebar-width: 280px;
  --spacing-xs: 0.25rem;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
  --spacing-xl: 2rem;
  --spacing-2xl: 3rem;

  /* Animation */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --duration-fast: 150ms;
  --duration-normal: 300ms;
  --duration-slow: 500ms;

  /* Borders & Radius */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
}

/* ─── V2 Dark Theme (PRD §19.2, DESIGN.md §3) ───
   Activated by setting `data-theme="dark"` on <html>. Default (no
   attribute) and `data-theme="light"` both render via the :root block
   above — byte-identical to the deployed platform.

   The override pairs the 18 functional tokens (per DESIGN.md §3.3,
   reconciled with design-system/02-colour.md contrast tiers) with
   selective flips of the prescriptive --color-* aliases that have a
   pure single role (text colours, borders, the off-white recessed
   surface). --color-primary stays at #1B2F3C in both themes because
   it serves as a dark fill (footer, video player chrome, completion
   gradient base) — when the canvas itself becomes Gable Green in dark
   mode, those dark fills sit flush, which is the desired effect.
   --color-white flips to #1B2F3C so it works as a background token;
   the small set of "white text on always-dark surface" uses (hero
   text, footer copy, stat-card numbers, completion banner, video-
   player chrome) are overridden explicitly below.

   Full WCAG-AA surface coverage across every section type / state
   combination is the Phase 2a "Theme QA sweep" task. This block is
   the foundation it builds on. */
:root[data-theme="dark"] {
  --bg:             #1B2F3C;
  --bg-deep:        #152532;
  --surface:        rgba(255, 255, 255, 0.04);
  --surface-hover:  rgba(255, 255, 255, 0.08);
  --ink:            #FFFFFF;
  --ink-soft:       #CFDBE4;
  --ink-muted:      #8AA0AE;
  --line:           rgba(255, 255, 255, 0.10);
  --line-strong:    rgba(255, 255, 255, 0.22);
  --accent:         #00FFBC;
  --accent-secondary: #00B1FF;
  --accent-cta:     #0084B2;
  --ink-on-accent:  #1B2F3C;
  --warn:           #FF9D6B;
  --warn-bg:        rgba(255, 157, 107, 0.12);
  --focus:          #00FFBC;
  --shadow:         0 4px 18px rgba(0, 0, 0, 0.30);
  --shadow-strong:  0 12px 32px rgba(0, 0, 0, 0.45);

  /* Prescriptive aliases that flip cleanly (single role). */
  --color-white:          #1B2F3C;   /* used as page/card bg — flips dark; white-text uses overridden below */
  --color-off-white:      #152532;   /* recessed surface → dark deep */
  --color-text-primary:   #FFFFFF;
  --color-text-secondary: #CFDBE4;
  --color-text-muted:     #8AA0AE;
  --color-border:         rgba(255, 255, 255, 0.10);

  /* The "accessible" accent variants were the light-bg-only forms (#007A5E
     / #0071A1). On a Gable canvas they fall under WCAG AA, so in dark mode
     they flip back to their bright forms — which are the Tier-3-on-dark
     colours the accessible variants existed to replace on light. This
     auto-fixes ~19 selector usages (link hovers, section labels, lesson-
     nav highlights, key-tips icons, in-development locked icon, catalogue
     card hover border) without per-selector overrides. */
  --color-accent-1-accessible: #00FFBC;
  --color-accent-2-accessible: #00B1FF;
}

/* White text preserved on always-dark surfaces (--color-white now
   resolves to #1B2F3C in dark, so these explicit overrides keep the
   text legible on the hero gradient, footer, completion banner, stat
   cards, video-player chrome, and the prompt copy-button hover). */
:root[data-theme="dark"] .hero,
:root[data-theme="dark"] .hero__title,
:root[data-theme="dark"] footer,
:root[data-theme="dark"] footer a,
:root[data-theme="dark"] .video-player__minimize,
:root[data-theme="dark"] .stat-card,
:root[data-theme="dark"] .completion-celebration,
:root[data-theme="dark"] .prompt-copy-btn:hover {
  color: #FFFFFF;
}

/* Dark-mode surface overrides for selectors that use raw light hex
   literals (deliberately left as raw in the original refactor for
   zero-visual-change). These flip them to dark equivalents now that
   we have a full dark-mode contract. */
:root[data-theme="dark"] .lesson-locked-panel {
  background: var(--bg-deep);
  border-color: var(--line);
}
:root[data-theme="dark"] .lesson-locked-icon {
  /* Was rgba(27, 47, 60, 0.06) — a dark tint on light. On a dark canvas
     that's invisible. Flip to a faint white tint. */
  background: rgba(255, 255, 255, 0.06);
}
:root[data-theme="dark"] .lesson-locked-panel--in_development .lesson-locked-icon {
  background: rgba(0, 177, 255, 0.16); /* slightly stronger blue tint on dark */
}
:root[data-theme="dark"] .section-text tr:nth-child(even) td {
  /* Was #fafbfc (near-white stripe) — invisible on dark. Faint white tint. */
  background: rgba(255, 255, 255, 0.03);
}
:root[data-theme="dark"] .section-label--prompt {
  /* Cream/gold pair (#F0E4D0 bg, #7A5E1A text) → cream tint on dark with
     cream text. Preserves the deliberate warm signal of the prompt label. */
  background: rgba(240, 228, 208, 0.12);
  color: #F0E4D0;
}
/* Account-menu border + divider use a literal #E4E8EC (slightly cooler
   than --line). Bring them in line with --line on dark so the popover
   has a coherent border colour. */
:root[data-theme="dark"] .account-menu {
  /* --surface is translucent in dark (rgba white .04), which let the page
     show through and made the menu hard to read. Use the opaque recessed
     surface so the dropdown is fully solid. */
  background: var(--bg-deep);
  border-color: var(--line);
}
:root[data-theme="dark"] .account-menu__divider {
  border-top-color: var(--line);
}
/* Reserved: .account-menu__name-save (dark Gable button, white text)
   is dead code as of 2026-06-08 — the name-edit UI was removed. No
   dark override needed; if the button is reintroduced, give it
   var(--accent-cta) as fill. */

/* ====================================================================
   2. Reset & Base Styles
   ==================================================================== */

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.7;
  color: var(--color-text-primary);
  background-color: var(--color-white);
  overflow-x: hidden;
}

/* ====================================================================
   3. Typography
   ==================================================================== */

h1 {
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin-bottom: var(--spacing-lg);
}

h2 {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin-bottom: var(--spacing-lg);
}

h3 {
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.01em;
  margin-bottom: var(--spacing-md);
}

h4 {
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.005em;
  margin-bottom: var(--spacing-md);
}

p {
  margin-bottom: var(--spacing-md);
}

small {
  font-size: 0.875rem;
}

a {
  color: var(--color-accent-2);
  text-decoration: none;
  transition: color var(--duration-normal) var(--ease-out);
}

a:hover {
  color: var(--color-accent-1-accessible);
}

/* ====================================================================
   4. Container & Layout Utilities
   ==================================================================== */

.container {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--spacing-lg);
}

.content-width {
  max-width: 680px;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--spacing-xl);
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--spacing-xl);
}

.flex {
  display: flex;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.flex-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.flex-col {
  display: flex;
  flex-direction: column;
}

/* ====================================================================
   5. Progress Bar
   ==================================================================== */

.progress-bar {
  width: 100%;
  height: 4px;
  background-color: var(--color-border);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: var(--spacing-lg);
}

.progress-bar__fill {
  height: 100%;
  background: var(--gradient-accent);
  border-radius: 2px;
  width: 0%;
  transition: width var(--duration-slow) var(--ease-out);
  position: relative;
}

.progress-bar__fill::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 30px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3));
  animation: shimmer 2s infinite;
}

@keyframes shimmer {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.progress-bar__label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-muted);
  margin-top: var(--spacing-sm);
}

/* ====================================================================
   6. Badge
   ==================================================================== */

.badge {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background-color: var(--color-off-white);
  color: var(--color-text-secondary);
}

.badge--accent {
  background: var(--gradient-accent);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--color-accent-1);
}

.badge--success {
  background-color: rgba(23, 206, 149, 0.1);
  color: var(--color-meadow);
}

.badge--info {
  background-color: rgba(0, 177, 255, 0.1);
  color: var(--color-accent-2);
}

/* ====================================================================
   7. LANDING PAGE
   ==================================================================== */

/* ---- Hero Section ---- */

.hero {
  background: var(--gradient-hero);
  color: var(--color-white);
  padding: var(--spacing-2xl) var(--spacing-lg);
  text-align: center;
  position: relative;
  overflow: hidden;
}

.hero::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(circle at 20% 50%, rgba(0, 255, 188, 0.05) 0%, transparent 50%),
    radial-gradient(circle at 80% 80%, rgba(0, 177, 255, 0.05) 0%, transparent 50%);
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: 1;
  max-width: 800px;
  margin: 0 auto;
}

.hero__title {
  font-size: 3rem;
  font-weight: 700;
  line-height: 1.2;
  margin-bottom: var(--spacing-lg);
  color: var(--color-white);
}

.hero__subtitle {
  font-size: 1.125rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.85);
  margin-bottom: var(--spacing-2xl);
}

.hero__progress {
  margin-bottom: var(--spacing-2xl);
}

.hero__stat {
  display: inline-block;
  margin: 0 var(--spacing-lg);
  color: var(--color-accent-1);
}

.hero__stat-number {
  display: block;
  font-size: 2rem;
  font-weight: 700;
}

.hero__stat-label {
  display: block;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.7);
  margin-top: var(--spacing-xs);
}

/* ---- Module Cards ---- */

.modules-section {
  padding: var(--spacing-2xl) var(--spacing-lg);
}

.modules-title {
  text-align: center;
  margin-bottom: var(--spacing-2xl);
}

.modules-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--spacing-xl);
  margin-bottom: var(--spacing-2xl);
}

/* "Everyone should know" divider (PLA-91).
   Full-width row inside .modules-grid separating the selected function's own
   module cards from the universal ones. grid-column spans every track so it
   breaks the flow rather than sitting in a column as a stray card. */
.xp-universal-divider {
  grid-column: 1 / -1;
  margin: var(--spacing-sm) 0 0;
  padding-top: var(--spacing-lg);
  border-top: 1px solid var(--color-border);
  font-size: var(--font-size-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted, var(--color-text-secondary));
}

.module-card {
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  transition: all var(--duration-normal) var(--ease-out);
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.module-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--gradient-card-hover);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
}

.module-card:hover {
  border-color: var(--color-accent-1-accessible);
  box-shadow: var(--shadow-md), var(--shadow-glow-subtle);
  transform: translateY(-4px);
}

.module-card:hover::before {
  opacity: 1;
}

.module-card__content {
  position: relative;
  z-index: 1;
  flex: 1;
}

.module-card__number {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-2);
  margin-bottom: var(--spacing-sm);
}

.module-card__title {
  font-size: 1.375rem;
  font-weight: 700;
  margin-bottom: var(--spacing-sm);
  color: var(--color-text-primary);
  line-height: 1.3;
}

.module-card__subtitle {
  font-size: 0.95rem;
  color: var(--color-text-secondary);
  margin-bottom: var(--spacing-lg);
  line-height: 1.6;
}

.module-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.875rem;
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-lg);
  padding-bottom: var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
}

.module-card__duration {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
}

.module-card__lessons {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
}

.module-card__progress {
  margin-bottom: var(--spacing-md);
}

.module-card__cta {
  align-self: flex-start;
  padding: var(--spacing-sm) var(--spacing-md);
  background-color: var(--color-off-white);
  color: var(--color-accent-2);
  border: none;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 0.875rem;
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
}

.module-card__cta:hover {
  color: var(--color-accent-1-accessible);
}

/* ---- Footer ---- */

footer {
  background-color: var(--color-primary);
  color: var(--color-white);
  padding: var(--spacing-xl) var(--spacing-lg);
  text-align: center;
  border-top: 1px solid var(--color-border-dark);
}

footer p {
  font-size: 0.875rem;
  opacity: 0.85;
  margin-bottom: var(--spacing-sm);
}

footer a {
  color: var(--color-accent-1);
}

footer a:hover {
  color: var(--color-white);
}

/* ====================================================================
   8. MODULE PAGE — Layout
   ==================================================================== */

.module-layout {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
  background-color: var(--color-off-white);
}

.module-sidebar {
  background: var(--color-white);
  border-right: 1px solid var(--color-border);
  overflow-y: auto;
  position: sticky;
  top: 0;
  max-height: 100vh;
  padding: var(--spacing-lg);
}

.module-sidebar__header {
  margin-bottom: var(--spacing-lg);
  padding-bottom: var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
}

.module-sidebar__title {
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-md);
}

.module-sidebar__progress {
  margin-bottom: var(--spacing-lg);
}

.module-content {
  overflow-y: auto;
  background-color: var(--color-off-white);
}

/* ---- Lesson Navigation ---- */

.lesson-nav {
  list-style: none;
}

.lesson-nav-item {
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-sm);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
  border-left: 3px solid transparent;
  background-color: transparent;
  color: var(--color-text-secondary);
}

.lesson-nav-item:hover {
  background-color: var(--color-off-white);
  border-left-color: var(--color-accent-2);
}

.lesson-nav-item--in-progress {
  background-color: rgba(0, 122, 94, 0.05);
  border-left-color: var(--color-accent-1-accessible);
  color: var(--color-accent-1-accessible);
  font-weight: 600;
}

.lesson-nav-item--completed {
  background-color: rgba(23, 206, 149, 0.05);
  border-left-color: var(--color-meadow);
  color: var(--color-meadow);
}

.lesson-nav-item--completed::before {
  content: '✓ ';
  font-weight: 700;
}

.lesson-nav-item__badge {
  display: inline-block;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--color-border);
  margin-right: var(--spacing-sm);
  vertical-align: middle;
  flex-shrink: 0;
}

/* ====================================================================
   9. MODULE PAGE — Video Player
   ==================================================================== */

.video-player {
  position: sticky;
  top: 0;
  z-index: 10;
  width: 100%;
  background-color: var(--color-primary);
  padding: var(--spacing-lg);
  transition: all var(--duration-normal) var(--ease-out);
}

.video-player__container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
  height: 0;
  overflow: hidden;
  border-radius: 48px;
  background-color: var(--color-surface-dark);
}

.video-player__frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

/* Floating state (shrunk to corner on scroll) */
.video-player.floating {
  position: fixed;
  bottom: var(--spacing-lg);
  right: var(--spacing-lg);
  width: 150px;
  padding: 0;
  background: transparent;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.video-player.floating .video-player__container {
  padding-bottom: 56.25%;
  margin: 0;
}

.video-player.floating .video-player__minimize {
  display: block;
}

.video-player__minimize {
  display: none;
  position: absolute;
  top: var(--spacing-md);
  right: var(--spacing-md);
  z-index: 20;
  width: 32px;
  height: 32px;
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius-md);
  color: var(--color-white);
  cursor: pointer;
  font-size: 1rem;
  transition: all var(--duration-normal) var(--ease-out);
}

.video-player__minimize:hover {
  background: var(--color-accent-1);
}

/* ====================================================================
   10. MODULE PAGE — Content Sections
   ==================================================================== */

.module-header {
  background: var(--color-white);
  padding: var(--spacing-2xl) var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 9;
}

.module-header__breadcrumb {
  font-size: 0.875rem;
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-md);
}

.module-header__title {
  margin-bottom: var(--spacing-md);
}

.module-header__meta {
  display: flex;
  gap: var(--spacing-md);
  align-items: center;
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.content-main {
  padding: var(--spacing-2xl) var(--spacing-lg);
  background: var(--color-off-white);
  max-width: 900px;
  margin: 0 auto;
}

.content-main > * + * {
  margin-top: var(--spacing-xl);
}

/* ---- Unavailable Lesson / Course Panel ---- */

.lesson-locked-panel {
  margin: var(--spacing-2xl) auto;
  padding: var(--spacing-2xl) var(--spacing-xl);
  background: #F4F6F8;
  border: 1px solid #E0E5EA;
  border-radius: var(--radius-lg);
  box-shadow: none;
  text-align: center;
  max-width: 520px;
}

.lesson-locked-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin: 0 auto var(--spacing-md);
  border-radius: 50%;
  background: rgba(27, 47, 60, 0.06);
  color: var(--ink-soft);
}

.lesson-locked-icon svg {
  width: 26px;
  height: 26px;
}

.lesson-locked-panel--in_development .lesson-locked-icon {
  background: rgba(0, 113, 161, 0.08);
  color: var(--color-accent-2-accessible);
}

.lesson-locked-heading {
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--color-text-primary);
  letter-spacing: -0.01em;
  margin-bottom: var(--spacing-sm);
}

.lesson-locked-body {
  color: var(--color-text-secondary);
  line-height: 1.6;
  margin: 0 auto;
  max-width: 380px;
}

/* Admin view marker above normally-locked content (superadmin only) */
.lesson-admin-banner {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin: 0 0 var(--spacing-lg);
  padding: var(--spacing-sm) var(--spacing-md);
  background: rgba(0, 113, 161, 0.08);
  border: 1px solid rgba(0, 113, 161, 0.25);
  border-radius: var(--radius-md);
  color: var(--color-accent-2-accessible);
  font-size: 0.85rem;
  font-weight: 600;
}

.lesson-admin-banner-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.lesson-admin-banner-icon svg {
  width: 16px;
  height: 16px;
}

/* Lock badge in the lesson sidebar nav */
.nav-lesson-lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: auto;
  flex-shrink: 0;
  color: var(--ink-muted);
  opacity: 0.8;
}

.nav-lesson-lock svg {
  width: 14px;
  height: 14px;
}

/* ---- Text Section ---- */

.section-text {
  max-width: 680px;
  line-height: 1.8;
}

.section-text p {
  margin-bottom: var(--spacing-lg);
}

.section-text ul,
.section-text ol {
  margin-left: var(--spacing-lg);
  margin-bottom: var(--spacing-lg);
}

.section-text li {
  margin-bottom: var(--spacing-md);
}

.section-text table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--spacing-xl);
  font-size: 0.95rem;
}

.section-text th,
.section-text td {
  padding: var(--spacing-sm) var(--spacing-md);
  border: 1px solid var(--color-border);
  text-align: left;
  vertical-align: top;
}

.section-text th {
  background: var(--color-off-white);
  font-weight: 600;
  color: var(--color-text-primary);
}

.section-text tr:nth-child(even) td {
  background: #fafbfc;
}

/* ---- Stat Cards ---- */

.section-stat {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--spacing-lg);
  margin: var(--spacing-xl) 0;
}

.stat-card {
  padding: var(--spacing-lg);
  background: var(--gradient-stat);
  border-radius: var(--radius-lg);
  color: var(--color-white);
  text-align: center;
  box-shadow: var(--shadow-md);
  transition: all var(--duration-normal) var(--ease-out);
}

.stat-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.stat-card__number {
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1;
  margin-bottom: var(--spacing-sm);
  background: var(--gradient-accent);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--color-accent-1);
}

.stat-card__label {
  font-size: 0.875rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
}

/* ---- Interactive Section ---- */

.section-interactive {
  margin: var(--spacing-xl) 0;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

.section-interactive__label {
  padding: var(--spacing-lg);
  background: var(--color-off-white);
  border-bottom: 1px solid var(--color-border);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.section-interactive__container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  height: 0;
  background: var(--color-primary);
}

.section-interactive__frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

/* ---- Prompt Block ---- */
/* Note: .section-prompt and inner classes defined in Section 13 below */

/* ---- Tip Section ---- */

.section-tip {
  padding: var(--spacing-lg);
  background: var(--color-off-white);
  border-left: 4px solid var(--color-accent-1-accessible);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  margin: var(--spacing-xl) 0;
}

.section-tip__label {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--color-accent-1-accessible);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--spacing-sm);
}

.section-tip__content {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

/* ---- Callout Section ---- */

.section-callout {
  padding: var(--spacing-lg);
  background: linear-gradient(135deg, rgba(0, 177, 255, 0.08) 0%, rgba(0, 255, 188, 0.08) 100%);
  border: 1px solid rgba(0, 177, 255, 0.2);
  border-radius: var(--radius-lg);
  margin: var(--spacing-xl) 0;
  display: flex;
  gap: var(--spacing-lg);
}

.section-callout__icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--gradient-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
  font-weight: 700;
  font-size: 1.25rem;
}

.section-callout__content {
  flex: 1;
}

.section-callout__title {
  font-weight: 600;
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-sm);
}

.section-callout__text {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

/* "Watch first" prerequisites block — internal-tier only for now. Sits at the
   top of the lesson body, above the first section. Quiet card so it frames the
   lesson without competing with the title. */
.lesson-prerequisites {
  margin: 0 0 var(--spacing-xl);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent-2);
  border-radius: var(--radius-md);
}

.lesson-prerequisites__heading {
  margin: 0 0 var(--spacing-sm);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.lesson-prerequisites__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.lesson-prerequisites__link {
  display: inline-flex;
  align-items: baseline;
  gap: var(--spacing-sm);
  color: var(--color-text-primary);
  text-decoration: none;
  font-weight: 500;
}

.lesson-prerequisites__link:hover .lesson-prerequisites__title {
  text-decoration: underline;
}

/* Transient placeholder while an entitled viewer's gated lesson body is
   fetched from /api/lesson-content. */
.lesson-loading-body {
  padding: var(--spacing-xl) 0;
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

.lesson-prerequisites__kind {
  flex-shrink: 0;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-2-accessible);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.4rem;
}

/* ====================================================================
   11. QUIZ SECTION
   ==================================================================== */

.section-quiz {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  margin: var(--spacing-xl) 0;
  box-shadow: var(--shadow-sm);
}

.section-quiz__question {
  font-size: 1.125rem;
  font-weight: 600;
  margin-bottom: var(--spacing-lg);
  color: var(--color-text-primary);
}

.quiz-options {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

.quiz-option {
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
  font-weight: 500;
  position: relative;
  overflow: hidden;
  /* <button> doesn't inherit colour — set it explicitly so the text follows
     the theme (dark on light, light on dark) instead of the UA default. */
  color: var(--color-text-primary);
  font-family: inherit;
  font-size: 1rem;
  width: 100%;
  text-align: left;
}

.quiz-option:hover {
  border-color: var(--color-accent-2);
  background: rgba(0, 177, 255, 0.05);
}

.quiz-option.selected {
  border-color: var(--color-accent-2);
  background: rgba(0, 177, 255, 0.1);
}

.quiz-option.correct {
  border-color: var(--color-meadow);
  background: rgba(23, 206, 149, 0.1);
  color: var(--color-meadow);
  cursor: default;
}

.quiz-option.correct::before {
  content: '✓ ';
  font-weight: 700;
}

.quiz-option.incorrect {
  border-color: var(--color-sea-pink);
  background: rgba(239, 172, 168, 0.1);
  color: var(--color-sea-pink);
  cursor: default;
}

.quiz-option.incorrect::before {
  content: '✗ ';
  font-weight: 700;
}

.quiz-feedback {
  margin-top: var(--spacing-lg);
  padding: var(--spacing-md) var(--spacing-lg);
  border-radius: var(--radius-md);
  font-size: 0.95rem;
  line-height: 1.6;
}

.quiz-feedback.correct {
  background: rgba(23, 206, 149, 0.1);
  color: var(--color-meadow);
  border-left: 4px solid var(--color-meadow);
}

.quiz-feedback.incorrect {
  background: rgba(239, 172, 168, 0.1);
  color: var(--color-sea-pink);
  border-left: 4px solid var(--color-sea-pink);
}

/* ====================================================================
   12. MODULE COMPLETION
   ==================================================================== */

.completion-celebration {
  text-align: center;
  padding: var(--spacing-2xl) var(--spacing-lg);
  background: linear-gradient(135deg, var(--color-primary) 0%, #0A4A6B 100%);
  border-radius: var(--radius-lg);
  color: var(--color-white);
  position: relative;
  overflow: hidden;
  margin: var(--spacing-2xl) 0;
}

.completion-celebration::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(circle at 20% 50%, rgba(0, 255, 188, 0.2) 0%, transparent 50%),
    radial-gradient(circle at 80% 80%, rgba(0, 177, 255, 0.2) 0%, transparent 50%);
  animation: pulse 2s ease-in-out infinite;
}

.completion-celebration__content {
  position: relative;
  z-index: 1;
}

.completion-celebration__icon {
  font-size: 3rem;
  margin-bottom: var(--spacing-lg);
  display: inline-block;
  animation: bounce 0.6s ease-out;
}

.completion-celebration__title {
  font-size: 2rem;
  font-weight: 700;
  margin-bottom: var(--spacing-md);
  color: var(--color-accent-1);
}

.completion-celebration__text {
  font-size: 1.125rem;
  margin-bottom: var(--spacing-lg);
  opacity: 0.9;
}

.completion-celebration__cta {
  display: inline-block;
  padding: var(--spacing-md) var(--spacing-xl);
  background: var(--gradient-accent);
  color: var(--color-primary);
  border: none;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
  margin-top: var(--spacing-md);
}

.completion-celebration__cta:hover {
  transform: scale(1.05);
  box-shadow: var(--shadow-lg);
}

@keyframes bounce {
  0% {
    transform: translateY(-40px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes pulse {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}

/* ====================================================================
   13. SECTION LABELS & ENGINE-GENERATED CLASSES
   ==================================================================== */

/* ---- Section Label Badges ---- */

.section-label {
  display: inline-block;
  padding: 4px 12px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-radius: 6px;
  margin-bottom: var(--spacing-md);
}

.section-label--prompt {
  background: #F0E4D0;
  color: #7A5E1A;
}

.section-label--interactive {
  background: rgba(0, 122, 94, 0.12);
  color: var(--color-accent-1-accessible);
}

.section-label--tip {
  background: rgba(0, 122, 94, 0.12);
  color: var(--color-accent-1-accessible);
}

.section-label--callout {
  background: rgba(0, 177, 255, 0.1);
  color: var(--color-accent-2-accessible);
}

/* ---- Image Section (engine.js classes) ---- */

.section-image {
  margin: var(--spacing-xl) 0;
}

.section-image-figure {
  margin: 0;
  text-align: center;
}

/* Constrain wide / tall images to fit the viewport without dominating the prose.
   max-height: 60vh keeps landscape images in proportion; object-fit: contain
   prevents cropping and preserves the native aspect ratio. */
.section-image-figure img {
  display: block;
  max-width: 100%;
  max-height: 60vh;
  object-fit: contain;
  margin: 0 auto;
  border-radius: var(--radius-md);
}

.section-image-caption {
  margin-top: var(--spacing-sm);
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  font-style: italic;
}

/* ---- Video Block (engine.js classes) ---- */

.section-video {
  margin: var(--spacing-xl) 0;
}

.video-embed {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 */
  height: 0;
  overflow: hidden;
  border-radius: 25px;
  background: #000;
}

.video-embed iframe,
.video-embed mux-player {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

.video-embed--mux {
  padding-bottom: 0;
  height: auto;
}

.video-embed--mux mux-player {
  position: static;
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}

/* Hide the player until the <mux-player> custom element has been registered
   by the CDN module. Before upgrade the element renders with no shadow-DOM
   styling, so its internal controls (the centred play button) flash as an
   unstyled box — the "square where the play button should be". The reserved
   16:9 box is preserved by the rules above so there's no layout shift. */
.video-embed--mux mux-player:not(:defined) {
  visibility: hidden;
}

/* Mux signed-playback hydration states (engine.js renderVideo + hydrateMuxPlayers).
   While the engine fetches a signed token, the placeholder shows a loading
   message styled to fill the same 16:9 box the player will occupy. On error,
   the same box renders a readable status message. */
.section-video--mux-pending .video-embed--mux,
.section-video--mux-error   .video-embed--mux {
  aspect-ratio: 16 / 9;
  height: auto;
  padding-bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mux-video-status,
.mux-video-error {
  color: #fff;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  font-size: 0.95rem;
  padding: 1rem 1.5rem;
  text-align: center;
}

.mux-video-error {
  color: #ff9aa2;
}

/* ---- Prompt Block (engine.js classes) ---- */

.section-prompt {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  margin: var(--spacing-xl) 0;
  padding: var(--spacing-lg);
}

.prompt-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-sm);
  flex-wrap: wrap;
}

.prompt-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--color-text-primary);
}

.prompt-tool {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.prompt-description {
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
  margin-bottom: var(--spacing-md);
}

.prompt-code {
  padding: var(--spacing-lg);
  background: var(--color-off-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--color-text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
  margin: 0 0 var(--spacing-md) 0;
}

.prompt-copy-btn {
  display: inline-block;
  padding: 0.5rem 1rem;
  background: var(--color-off-white);
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
}

.prompt-copy-btn:hover {
  background: var(--color-primary);
  color: var(--color-white);
  border-color: var(--color-primary);
}

/* ---- Scenario choices (scenario-choices.js) ----
   Judgement scenarios with no right answer. Borrows the quiz option geometry so
   it sits consistently beside aia:quiz, but never uses the correct/incorrect
   colours: there is nothing to be right about, and green/red would assert one. */

.scenario-set {
  display: block;
  width: 100%;
}

.scenario-intro {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
  margin: 0 0 var(--spacing-lg) 0;
}

.scenario + .scenario {
  margin-top: var(--spacing-xl);
  padding-top: var(--spacing-xl);
  border-top: 1px solid var(--color-border);
}

.scenario-count {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-xs);
}

.scenario-situation {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.6;
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-md) 0;
}

.scenario-choices {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}

.scenario-choice {
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--color-text-primary);
  width: 100%;
  text-align: left;
}

.scenario-choice:hover {
  border-color: var(--color-accent-2);
  background: rgba(0, 177, 255, 0.05);
}

.scenario-choice.selected {
  border-color: var(--color-accent-2);
  background: rgba(0, 177, 255, 0.1);
}

.scenario-choice:focus-visible {
  outline: 2px solid var(--color-accent-2);
  outline-offset: 2px;
}

.scenario-consequence {
  margin-top: var(--spacing-md);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border-left: 4px solid var(--color-deep-cerulean);
  border-radius: var(--radius-md);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-text-primary);
}

.scenario-consequence__label {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-deep-cerulean);
  margin-bottom: var(--spacing-xs);
}

/* ---- Toggle comparison (toggle-comparison.js) ---- */

.toggle-comparison {
  display: block;
  width: 100%;
}

.tc-line {
  margin: 0 0 var(--spacing-lg) 0;
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-md);
}

.tc-line__text {
  display: block;
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--color-text-primary);
}

.tc-line__speaker {
  display: block;
  margin-top: var(--spacing-xs);
  font-size: 0.85rem;
  font-style: normal;
  color: var(--color-text-muted);
}

.tc-switch {
  display: flex;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-md);
  flex-wrap: wrap;
}

.tc-tab {
  padding: 0.5rem 1rem;
  background: var(--color-off-white);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) var(--ease-out);
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-secondary);
}

.tc-tab:hover {
  border-color: var(--color-accent-2);
  color: var(--color-text-primary);
}

.tc-tab.active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-white);
}

.tc-tab:focus-visible {
  outline: 2px solid var(--color-accent-2);
  outline-offset: 2px;
}

.tc-panel {
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.tc-conclusion {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.6;
  color: var(--color-text-primary);
  margin: 0;
}

.tc-signals {
  margin: var(--spacing-md) 0 0 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.tc-signals__label {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 2px;
}

/* ---- Extraction builder (extraction-builder.js) ---- */

.extraction-builder {
  display: block;
  width: 100%;
}

.eb-fields {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--spacing-md) var(--spacing-lg);
  margin: 0 0 var(--spacing-md) 0;
}

.eb-legend {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: 0 var(--spacing-xs);
}

.eb-field,
.eb-flag {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-sm);
  padding: var(--spacing-sm) 0;
  cursor: pointer;
}

.eb-flag {
  margin-bottom: var(--spacing-lg);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-off-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.eb-field input,
.eb-flag input {
  margin-top: 0.2rem;
  width: 1rem;
  height: 1rem;
  accent-color: var(--color-deep-cerulean);
  flex: 0 0 auto;
  cursor: pointer;
}

.eb-field__body { display: block; }

.eb-field__label {
  display: block;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--color-text-primary);
}

.eb-field__note {
  display: block;
  margin-top: 2px;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--color-text-secondary);
}

.eb-output__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-xs);
  flex-wrap: wrap;
}

.eb-output__label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.prompt-code.eb-empty {
  color: var(--color-text-muted);
  font-style: italic;
}

.prompt-copy-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.prompt-copy-btn:disabled:hover {
  background: var(--color-off-white);
  color: var(--color-text-secondary);
  border-color: var(--color-border);
}

.eb-shapes { margin-top: var(--spacing-lg); }

.eb-shapes__label {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--spacing-sm);
}

.eb-shape {
  padding: var(--spacing-sm) var(--spacing-md);
  border-left: 3px solid var(--color-border);
  margin-bottom: var(--spacing-sm);
}

.eb-shape__field {
  display: block;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text-primary);
}

.eb-shape__example {
  display: block;
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

@media (max-width: 600px) {
  .eb-fields { padding: var(--spacing-sm) var(--spacing-md); }
  .eb-flag { padding: var(--spacing-sm) var(--spacing-md); }
}

/* ---- Inline Interactive Container ---- */

.section-interactive--inline {
  overflow: visible;
  padding: var(--spacing-lg);
}

.section-interactive--inline h3 {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-xs) 0;
}

.section-interactive--inline > p {
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin: 0 0 var(--spacing-md) 0;
}

.inline-interactive {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--spacing-sm) var(--spacing-md);
}
/* Keep any oversized interactive contained to the column on phones rather than
   forcing the whole page to scroll sideways; images scale, padding tightens. */
.inline-interactive > * { max-width: 100%; }
.inline-interactive img { max-width: 100%; height: auto; }
@media (max-width: 600px) {
  .section-interactive--inline { padding: var(--spacing-md); }
  .inline-interactive { padding: var(--spacing-xs) var(--spacing-sm); }
}
/* Interactive components are built for a white page — some hardcode light
   colours, some read the platform tokens (--ink, --surface, etc.). On the dark
   theme both broke: hardcoded dark text vanished on the Gable canvas, and
   token-based text (e.g. quiz options using --ink) turned white and was
   invisible until hover. Fix: render each interactive as a light "island" AND
   re-pin every theme token to its light value within the subtree, so the whole
   component renders exactly as it does in light mode. Literals are deliberate —
   this island is light regardless of the page theme. */
:root[data-theme="dark"] .inline-interactive:not([data-interactive="quiz"]):not([data-interactive="prompt"]) {
  background: #FFFFFF;
  color: #1B2F3C;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  padding: var(--spacing-md);
  --bg: #FFFFFF; --bg-deep: #F0F3F5; --surface: #FFFFFF; --surface-hover: #F8F9FA;
  --ink: #1B2F3C; --ink-soft: #5A6B7A; --ink-muted: #8A98A4;
  --line: #E2E8F0; --line-strong: rgba(27, 47, 60, 0.18);
  --accent: #007A5E; --accent-secondary: #00B1FF; --accent-cta: #0084B2; --ink-on-accent: #FFFFFF;
  --warn: #FF5F5F; --warn-bg: rgba(255, 95, 95, 0.08); --focus: #0084B2;
  --color-text-primary: #1B2F3C; --color-text-secondary: #575756; --color-text-muted: #6B7A88;
  --color-border: #E2E8F0; --color-white: #FFFFFF; --color-off-white: #F8F9FA;
  --color-accent-1-accessible: #007A5E; --color-accent-2-accessible: #0071A1;
}

/* Quiz and prompt are natively dark-themed (excluded from the light island
   above). Their base styles already flip with the theme tokens — these rules
   just add the dark-mode crispness the token defaults miss: a visible card
   edge, and an option surface that sits slightly proud of the card so the
   choices read as distinct, tappable rows. */
:root[data-theme="dark"] .section-quiz,
:root[data-theme="dark"] .section-prompt { border: 1px solid var(--color-border-dark); }
:root[data-theme="dark"] .quiz-option {
  background: rgba(255, 255, 255, 0.04);
  border-color: var(--color-border-dark);
}
:root[data-theme="dark"] .quiz-option:hover { border-color: var(--color-accent-2); background: rgba(0, 177, 255, 0.10); }
:root[data-theme="dark"] .prompt-code { border-color: var(--color-border-dark); }

/* ====================================================================
   14. RESPONSIVE DESIGN
   ==================================================================== */

/* ---- Tablet (640px - 1024px) ---- */

@media (max-width: 1024px) {
  .module-layout {
    grid-template-columns: 1fr;
  }

  .module-sidebar {
    position: fixed;
    top: 0;
    left: -100%;
    width: 280px;
    height: 100vh;
    z-index: 100;
    border-right: 1px solid var(--color-border);
    background: var(--color-white);
    transition: left var(--duration-normal) var(--ease-out);
    max-height: 100vh;
    overflow-y: auto;
    box-shadow: var(--shadow-lg);
  }

  .module-sidebar.open {
    left: 0;
  }

  .module-sidebar__overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(27, 47, 60, 0.3);
    backdrop-filter: blur(4px);
    z-index: 99;
    display: none;
  }

  .module-sidebar.open ~ .module-sidebar__overlay {
    display: block;
  }

  .modules-grid {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  }

  h1 {
    font-size: 2rem;
  }

  .hero__title {
    font-size: 2rem;
  }
}

/* ---- Mobile (< 640px) ---- */

@media (max-width: 640px) {
  :root {
    --spacing-lg: 1rem;
    --spacing-xl: 1.5rem;
    --spacing-2xl: 2rem;
  }

  body {
    font-size: 15px;
  }

  h1 {
    font-size: 1.75rem;
    margin-bottom: var(--spacing-lg);
  }

  h2 {
    font-size: 1.5rem;
  }

  h3 {
    font-size: 1.125rem;
  }

  /* Hero */
  .hero {
    padding: var(--spacing-xl) var(--spacing-lg);
  }

  .hero__title {
    font-size: 1.75rem;
  }

  .hero__subtitle {
    font-size: 1rem;
  }

  .hero__stat {
    display: inline-block;
    margin: 0 var(--spacing-md);
  }

  .hero__stat-number {
    font-size: 1.5rem;
  }

  /* Cards */
  .modules-grid {
    grid-template-columns: 1fr;
    gap: var(--spacing-lg);
  }

  .module-card {
    padding: var(--spacing-lg);
  }

  /* Video player */
  .video-player.floating {
    width: 120px;
    bottom: var(--spacing-md);
    right: var(--spacing-md);
  }

  /* Content */
  .content-main {
    padding: var(--spacing-xl) var(--spacing-lg);
  }

  .section-stat {
    grid-template-columns: 1fr;
  }

  .stat-card {
    padding: var(--spacing-lg);
  }

  .section-callout {
    flex-direction: column;
    gap: var(--spacing-md);
  }

  .section-callout__icon {
    margin: 0 auto;
  }

  .section-callout__content {
    text-align: center;
  }

  /* Prompt blocks */
  .prompt-header {
    flex-direction: column;
    gap: var(--spacing-xs);
  }

  .prompt-title {
    font-size: 1rem;
  }

  .prompt-code {
    font-size: 0.85rem;
    padding: var(--spacing-md);
  }

  /* Inline interactives */
  .section-interactive--inline {
    padding: var(--spacing-md);
  }

  .section-interactive--inline h3 {
    font-size: 1.05rem;
  }

  /* Completion */
  .completion-celebration {
    padding: var(--spacing-xl) var(--spacing-lg);
  }

  .completion-celebration__title {
    font-size: 1.5rem;
  }

  .completion-celebration__icon {
    font-size: 2.5rem;
  }
}

/* ====================================================================
   14. Utility & Accessibility
   ==================================================================== */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* Focus states for keyboard navigation */
button:focus-visible,
a:focus-visible,
.quiz-option:focus-visible {
  outline: 2px solid var(--color-accent-1);
  outline-offset: 2px;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Print styles */
@media print {
  .module-sidebar,
  .video-player,
  .module-header,
  .copy-btn {
    display: none;
  }

  .module-layout {
    grid-template-columns: 1fr;
  }

  body {
    background: var(--color-white);
  }
}

/* ====================================================================
   v2.4 ADDITIONS — Key Tips, File Video, Section Labels, Utilities
   ==================================================================== */

/* ---- Key Tips Section ---- */

.kt-box {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  margin: var(--spacing-xl) 0;
  box-shadow: var(--shadow-sm);
}

.kt-header {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-lg);
}

.kt-header-icon {
  width: 20px;
  height: 20px;
  color: var(--color-accent-1-accessible);
  flex-shrink: 0;
}

.kt-header span {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--color-accent-1-accessible);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.kt-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

.kt-item {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-sm);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.kt-icon {
  width: 16px;
  height: 16px;
  color: var(--color-accent-1-accessible);
  flex-shrink: 0;
  margin-top: 3px;
}

/* ---- File-provider video loops ---- */

.video-embed--file {
  margin: 0;
  padding: 0;
  display: block;
}

.video-loop {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
  border-radius: var(--radius-lg);
}

/* ---- Additional section-label variants ---- */

.section-label--quiz {
  background: rgba(0, 177, 255, 0.1);
  color: var(--color-accent-2-accessible);
}

.section-label--video {
  background: rgba(0, 122, 94, 0.12);
  color: var(--color-accent-1-accessible);
}

.section-label--stat {
  background: rgba(0, 177, 255, 0.1);
  color: var(--color-accent-2-accessible);
}

/* ---- Accessibility utility ---- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* ===== V2 Course Utility Menu (PRD §19.6, DESIGN.md §4) ==================
   Flag-gated menu shell on module.html. Renders only when at least one of
   the theming / recommendations / companion / presenter flags is on.
   Trigger sits to the left of the identity chip in the module header.
   With every flag off, js/course-utility-menu.js writes no DOM and these
   styles attach to nothing — the deployed platform is unchanged. */

[data-course-utility-menu] {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;   /* space between the hamburger and the standalone theme icon */
}

.util-menu__trigger,
.util-menu__theme-direct {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s;
}
.util-menu__trigger:hover,
.util-menu__trigger:focus-visible,
.util-menu__theme-direct:hover,
.util-menu__theme-direct:focus-visible {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.18);
  outline: none;
}
.util-menu__trigger:focus-visible,
.util-menu__theme-direct:focus-visible {
  box-shadow: 0 0 0 2px var(--focus);
}

/* The standalone sun/moon theme icon sits beside the course hamburger and is the
   single theme control (the in-dropdown item was removed to avoid duplication),
   so it is always shown. */
.util-menu__theme-direct { display: inline-flex; }

.util-menu__popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 260px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow-strong);
  padding: 8px 0;
  z-index: 1100;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
}
.util-menu__popover[hidden] { display: none; }
/* --surface is translucent in dark (rgba white .04) — the popover let the page
   show through and was hard to read. Use the opaque recessed surface. */
:root[data-theme="dark"] .util-menu__popover { background: var(--bg-deep); }

.util-menu__section {
  padding: 8px 14px 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.util-menu__divider {
  border: none;
  border-top: 1px solid var(--line);
  margin: 6px 0;
}

.util-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  height: 38px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  transition: background 0.14s, color 0.14s;
}
.util-menu__item:hover,
.util-menu__item:focus-visible {
  background: var(--bg-deep);
  outline: none;
}
.util-menu__item--active {
  color: var(--accent);
}
.util-menu__item[disabled],
.util-menu__item--disabled {
  color: var(--ink-muted);
  cursor: default;
}
.util-menu__item[disabled]:hover {
  background: transparent;
}

.util-menu__icon {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  opacity: 0.8;
}
.util-menu__icon svg {
  width: 18px;
  height: 18px;
}

.util-menu__label {
  flex: 1;
}


/* ===== Identity chip ===================================================== */

/* Container is the position anchor for the dropdown */
[data-account-chip] {
  position: relative;
  display: inline-flex;
  align-items: center;
}

/* ── Chip button ── */
.account-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 999px;
  color: #fff;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.account-chip:hover,
.account-chip:focus-visible {
  background: rgba(255,255,255,0.10);
  border-color: rgba(255,255,255,0.18);
  outline: none;
}

.account-chip__avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, #00FFBC 0%, #00B1FF 100%);
  color: #1B2F3C;
  font-weight: 600;
  font-size: 11px;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 1;
}

.account-chip__name {
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-chip__chevron {
  width: 14px;
  height: 14px;
  color: rgba(255,255,255,0.5);
  flex-shrink: 0;
  transition: transform 0.2s;
}
.account-chip[aria-expanded="true"] .account-chip__chevron {
  transform: rotate(180deg);
}

/* ── Dropdown menu ── */
.account-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 240px;
  background: var(--surface);
  border: 1px solid #E4E8EC; /* slightly cooler than --line (#E2E8F0); kept exact for zero visual change */
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  padding: 10px 0;
  z-index: 1100;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
}
.account-menu[hidden] { display: none; }
/* Menu items carry `display:flex`, which otherwise overrides the UA
   `[hidden]{display:none}` rule — so a flag-gated item (e.g. the
   recommendations retake link) needs this to honour the `hidden` attribute. */
.account-menu__item[hidden] { display: none; }

.account-menu__email {
  padding: 6px 16px 4px;
  font-size: 12px;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Inline name edit */
.account-menu__name-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 16px 8px;
}
.account-menu__name-display {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.account-menu__name-edit-btn {
  display: flex;
  align-items: center;
  padding: 3px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink-muted);
  border-radius: 4px;
  flex-shrink: 0;
  transition: color 0.15s, background 0.15s;
}
.account-menu__name-edit-btn:hover { color: var(--ink); background: var(--bg-deep); }

.account-menu__name-form {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
}
.account-menu__name-input {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  padding: 3px 8px;
  border: 1.5px solid var(--color-accent-2-accessible);
  border-radius: 6px;
  outline: none;
  color: var(--ink);
}
.account-menu__name-save {
  font-size: 12px;
  font-weight: 600;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  padding: 3px 10px;
  border: none;
  border-radius: 6px;
  background: #1B2F3C;
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s;
}
.account-menu__name-save:hover { background: #0A4A6B; }

.account-menu__divider {
  border: none;
  border-top: 1px solid #E4E8EC; /* matches the account-menu border above */
  margin: 6px 0;
}

/* ─── Paper-styled account (settings) menu — light mode only (PLA-29) ───
   The gear-icon dropdown shipped on cool white (--surface) with cool
   #E4E8EC borders/dividers and cool hover fills. Warm it to the paper
   palette: elevated surface popover, warm hairline + divider, warm hover.
   Guarded to light via :root:not([data-theme="dark"]) so the existing
   :root[data-theme="dark"] .account-menu overrides still own dark mode.
   Applies on every page since the nav (account-chip) is shared. */
:root:not([data-theme="dark"]) .account-menu { background: #FAF9F5; border-color: #E3DACC; }
:root:not([data-theme="dark"]) .account-menu__divider { border-top-color: #E3DACC; }
:root:not([data-theme="dark"]) .account-menu__item:hover { background: #F0EEE6; }
:root:not([data-theme="dark"]) .account-menu__name-edit-btn:hover { background: #F0EEE6; }
:root:not([data-theme="dark"]) .account-menu__name-input { background: #FAF9F5; }

.account-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  transition: background 0.14s;
}
.account-menu__item:hover { background: var(--surface-hover); }

/* Icon size guard — prevents inline SVGs from rendering at full canvas size */
.account-menu__item svg,
.account-menu__item i {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  opacity: 0.55;
}

.account-menu__item--signout { color: var(--ink-soft); }

/* Weekly-email toggle (PLA-9): push the On/Off state chip to the right. */
.account-menu__item--email .account-menu__email-state {
  margin-left: auto;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-soft);
}
.account-menu__item--email[aria-checked="true"] .account-menu__email-state {
  color: var(--accessible-turquoise, #007A5E);
}

/*
 * Mobile wayfinding section (PLA-87) — filled by js/nav-primary.js
 * renderMobileNav() into the [data-nav-mobile] placeholder in the menu.
 *
 * Hidden by default and revealed only below the breakpoint at which the nav's
 * own Guide / Blog / Admin / Views triggers go display:none — 768px, the same
 * value those rules use in index.html, module.html and nav-primary.js's injected
 * stylesheet. Keep the three in step: if the bar's collapse point moves and this
 * does not, the destinations exist in both places at once or in neither.
 *
 * `display: none` rather than emptying the container in JS, so there is one
 * breakpoint to reason about rather than a JS matchMedia listener that has to
 * agree with a media query.
 */
.account-menu__mobile { display: none; }
.account-menu__mobile .account-menu__item { padding-left: 16px; }
/* One line per row. The label and its "desktop only" note were wrapping onto a
   second line in a narrow menu, which made one row twice the height of its
   neighbours and read as a heading with something under it. */
.account-menu__item > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A mode that exists but cannot be opened on this device. Muted, no pointer,
   and the reason stated inline rather than left to be inferred from the grey. */
.account-menu__item.is-locked {
  color: var(--color-text-muted, #6B7A86); cursor: default;
}
.account-menu__item.is-locked:hover { background: transparent; }
.account-menu__note {
  font-style: normal; font-size: 0.72em; font-weight: 600;
  letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--color-text-muted, #6B7A86); opacity: 0.85;
}
/* Group heading. Restores the distinction the desktop bar's separate dropdown
   titles carried — "this lesson" actions vs guides about the modes — which is
   otherwise lost when both are flattened into one list. */
.account-menu__group {
  margin: 8px 0 2px;
  padding: 0 16px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ── Responsive ── */
@media (max-width: 768px) {
  .account-chip__name { display: none; }
  .account-chip { padding: 4px; gap: 0; }
  .account-menu__mobile { display: block; }
  /* The menu is anchored right:0 under a 36px gear at the edge of the viewport,
     and its 240px min-width was enough to push it off-screen on a 360px phone
     once these rows made it taller and wider. Cap it to the viewport instead. */
  .account-menu { min-width: 0; width: max-content; max-width: calc(100vw - 24px); }
}

/* ====================================================================
   Catalogue explorer (search + filters) — 2026-06-12
   Styled to the Use Case Library toolbar/chip/card language.
   ==================================================================== */
.xp-toolbar { display: flex; gap: var(--spacing-sm); flex-wrap: wrap; align-items: center; margin-bottom: var(--spacing-sm); }
.xp-toolbar input[type=search] {
  flex: 1 1 260px; min-width: 220px; padding: 0.7rem 1rem;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  font: inherit; font-size: 0.9rem; background: var(--color-white); color: var(--color-text-primary);
  transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.xp-toolbar input[type=search]:focus { outline: none; border-color: var(--color-accent-2); box-shadow: 0 0 0 3px rgba(0,177,255,0.18); }
.xp-chips { display: flex; gap: var(--spacing-sm); flex-wrap: wrap; }
.xp-chips button {
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0.45rem 0.85rem; border-radius: 99px; border: 1px solid var(--color-border);
  background: var(--color-white); color: var(--color-text-secondary); cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out); font-family: var(--font);
}
.xp-chips button:hover { border-color: var(--color-accent-2-accessible); color: var(--color-accent-2-accessible); }
.xp-chips button[aria-pressed=true] { background: var(--color-primary); color: var(--color-white); border-color: var(--color-primary); }
.xp-chips button:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.xp-row { display: flex; gap: var(--spacing-sm); flex-wrap: wrap; align-items: center; margin-bottom: var(--spacing-sm); }
.xp-row .xp-label { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); margin-right: 0.15rem; }
.xp-select-wrap select {
  font: inherit; font-size: 0.82rem; padding: 0.45rem 0.7rem; border-radius: var(--radius-md);
  border: 1px solid var(--color-border); background: var(--color-white); color: var(--color-text-primary); max-width: 240px;
}
.xp-clear {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  background: none; border: none; color: var(--color-accent-2-accessible); cursor: pointer; padding: 0.45rem 0.5rem; font-family: var(--font);
}
.xp-clear:hover { text-decoration: underline; }
.xp-count { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); margin: var(--spacing-sm) 0; }
.xp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--spacing-md); }
.xp-card {
  display: flex; flex-direction: column; gap: 0.55rem; background: var(--color-white);
  border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--spacing-lg);
  text-decoration: none; color: inherit; position: relative; overflow: hidden;
  transition: all var(--duration-normal) var(--ease-out);
}
.xp-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--gradient-accent); opacity: 0; transition: opacity var(--duration-normal) var(--ease-out); }
a.xp-card:hover { border-color: var(--color-accent-1-accessible); box-shadow: var(--shadow-md), var(--shadow-glow-subtle); transform: translateY(-4px); }
a.xp-card:hover::before { opacity: 1; }
.xp-card--soon { opacity: 0.78; }
.xp-card h3 { font-size: 1.05rem; font-weight: 700; line-height: 1.35; letter-spacing: -0.01em; color: var(--color-text-primary); margin: 0; }
.xp-desc { color: var(--color-text-secondary); font-size: 0.84rem; line-height: 1.55; flex: 1; margin: 0; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.xp-crumb { font-size: 0.72rem; font-weight: 600; color: var(--color-text-muted); }
.xp-badges { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }
.xp-badge { display: inline-block; padding: 0.22rem 0.65rem; border-radius: var(--radius-sm); font-size: 0.66rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.xp-badge--knowledge  { background: rgba(0,177,255,0.10);  color: var(--color-accent-2-accessible); }
.xp-badge--techniques { background: rgba(97,97,255,0.10);  color: #6161FF; }
.xp-badge--tools      { background: rgba(23,206,149,0.12); color: var(--color-accent-1-accessible); }
.xp-badge--usecases   { background: rgba(255,159,28,0.14); color: #B36200; }
.xp-soon { font-size: 0.66rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); border: 1px dashed var(--color-border); border-radius: 99px; padding: 0.2rem 0.6rem; }
.xp-meta { display: flex; gap: 0.4rem; flex-wrap: wrap; border-top: 1px solid var(--color-border); padding-top: 0.6rem; }
.xp-meta-pill { font-size: 0.68rem; font-weight: 600; color: var(--color-text-secondary); background: var(--color-off-white); border-radius: 99px; padding: 0.18rem 0.6rem; }
.xp-more { grid-column: 1 / -1; text-align: center; color: var(--color-text-muted); font-size: 0.85rem; }

/* "For you" recommended filter chip + reason line on result cards */
.xp-foryou {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0.45rem 0.95rem; border-radius: 99px; border: 1px solid var(--color-accent-1-accessible);
  background: var(--color-white); color: var(--color-accent-1-accessible); cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out); font-family: var(--font);
}
.xp-foryou:hover { background: rgba(23,206,149,0.10); }
.xp-foryou[aria-pressed=true] { background: var(--gradient-accent); color: var(--color-primary); border-color: transparent; box-shadow: var(--shadow-glow-subtle); }
.xp-foryou:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.xp-reason { font-size: 0.78rem; font-style: italic; color: var(--color-accent-1-accessible); line-height: 1.45; margin: 0; }

/* ====================================================================
   Knowledge-graph catalogue — Obsidian-style library view (2026-06-12)
   Dark Gable Green surface; node colours from the dark-bg brand palette.
   ==================================================================== */
/* Stage height, as ONE token. The preview card is the stage's sibling in a
   stretch flex row, so it takes the row's height for free — but it carried its
   own, smaller clamp as a max-height, which cropped it short of the stage and
   left the two surfaces mismatched. Both read this now, so they cannot drift. */
:root { --kg-stage-h: clamp(560px, 82vh, 1100px); }
.kg-wrap {
  position: relative;
  height: var(--kg-stage-h);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--gradient-hero);
  border: 1px solid var(--color-border-dark);
  box-shadow: var(--shadow-lg);
}
/* Give the stage the whole viewport width (minus a gutter), breaking out of
   the 1280px container — the constellation and the trail both earn the room.
   The search/filter toolbar breaks out to the SAME width so the two surfaces
   read as one aligned column in Graph view. */
body.view-explore .kg-layout,
body.view-explore #exploreToolbar,
/* Catalogue view breaks out to the SAME width as the graph so the toolbar and
   course grid line up with the graph's (and the nav's) left/right edges. */
body.view-browse #exploreToolbar,
body.view-browse #modulesGrid,
body.view-browse #allModulesHead,
/* Use Cases & Skills view breaks out to the SAME width as the catalogue so the
   two views line up edge-to-edge when switching between them. */
body.view-usecases #useCasesView,
/* Glossary too, so its left edge lands where every other view's does. Its own
   children stay capped at a reading width (see #glossaryView > * below). */
body.view-glossary #glossaryView,
/* And Requests, whose own children are capped the same way. */
body.view-requests #requestsView,
/* And Activities. Unlike the two above it takes no `> *` reading cap: a grid of
   cards wants the full breakout, and the one block of prose on it caps itself. */
body.view-activities #activitiesView {
  width: min(96vw, 1760px);
  margin-left: calc(50% - min(48vw, 880px));
}
.kg-wrap::before {
  content: '';
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at 22% 12%, rgba(0,255,188,0.07), transparent 55%),
              radial-gradient(ellipse at 82% 88%, rgba(0,177,255,0.09), transparent 55%);
}
#kgCanvas { position: absolute; inset: 0; cursor: grab; touch-action: none; }
#kgCanvas:active { cursor: grabbing; }
.kg-legend {
  position: absolute; top: 14px; left: 16px; display: flex; gap: 0.9rem; align-items: center;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: rgba(255,255,255,0.78); flex-wrap: wrap; pointer-events: none;
}
.kg-legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.kg-legend i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.kg-reset {
  pointer-events: auto; margin-left: 0.4rem;
  font: 600 0.7rem/1 var(--font); letter-spacing: 0.05em; text-transform: uppercase;
  color: rgba(255,255,255,0.85); background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.25); border-radius: 99px; padding: 0.38rem 0.8rem; cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}
.kg-reset:hover { background: rgba(255,255,255,0.16); }
/* Which hint applies is a question about the INPUT DEVICE, not screen width —
   a small laptop window still has a keyboard and a wheel, a large tablet has
   neither. `pointer: coarse` asks the right question. */
.kg-hint--touch { display: none; }
@media (pointer: coarse) {
  .kg-hint--pointer { display: none; }
  .kg-hint--touch { display: block; }
}
.kg-hint {
  position: absolute; bottom: 12px; left: 16px; right: 16px;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.05em;
  color: rgba(255,255,255,0.45); pointer-events: none;
}
.kg-layout { display: flex; gap: var(--spacing-md); align-items: stretch; }
.kg-layout .kg-wrap { flex: 1 1 auto; min-width: 0; }

/* Lesson loading screen — full-page cover (theme-aware) shown while a lesson
   assembles; engine.js fades it out once the first lesson has rendered. */
.lesson-loading {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: var(--bg);
  transition: opacity 0.35s var(--ease-out, ease);
}
.lesson-loading.is-hidden { opacity: 0; pointer-events: none; }
.lesson-loading__spinner {
  width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  animation: lessonSpin 0.8s linear infinite;
}
.lesson-loading__label {
  font: 600 0.78rem/1 var(--font, 'Poppins', sans-serif);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted);
}
@keyframes lessonSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .lesson-loading__spinner { animation: none; } }

/* Catalogue loading state — spans the whole modules grid while the catalogue
   and every module's detail JSON load, so cards render in one pass instead of
   popping in (and re-rendering) as data arrives. */
.catalogue-loading {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; min-height: 240px; padding: 56px 0;
}
.catalogue-loading__spinner {
  width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  animation: lessonSpin 0.8s linear infinite;
}
.catalogue-loading__label {
  font: 600 0.78rem/1 var(--font, 'Poppins', sans-serif);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted);
}
@media (prefers-reduced-motion: reduce) { .catalogue-loading__spinner { animation: none; } }

/* Graph loading screen — covers the stage on the Gable canvas until the layout
   is built and settled, then fades out (the graph reveals already laid out). */
.kg-loading {
  position: absolute; inset: 0; z-index: 6;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: var(--gradient-hero);
  transition: opacity 0.4s var(--ease-out, ease);
}
.kg-loading.is-hidden { opacity: 0; pointer-events: none; }
.kg-loading__spinner {
  width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.15);
  border-top-color: var(--color-accent-1, #00FFBC);
  animation: kgSpin 0.8s linear infinite;
}
.kg-loading__label {
  font: 600 0.78rem/1 var(--font, 'Poppins', sans-serif);
  letter-spacing: 0.1em; text-transform: uppercase; color: rgba(255, 255, 255, 0.72);
}
@keyframes kgSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .kg-loading__spinner { animation: none; } }
.kg-preview {
  flex: 0 0 320px;
  max-height: var(--kg-stage-h);   /* same height as the stage beside it */
  overflow: auto;
  background: var(--gradient-hero); color: var(--color-white);
  border: 1px solid var(--color-border-dark);
  border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
  padding: var(--spacing-lg);
  display: flex; flex-direction: column; gap: 0.6rem;
  position: relative;
  animation: kg-slide 220ms var(--ease-out);
}
.kg-preview[hidden] { display: none; }
.kg-reason { font-size: 0.8rem; font-style: italic; color: var(--color-accent-1-accessible); margin: 0; }
@keyframes kg-slide { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
.kg-close {
  position: absolute; top: 10px; right: 12px;
  background: none; border: 0; font-size: 1.5rem; line-height: 1;
  color: var(--color-text-muted); cursor: pointer; padding: 4px;
}
.kg-close:hover { color: var(--color-text-primary); }
.kg-kicker {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-text-secondary);
  border-left: 5px solid var(--kg-accent, var(--color-accent-2)); padding-left: 0.6rem;
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.kg-preview h3 { font-size: 1.2rem; font-weight: 700; line-height: 1.3; letter-spacing: -0.01em; margin: 0; color: var(--color-text-primary); }
.kg-crumb { font-size: 0.72rem; font-weight: 600; color: var(--color-text-muted); }
.kg-preview p { font-size: 0.86rem; line-height: 1.6; color: var(--color-text-secondary); margin: 0; flex: 1; }
.kg-meta { font-size: 0.74rem; font-weight: 600; color: var(--color-text-muted); border-top: 1px solid var(--color-border); padding-top: 0.6rem; }
.kg-soon {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.06em;
  color: var(--color-text-muted); border: 1px dashed var(--color-border);
  border-radius: 99px; padding: 0.14rem 0.5rem;
}
.kg-cta {
  display: block; text-align: center; text-decoration: none;
  background: var(--color-deep-cerulean, #0084B2); color: var(--color-white);
  font-size: 0.85rem; font-weight: 600; border-radius: var(--radius-md);
  padding: 0.7rem 1rem; transition: filter var(--duration-fast) var(--ease-out);
}
.kg-cta:hover { filter: brightness(1.08); }
.kg-cta--disabled { background: var(--color-border); color: var(--color-text-muted); cursor: default; }
@media (max-width: 760px) {
  .kg-wrap { height: 64vh; }
  .kg-layout { flex-direction: column; }
  .kg-preview { flex: 0 0 auto; max-height: none; }
}

/* Domain tags on the graph preview card */
.kg-domains { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.kg-domains span {
  font-size: 0.66rem; font-weight: 600; letter-spacing: 0.04em; text-transform: capitalize;
  color: var(--color-accent-1-accessible); background: rgba(23,206,149,0.10);
  border-radius: 99px; padding: 0.18rem 0.6rem;
}

/* Course cards replaced by the knowledge graph: the grid stays in the DOM
   (progress + continue-banner logic reads it) but must never render.
   The .modules-grid{display:grid} rule beats the hidden attribute, hence !important. */
body.view-explore #modulesGrid { display: none !important; }
body.view-browse .kg-layout { display: none !important; }

/* Use Cases & Skills view: hide both catalogue surfaces and the lesson
   search toolbar, and reveal the use-case library. The library is hidden
   by default so it never shows in Graph or Catalogue view. */
#useCasesView { display: none; }
body.view-usecases #useCasesView { display: block; }
body.view-usecases .kg-layout,
body.view-usecases #modulesGrid,
body.view-usecases #requestsView,
body.view-usecases #exploreToolbar { display: none !important; }

/* Glossary view (PLA-104): the central glossary + FAQ. Hidden by default so it
   never shows in the three catalogue views; hides every catalogue surface and
   the lesson search toolbar when active. */
#glossaryView { display: none; }
body.view-glossary #glossaryView { display: block; }
body.view-glossary .kg-layout,
body.view-glossary #modulesGrid,
body.view-glossary #useCasesView,
body.view-glossary #requestsView,
body.view-glossary #exploreToolbar { display: none !important; }

/* Requests view (PLA-87): the learner's own lesson requests. Same shape as the
   glossary gate — hidden unless its view is on, and it hides every catalogue
   surface plus the filter readout, which has nothing to say about requests.
   #requestsView's own display:block lives in the styles js/requests-view.js
   injects, per DESIGN.md §6.3 (a surface brings its own styles); what has to be
   here is the mutual exclusion with the views declared above it. */
body.view-requests .kg-layout,
body.view-requests #modulesGrid,
body.view-requests #useCasesView,
body.view-requests #glossaryView,
body.view-requests #allModulesHead,
body.view-requests #exploreToolbar { display: none !important; }

/* Activities view (PLA-85): the workshop activities a room can run. Same shape
   as the two gates above it. Only the !important overrides need to be here —
   the views themselves are `display: none` by default and are switched on by
   their own body class, so they do not have to be named in each other's lists.
   #activitiesView's own display pair lives in the styles js/activities-view.js
   injects, per DESIGN.md §6.3 (a surface brings its own styles). */
body.view-activities .kg-layout,
body.view-activities #modulesGrid,
body.view-activities #useCasesView,
body.view-activities #glossaryView,
body.view-activities #requestsView,
body.view-activities #allModulesHead,
body.view-activities #exploreToolbar { display: none !important; }
#requestsView > * { max-width: 900px; }

/* ---- Glossary view surfaces (js/glossary-view.js) ----
   Reference reading, so the column stays narrow rather than breaking out to the
   catalogue's full width. Chrome follows the catalogue's existing language
   (.xp-toolbar search field, card surface + border tokens); the mono letter
   rails pick up the index motif introduced with the view band. */
/* The panel breaks out to the catalogue's width (see the breakout rule above) so
   its left edge lines up, but definitions are prose — cap each child at a
   readable measure rather than letting lines run 1760px wide. */
#glossaryView > * { max-width: 900px; }
.gl-subswitch {
  display: inline-flex; gap: 4px; padding: 3px; margin-bottom: var(--spacing-md);
  border: 1px solid var(--color-border); border-radius: 999px;
}
.gl-subbtn {
  appearance: none; border: 0; border-radius: 999px;
  padding: 6px 18px; cursor: pointer; background: transparent;
  font: 600 0.82rem/1.4 var(--font); color: var(--ink-muted);
  transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.gl-subbtn:hover { color: var(--ink); }
.gl-subbtn.is-active { background: var(--color-primary); color: #fff; }
.gl-subbtn:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }

/* A–Z rail. Letters with no terms stay visible but inert, so the rail keeps a
   stable shape as the library grows. */
.gl-alpha {
  display: flex; flex-wrap: wrap; gap: 2px;
  margin: 0.6rem 0 0.2rem;
}
/* Buttons now, not anchors: the rail filters the list rather than scrolling to
   a heading inside it, so it needs a pressed state to show which letter is on. */
.gl-alpha__l {
  font: 700 0.72rem/1 var(--font-mono);
  min-width: 22px; padding: 5px 0; text-align: center;
  border-radius: 4px; text-decoration: none;
  color: var(--color-accent-2-accessible);
  background: none; border: 0; cursor: pointer;
}
button.gl-alpha__l:hover { background: var(--color-off-white); color: var(--ink); }
button.gl-alpha__l:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 1px; }
.gl-alpha__l.is-on { background: var(--color-accent-2-accessible); color: var(--color-white); }
.gl-alpha__all { min-width: auto; padding: 5px 8px; }
.gl-alpha__l.is-empty { color: var(--ink-muted); opacity: 0.4; cursor: default; }

.gl-group { margin-top: var(--spacing-lg); }
.gl-group__head {
  font: 700 1.1rem/1 var(--font-mono);
  color: var(--ink);
  padding-bottom: 8px; margin-bottom: 4px;
  border-bottom: 2px solid var(--color-border);
}
.gl-list { margin: 0; }
.gl-term {
  padding: 16px 0;
  border-bottom: 1px solid var(--color-border);
}
.gl-term:last-child { border-bottom: 0; }
.gl-term__name {
  font-weight: 700; font-size: 1rem; color: var(--ink);
  letter-spacing: -0.01em; margin-bottom: 4px;
}
/* A term defined differently by different courses (e.g. "Deep Research"). */
.gl-term__senses {
  font: 600 0.68rem/1 var(--font); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-muted); margin-left: 0.5ch;
}
.gl-def {
  margin: 0 0 6px; font-size: 0.92rem; line-height: 1.6;
  color: var(--ink-soft);
}
.gl-def:last-child { margin-bottom: 0; }
.gl-courses { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.gl-course {
  font: 600 0.66rem/1 var(--font); letter-spacing: 0.03em;
  color: var(--color-accent-1-accessible); background: rgba(23,206,149,0.10);
  border-radius: 99px; padding: 4px 9px;
}
.gl-empty { color: var(--ink-muted); font-size: 0.92rem; padding: 1.5rem 0; }

.gl-faq { margin-top: 0.4rem; }
.gl-q {
  background: var(--color-white);
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  padding: 12px 16px; margin-bottom: 10px;
}
.gl-q > summary {
  cursor: pointer; list-style: none;
  font-weight: 600; font-size: 0.95rem; color: var(--ink);
  display: flex; align-items: baseline; gap: 10px;
}
.gl-q > summary::-webkit-details-marker { display: none; }
.gl-q > summary::before {
  content: '+'; flex: 0 0 auto;
  font: 700 0.95rem/1.4 var(--font-mono); color: var(--color-accent-2-accessible);
}
.gl-q[open] > summary::before { content: '\2212'; }
.gl-q > summary:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.gl-q__body { padding: 8px 0 2px 22px; }
.gl-q__body p { font-size: 0.92rem; line-height: 1.6; color: var(--ink-soft); }

:root[data-theme="dark"] .gl-course {
  color: var(--color-accent-1); background: rgba(0,255,188,0.12);
}
:root[data-theme="dark"] .gl-alpha__l { color: var(--color-accent-2); }

/* ─── View band (PLA-104; toolbar reshaped in PLA-87) ─────────────────────────
   The library views AND the controls that act on them, in one full-width row
   anchored directly under the hero: views left, then search / filter / the
   primary action right-aligned.

   Modelled on Notion's database toolbar. The layout problem is the same one
   they solved: an unbounded set of views plus a fixed set of actions, on a
   viewport that may be 390px wide. Their answer, and now ours, is that the
   views collapse and the actions do not — below --vb-collapse the tab row is
   swapped for a single "current view" dropdown (.view-band__pill), because a
   learner needs one view at a time but needs every action all the time.

   The previous mobile treatment was `overflow-x: auto` on the tab row, which is
   why this changed: a horizontal scroller inside a vertically-scrolling page
   hides its own overflow. Glossary was off the right edge with nothing to
   indicate it was there. */
.view-band {
  background: var(--color-white);
  border-bottom: 1px solid var(--color-border);
  position: relative;
  /* Above the toolbar's own facet menus (z-index 40), because the band's
     dropdowns are children of this stacking context and would otherwise be
     painted over by them. Still well under the fixed navbar's 1000 — the band
     scrolls, so it never needs to compete with it. */
  z-index: 60;
  box-shadow: var(--shadow-sm);
}
/* Matches the nav / graph / catalogue column so every left and right edge on
   the page lines up. */
.view-band__inner {
  width: min(96vw, 1760px);
  margin: 0 auto;
  display: flex;
  align-items: stretch;
  gap: 6px;
}
.view-band__tabs { display: flex; align-items: stretch; gap: 6px; min-width: 0; }
/* The collapsed pill is the mobile half of the pair; the media query at the end
   of this block swaps which of the two is displayed. */
.view-band__pill { display: none; }
.view-tab {
  display: flex; align-items: center; gap: 9px;
  font: 600 0.85rem/1 var(--font);
  color: var(--ink-soft); background: transparent;
  border: 0; border-bottom: 3px solid transparent;
  padding: 17px 18px 15px;
  cursor: pointer; position: relative;
  transition: color var(--duration-fast) var(--ease-out);
}
.view-tab__idx {
  font-family: var(--font-mono);
  font-size: 0.7rem; font-weight: 700;
  color: var(--color-accent-2-accessible);
  transition: all var(--duration-fast) var(--ease-out);
}
.view-tab:hover { color: var(--ink); }
.view-tab[aria-pressed=true] { color: var(--ink); }
/* The gradient underline sits on the band's own bottom border, inset from the
   tab's padding so it reads as an underline for the label, not the whole hit
   area. */
.view-tab[aria-pressed=true]::after {
  content: '';
  position: absolute; left: 12px; right: 12px; bottom: -1px;
  height: 3px; background: var(--gradient-accent);
}
.view-tab[aria-pressed=true] .view-tab__idx {
  color: var(--ink);
  background: var(--color-accent-1);
  padding: 3px 5px 2px;
  border-radius: 4px;
  box-shadow: 1.5px 1.5px 0 rgba(0,177,255,0.6);
}
.view-tab:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: -2px; }
.view-band__spacer { flex: 1; }
.view-band__divider {
  align-self: center; height: 22px;
  border-left: 2px dotted var(--color-border);
  margin: 0 6px;
}
/* Glossary and Requests read as reference and personal, not peer catalogue
   views — muted until active. */
.view-tab--ref { color: var(--ink-muted); }
.view-tab--ref .view-tab__idx { color: var(--ink-muted); }

/* ── The action side of the band ──────────────────────────────────────────── */
.view-band__tools {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 0 8px 8px;
  min-width: 0;
}
/* Use Cases now uses the SAME two controls rather than its own flat toolbar
   below the switch — its search input and its facet row moved into the band, and
   which set is shown is decided here. Glossary keeps its own toolbar (it filters
   terms, not the lesson index) and Requests has nothing to filter, so for those
   two the icons still go and the primary action stays. */

/* One search field visible at a time. Both keep their ids and their own
   bindings; only visibility moves. */
.vb-search__input--uc { display: none; }
body.view-usecases .vb-search__input:not(.vb-search__input--uc) { display: none; }
body.view-usecases .vb-search__input--uc { display: block; }
body.view-usecases .vb-search.is-open .vb-search__input--uc { display: block; }

/* Same for the two panel bodies. */
.vb-panel__body--uc { display: none; }
body.view-usecases .vb-panel__body:not(.vb-panel__body--uc) { display: none; }
body.view-usecases .vb-panel__body--uc { display: block; }
/* "Clear all filters" is wired to the catalogue's state, so it does not belong
   over the Use Cases facets — their chips row is the way out there. */
body.view-usecases .vb-panel__foot { display: none; }

body.view-glossary .view-band__tools > .vb-search,
body.view-glossary .view-band__tools > #vbFilterToggle,
body.view-requests .view-band__tools > .vb-search,
body.view-requests .view-band__tools > #vbFilterToggle,
body.view-activities .view-band__tools > .vb-search,
body.view-activities .view-band__tools > #vbFilterToggle { display: none; }

/* Icon buttons: 34px square, quiet until they have something to say. */
.vb-icon {
  position: relative;
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  background: transparent; border: 1px solid transparent;
  border-radius: var(--radius-md, 8px);
  color: var(--ink-soft); cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.vb-icon:hover { background: var(--color-off-white); color: var(--ink); }
.vb-icon:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.vb-icon[aria-expanded="true"] { background: var(--color-off-white); color: var(--ink); }
/* Collapsing a control to an icon removes the thing that used to show its
   state, so an active one has to say so: tinted, plus a count. */
.vb-icon.is-active { color: var(--color-accent-2-accessible); background: rgba(0,177,255,0.10); }
.vb-icon__count {
  position: absolute; top: -3px; right: -3px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 0.62rem/1 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--color-white); background: var(--color-accent-2-accessible);
  border-radius: 999px;
}
.vb-icon__count[hidden] { display: none; }

/* Search: an icon that grows into a field, in place. The field is width-0 and
   padding-0 rather than display:none so the growth animates and so the input
   stays focusable the instant it opens. */
.vb-search { display: flex; align-items: center; min-width: 0; }
.vb-search__input {
  width: 0; min-width: 0; padding: 0; border: 1px solid transparent;
  opacity: 0; pointer-events: none;
  font: 400 0.88rem/1 var(--font);
  color: var(--ink); background: var(--color-off-white);
  border-radius: 99px;
  transition: width var(--duration-med, 220ms) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out),
              padding var(--duration-med, 220ms) var(--ease-out);
}
.vb-search.is-open .vb-search__input {
  width: clamp(180px, 32vw, 340px);
  /* Clear of the icon that opened it. Flush, the field's border and focus ring
     ran into the button and the two read as one broken control. Applied only
     when open, so the collapsed state keeps the icon tight to its neighbour. */
  margin-left: 6px;
  padding: 0.55rem 0.9rem;
  opacity: 1; pointer-events: auto;
  border-color: var(--color-border);
}
.vb-search__input:focus { outline: none; border-color: var(--color-accent-2); box-shadow: 0 0 0 3px rgba(0,177,255,0.15); }
.vb-search__input::-webkit-search-decoration { -webkit-appearance: none; }
.vb-search.is-active #vbSearchToggle { color: var(--color-accent-2-accessible); }

/* ── The primary action (js/lesson-request.js) ─────────────────────────────
   Was a flat --color-accent-2-accessible split button: Notion's shape and
   Notion's blue, sitting in a band where nothing else looked like that. The
   platform already has a fill for "this is the primary thing here" — the
   teal-to-blue accent gradient used on the active view underline, the "For you"
   toggle when it is on, and the assistant's send button. This uses that.

   Built from --color-accent-1-accessible → --color-accent-2-accessible rather
   than hardcoded stops, because those two tokens FLIP with the theme: deep
   green-to-blue on white, bright teal-to-blue on the dark surface. Paired with
   --ink-on-accent, which flips the other way, the button gets the right fill and
   readable text in both themes from one declaration and needs no dark override.

   The radius stays --radius-md to match .vb-icon beside it. A pill would have
   been more "brand", and wrong: it is a neighbour of the band's other controls
   before it is an example of the brand. */
.vb-new {
  display: flex; align-items: stretch; position: relative; flex: none;
  border-radius: var(--radius-md, 8px);
  /* The gradient lives on the WRAPPER so it runs once across both halves. Two
     backgrounds would each restart it and leave a seam down the middle. */
  background: linear-gradient(135deg,
              var(--color-accent-1-accessible) 0%,
              var(--color-accent-2-accessible) 100%);
  transition: box-shadow var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}
.vb-new:hover { box-shadow: var(--shadow-glow-subtle); }
.vb-new:active { transform: translateY(1px); }
.vb-new__main,
.vb-new__more {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 34px; padding: 0 13px;
  font: 600 0.82rem/1 var(--font);
  color: var(--ink-on-accent); background: transparent;
  border: 0; cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.vb-new__main { border-radius: var(--radius-md, 8px) 0 0 var(--radius-md, 8px); }
.vb-new__more { padding: 0 7px; border-radius: 0 var(--radius-md, 8px) var(--radius-md, 8px) 0; position: relative; }
/* A hairline in the text colour, so it reads on the deep fill and the bright one
   alike — a white rule was invisible against dark-on-teal. Inset top and bottom
   so it separates the halves without cutting the control in two. */
.vb-new__more::before {
  content: ''; position: absolute; left: 0; top: 7px; bottom: 7px; width: 1px;
  background: currentColor; opacity: 0.3;
}
/* Which half you are about to press. A translucent BLACK darkens both the deep
   and the bright fill, where brightness() washed the gradient out and lightened
   one theme while flattening the other. */
.vb-new__main:hover, .vb-new__more:hover { background-color: rgba(0,0,0,0.13); }
.vb-new__main:focus-visible, .vb-new__more:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.vb-new__main svg, .vb-new__more svg { width: 15px; height: 15px; flex: none; }
.vb-new__menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  min-width: 200px; padding: 6px;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md, 8px);
  box-shadow: var(--shadow-strong, 0 12px 32px rgba(27,47,60,0.16));
}
.vb-new__menu[hidden] { display: none; }
.vb-new__menu button {
  display: block; width: 100%; text-align: left;
  padding: 8px 10px; border: 0; border-radius: 6px;
  font: 500 0.85rem/1.3 var(--font); color: var(--ink);
  background: transparent; cursor: pointer;
}
.vb-new__menu button:hover { background: var(--color-off-white); }
.vb-new__menu button:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: -2px; }

/* ── The filter panel: popover on desktop, bottom sheet on mobile ─────────── */
.vb-panel {
  position: absolute; top: 100%; right: max(2vw, calc((100vw - 1760px) / 2));
  z-index: 60;
  width: min(94vw, 640px);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg, 12px);
  box-shadow: var(--shadow-strong, 0 12px 32px rgba(27,47,60,0.16));
  margin-top: 6px;
}
.vb-panel[hidden] { display: none; }
.vb-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--color-border);
}
.vb-panel__title {
  font: 700 0.7rem/1 var(--font); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-text-muted);
}
.vb-panel__close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: transparent; border: 0; border-radius: 6px;
  color: var(--ink-soft); cursor: pointer;
}
.vb-panel__close:hover { background: var(--color-off-white); color: var(--ink); }
.vb-panel__close:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.vb-panel__body { padding: 14px; }
.vb-panel__body .xp-row { margin-bottom: 0; }
.vb-panel__foot {
  display: flex; justify-content: flex-end;
  padding: 0 14px 14px;
}
/* Nothing to justify a footer's own padding when its only child is hidden. */
.vb-panel__foot:has(> .xp-clear[hidden]) { padding: 0; }

/* ── The mobile view dropdown ─────────────────────────────────────────────── */
.view-band__pill {
  align-self: center;
  display: none;              /* → flex below the collapse breakpoint */
  align-items: center; gap: 8px;
  padding: 7px 12px; margin: 8px 0;
  background: var(--color-off-white);
  border: 1px solid transparent; border-radius: 99px;
  font: 600 0.85rem/1 var(--font); color: var(--ink);
  cursor: pointer; min-width: 0;
}
.view-band__pill:hover { background: var(--color-white); border-color: var(--color-border); }
.view-band__pill:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.view-band__pill svg { flex: none; }
.view-band__pill-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.view-band__pill[aria-expanded="true"] .view-band__pill-chev { transform: rotate(180deg); }
.view-band__pill-chev { transition: transform var(--duration-fast) var(--ease-out); }

.vb-sheet {
  position: absolute; top: 100%; left: max(2vw, calc((100vw - 1760px) / 2));
  z-index: 60; min-width: 220px; padding: 6px; margin-top: 4px;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg, 12px);
  box-shadow: var(--shadow-strong, 0 12px 32px rgba(27,47,60,0.16));
}
.vb-sheet[hidden] { display: none; }
.vb-sheet__row {
  display: flex; align-items: flex-start; gap: 11px;
  width: 100%; text-align: left;
  padding: 11px 12px; border: 0; border-radius: 8px;
  font: 500 0.9rem/1.3 var(--font); color: var(--ink);
  background: transparent; cursor: pointer;
}
.vb-sheet__ico { flex: 0 0 auto; width: 1.15rem; height: 1.15rem; margin-top: 1px; opacity: 0.7; }
.vb-sheet__text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* The sentence is the point: five one-word labels said nothing about which view
   to open, and two of the names only mean something once you have seen them. */
.vb-sheet__desc {
  font-weight: 400; font-size: 0.76rem; line-height: 1.35; color: var(--ink-muted);
}
.vb-sheet__row.is-current .vb-sheet__ico { opacity: 1; }
.vb-sheet__row:hover { background: var(--color-off-white); }
.vb-sheet__row:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: -2px; }
.vb-sheet__row.is-current { font-weight: 700; background: rgba(0,177,255,0.09); color: var(--color-accent-2-accessible); }
/* The description must not take the current row's accent colour — it is
   secondary text, and tinting it made the row read as two headings. */
.vb-sheet__row.is-current .vb-sheet__desc { color: var(--ink-muted); font-weight: 400; }

/*
 * The collapse breakpoint.
 *
 * 900px, matching the value this band already used, and chosen for content
 * rather than a device: five tabs plus three actions stop fitting the
 * min(96vw, 1760px) column somewhere around there. Tablets land on the mobile
 * treatment, which is correct — the tab row would overflow on them too.
 */
@media (max-width: 900px) {
  .view-band__inner { width: 100%; padding: 0 10px; gap: 4px; }
  .view-band__tabs { display: none; }
  .view-band__pill { display: inline-flex; }
  .view-band__tools { padding: 8px 0; gap: 4px; }
  /* Just the plus, per Notion's phone layout. */
  .vb-new__label { display: none; }
  .vb-new__main { padding: 0 11px; }
  /*
   * Search takes the row when open, by DISPLACING the view pill rather than
   * covering it.
   *
   * The first attempt absolutely positioned the open field across the whole row.
   * That covered the filter icon — and because the field deliberately stays open
   * while it holds a query (see syncBandTools in js/explore.js), the filter
   * became permanently unreachable the moment you searched anything on a phone.
   * Notion gets away with an overlay because its search has a Cancel button; ours
   * does not, so the right answer is to give the field the pill's space and leave
   * every action where it was.
   *
   * Driven by a class from JS rather than `:has(.vb-search.is-open)` so the rule
   * does not depend on selector support for something this load-bearing.
   */
  .view-band.is-searching .view-band__pill,
  .view-band.is-searching .view-band__spacer { display: none; }
  .view-band.is-searching .view-band__tools { flex: 1; min-width: 0; }
  .vb-search.is-open { flex: 1; min-width: 0; }
  .vb-search.is-open .vb-search__input {
    width: 100%; flex: 1 1 auto; min-width: 0;
    padding: 0.5rem 0.7rem;
  }

  /* ANCHORED, not a bottom sheet. #395 made both of these sheets on the
     reasoning that a 640px popover cannot fit under a 34px icon at 390px — true
     of a 640px popover, so the panel is narrowed instead of relocated. A control
     that opens at the opposite end of the screen from the button you pressed
     does not read as that button's menu, and the facets inside it were reported
     as doing nothing at all.
     Right-aligned to the band, which is the edge the icon sits on. */
  .vb-panel {
    position: absolute; top: 100%; right: max(2vw, 8px); left: auto; inset: auto;
    top: 100%;
    width: min(22rem, calc(100vw - 2rem));
    max-height: min(70vh, 30rem); overflow-y: auto; overscroll-behavior: contain;
    margin: 4px 0 0; border-radius: var(--radius-lg, 12px);
    padding-bottom: 0;
    z-index: 1200;            /* over the fixed navbar */
  }
  .vb-panel__head { position: sticky; top: 0; background: var(--color-white); z-index: 1; }
  /* Stack the facets full-width so each is a proper tap target. */
  .vb-panel__body .xp-row--selects { display: grid; grid-template-columns: 1fr; gap: 0.5rem; }
  .vb-panel__body .xp-select-wrap,
  .vb-panel__body .xp-multi { display: block; width: 100%; }
  .vb-panel__body .xp-select-wrap select,
  .vb-panel__body .xp-multi__trigger { width: 100%; box-sizing: border-box; }
  .vb-panel__foot { justify-content: stretch; }
  .vb-panel__foot .xp-clear { width: 100%; justify-content: center; }

  /* Same again: under the pill that opened it. */
  .vb-sheet {
    position: absolute; top: 100%; left: max(2vw, 8px); right: auto; inset: auto;
    top: 100%;
    width: min(20rem, calc(100vw - 2rem)); margin: 4px 0 0; padding: 6px;
    border-radius: var(--radius-lg, 12px);
    z-index: 1200;
  }
  .vb-sheet__row { padding: 12px; font-size: 0.95rem; }

  /* No longer needed: nothing covers the page, so nothing has to freeze it.
     Locking the scroll for an anchored dropdown would strand a reader who
     opened it near the bottom of a long list. */
  body.vb-panel-open { overflow: visible; }
}

/* Dark theme for the band's controls. The band itself is already handled
   further down (:root[data-theme="dark"] .view-band). */
:root[data-theme="dark"] .vb-icon:hover,
:root[data-theme="dark"] .vb-icon[aria-expanded="true"] { background: rgba(255,255,255,0.07); color: #fff; }
:root[data-theme="dark"] .vb-icon.is-active { background: rgba(0,177,255,0.18); color: var(--color-accent-2); }
:root[data-theme="dark"] .vb-search__input { background: rgba(255,255,255,0.06); color: #fff; }
:root[data-theme="dark"] .vb-search.is-open .vb-search__input { border-color: rgba(255,255,255,0.14); }
:root[data-theme="dark"] .view-band__pill { background: rgba(255,255,255,0.06); color: #fff; }
:root[data-theme="dark"] .view-band__pill:hover { background: rgba(255,255,255,0.10); border-color: rgba(255,255,255,0.16); }
:root[data-theme="dark"] .vb-panel,
:root[data-theme="dark"] .vb-sheet,
:root[data-theme="dark"] .vb-new__menu { background: #1B2F3C; border-color: rgba(255,255,255,0.12); }
:root[data-theme="dark"] .vb-panel__head { background: #1B2F3C; border-bottom-color: rgba(255,255,255,0.12); }
:root[data-theme="dark"] .vb-sheet__row,
:root[data-theme="dark"] .vb-new__menu button { color: #fff; }
:root[data-theme="dark"] .vb-sheet__row:hover,
:root[data-theme="dark"] .vb-new__menu button:hover { background: rgba(255,255,255,0.07); }
:root[data-theme="dark"] .vb-sheet__row.is-current { background: rgba(0,177,255,0.20); color: var(--color-accent-2); }
:root[data-theme="dark"] .vb-panel__close:hover { background: rgba(255,255,255,0.07); color: #fff; }

/* Collapsible module list inside course cards */
.module-list-toggle {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem; width: 100%;
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.25); border-radius: 99px;
  font: 600 0.78rem/1 var(--font); letter-spacing: 0.04em;
  color: rgba(255,255,255,0.85); cursor: pointer;
  padding: 0.6rem 1rem; margin: 0.65rem 0 0.5rem;
  transition: all var(--duration-fast) var(--ease-out);
}
.module-list-toggle:hover { background: rgba(255,255,255,0.14); border-color: var(--color-accent-2); color: #fff; }
.module-list-toggle:focus-visible { outline: 2px solid var(--color-accent-2); outline-offset: 2px; }
.module-list-chev { transition: transform var(--duration-fast) var(--ease-out); }
.module-list-toggle.is-open .module-list-chev { transform: rotate(180deg); }

/* Graph preview card v2: accent band, tag pills, spec plate */
.kg-preview { padding-top: calc(var(--spacing-lg) + 6px); overflow-y: auto; overflow-x: hidden; }
.kg-card-band { position: absolute; top: 0; left: 0; right: 0; height: 6px; }
.kg-desc { font-size: 0.86rem; line-height: 1.6; color: var(--color-text-secondary); margin: 0; flex: 1; }
/* Module / course objectives in the node card (PLA-44) */
.kg-objectives { display: flex; flex-direction: column; gap: 0.3rem; }
.kg-objective { font-size: 0.86rem; line-height: 1.6; color: var(--color-text-secondary); margin: 0; }
.kg-objective-label {
  display: block;
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--color-text-muted);
}
.kg-objective .kg-objective-label { display: inline; margin-right: 0.35rem; }
.kg-objective-list { margin: 0.2rem 0 0; padding-left: 1.05rem; display: flex; flex-direction: column; gap: 0.28rem; }
.kg-objective-list li { font-size: 0.84rem; line-height: 1.55; color: var(--color-text-secondary); }
.kg-plate { border-top: 1px solid var(--color-border); padding-top: 0.65rem; display: flex; flex-direction: column; gap: 0.32rem; }
.kg-plate-row { display: grid; grid-template-columns: auto 1fr auto; align-items: baseline; gap: 0.5rem; }
.kg-plate-k {
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--color-text-muted);
}
.kg-plate-dots { border-bottom: 1px dotted var(--color-border); transform: translateY(-3px); }
.kg-plate-v { font-size: 0.78rem; font-weight: 600; color: var(--color-text-primary); text-align: right; }

/* Graph dimensions UI: lens bar, scope breadcrumb, clickable legend */
.kg-legend { pointer-events: auto; }
.kg-legend { right: 16px; }      /* span the full top edge so the back chip can sit right */
.kg-legend [data-bucket] {
  cursor: pointer; border-radius: 99px; padding: 0.28rem 0.6rem;
  border: 1px solid transparent;
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}
.kg-legend [data-bucket]:hover { background: rgba(255,255,255,0.12); border-color: rgba(255,255,255,0.25); transform: translateY(-1px); }
.kg-legend [data-bucket]:focus-visible { outline: 2px solid var(--color-accent-2); outline-offset: 2px; }
/* Pushed to the right end of the legend, but not flush against the stage edge:
   without the right margin the chip's pill touches the border and reads as
   clipped rather than placed. */
.kg-legend .kg-scope { margin-left: auto; margin-right: 0.6rem; }
.kg-lens {
  position: absolute; top: 14px; right: 16px; display: flex; gap: 4px;
  background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.2);
  border-radius: 99px; padding: 3px;
}
.kg-lens button {
  font: 600 0.7rem/1 var(--font); letter-spacing: 0.05em; text-transform: uppercase;
  color: rgba(255,255,255,0.75); background: transparent; border: 0; border-radius: 99px;
  padding: 0.42rem 0.85rem; cursor: pointer; transition: all var(--duration-fast) var(--ease-out);
}
.kg-lens button:hover { color: #fff; }
.kg-lens button[aria-pressed=true] { background: var(--gradient-accent); color: var(--color-primary); }
.kg-scope {
  pointer-events: auto; margin-left: 0.4rem;
  font: 700 0.7rem/1 var(--font); letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--color-primary); background: var(--color-accent-1);
  border: 0; border-radius: 99px; padding: 0.42rem 0.85rem; cursor: pointer;
  box-shadow: var(--shadow-glow-subtle);
}
.kg-scope:hover { filter: brightness(1.05); }
.kg-cta--ghost {
  background: transparent; border: 1.5px solid var(--color-deep-cerulean, #0084B2);
  color: var(--color-deep-cerulean, #0084B2); cursor: pointer; font-family: var(--font);
}
.kg-cta--ghost:hover { background: rgba(0,132,178,0.08); filter: none; }

.kg-scope-name { opacity: 0.75; font-weight: 600; margin-left: 0.3rem; }


/* ── Pathfinder trail (PLA-7) ─────────────────────────────────────────────
   Replaces the 3D cloud inside .kg-wrap whenever the view is narrowed
   (course focus, bucket dive, explorer filters). A game-map trail: stops
   snake across the stage in serpentine rows joined by one dashed path,
   zoned by module / difficulty, with a single pulsing "Start here" and a
   finish flag. Rendered by js/pathfinder.js on the same dark Gable stage. */
.kg-path {
  position: absolute; inset: 0; z-index: 5;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 60px clamp(16px, 5vw, 56px) 48px;
  color: #fff;
}
.kg-path[hidden] { display: none; }
.kg-wrap.kg-path-active #kgCanvas { visibility: hidden; }
.kg-wrap.kg-path-active .kg-hint { display: none; }
.kg-wrap .kg-legend { z-index: 7; }

.kg-path .pf-head { max-width: 720px; margin: 0 auto 1.6rem; text-align: center; }
.kg-path .pf-kicker {
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--color-accent-1, #00FFBC);
}
.kg-path .pf-title { margin: 0.25rem 0 0.4rem; font-size: 1.5rem; font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; color: #fff; }
.kg-path .pf-sub { margin: 0; font-size: 0.86rem; line-height: 1.55; color: rgba(255,255,255,0.72); }
.kg-path .pf-meta { display: block; margin-top: 0.3rem; font-size: 0.74rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: rgba(255,255,255,0.5); }

.kg-path .pf-map { max-width: 720px; margin: 0 auto; }
.kg-path .pf-zone { margin-bottom: 0.6rem; }
.kg-path .pf-zone-banner {
  position: relative; z-index: 1;   /* sits over the inter-zone trail thread */
  display: flex; align-items: baseline; justify-content: center; gap: 0.6rem;
  margin: 0.4rem 0 1.1rem; padding: 0.45rem 1rem;
  border: 1px solid rgba(92,213,255,0.28); border-radius: 99px;
  background: rgba(11,20,26,0.85);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(92,213,255,0.95);
  width: fit-content; margin-left: auto; margin-right: auto;
}
.kg-path .pf-zone-banner em { font-style: normal; font-weight: 500; letter-spacing: 0.02em; text-transform: none; color: rgba(255,255,255,0.5); }

/* The trail: SVG dashed path behind absolutely-positioned stops. */
.kg-path .pf-trail { position: relative; }
.kg-path .pf-trail > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.kg-path .pf-trail > svg path {
  fill: none; stroke: rgba(255,255,255,0.28); stroke-width: 2.5;
  stroke-dasharray: 1 8; stroke-linecap: round;
}
.kg-path .pf-stop {
  position: absolute; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  width: 170px; text-decoration: none; color: inherit; text-align: center;
}
.kg-path .pf-stop-dot {
  width: 44px; height: 44px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.9rem; font-weight: 700; color: #0B141A;
  background: radial-gradient(circle at 32% 28%, #fff 0%, var(--stop, #00FFBC) 32%, var(--stop, #00FFBC) 100%);
  box-shadow: 0 0 0 4px rgba(255,255,255,0.1), 0 0 18px color-mix(in srgb, var(--stop, #00FFBC) 45%, transparent);
  transition: transform var(--duration-fast, 0.15s) var(--ease-out, ease);
}
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .kg-path .pf-stop-dot { box-shadow: 0 0 0 4px rgba(255,255,255,0.1), 0 0 18px rgba(0,255,188,0.4); }
}
.kg-path .pf-stop:hover .pf-stop-dot { transform: scale(1.14); }
.kg-path .pf-stop:focus-visible { outline: 2px solid var(--color-accent-2, #00B1FF); outline-offset: 3px; border-radius: 12px; }
.kg-path .pf-stop-label {
  margin-top: 0.45rem; text-shadow: 0 1px 6px rgba(11,20,26,0.9);
}
/* Title and "why" clamp SEPARATELY — a long title must never swallow the
   why-line mid-sentence (the dangling-ellipsis bug). */
.kg-path .pf-stop-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 0.78rem; font-weight: 600; line-height: 1.3; color: #fff;
}
/* The why-line renders IN FULL — never clamped, never ellipsised. Row height
   is computed per section in js/pathfinder.js so long sentences get room. */
.kg-path .pf-stop-why {
  display: block; margin-top: 0.15rem; font-size: 0.68rem; font-style: normal;
  font-weight: 500; line-height: 1.35; color: rgba(255,255,255,0.62);
}
.kg-path .pf-stop-why--match { color: var(--color-accent-1, #00FFBC); font-style: italic; }
.kg-path .pf-stop-meta {
  display: block; margin-top: 0.15rem;
  font-size: 0.64rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: rgba(255,255,255,0.5);
}

/* Coming-soon stops: visible on the trail (full route shape) but not
   clickable — dashed dim dot, muted title. "Start here" never lands here. */
.kg-path .pf-stop--soon { cursor: default; }
.kg-path .pf-stop--soon .pf-stop-dot {
  background: rgba(255,255,255,0.08); box-shadow: none;
  border: 2px dashed rgba(255,255,255,0.3); color: rgba(255,255,255,0.55);
}
.kg-path .pf-stop--soon:hover .pf-stop-dot { transform: none; }
.kg-path .pf-stop--soon .pf-stop-title { color: rgba(255,255,255,0.55); }
.kg-path .pf-stop--soon .pf-stop-why { color: rgba(255,255,255,0.4); }

/* Empty trail: the view is valid but nothing is published yet. */
.kg-path .pf-empty {
  display: flex; justify-content: center; margin-top: 2.5rem;
  color: rgba(255,255,255,0.25);
}
.kg-path .pf-empty svg { width: 40px; height: 40px; }

/* Wayfinding: exactly one Start here, one Finish per route. */
.kg-path .pf-start-badge, .kg-path .pf-finish-badge {
  position: absolute; top: -24px; left: 50%; transform: translateX(-50%);
  white-space: nowrap; font-size: 0.64rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.2rem 0.6rem; border-radius: 99px;
}
.kg-path .pf-start-badge { color: #0B141A; background: var(--color-accent-1, #00FFBC); animation: pfPulse 2.2s ease-in-out infinite; }
.kg-path .pf-finish-badge { color: var(--color-accent-1, #00FFBC); border: 1px solid rgba(0,255,188,0.5); background: rgba(11,20,26,0.7); }
.kg-path .pf-stop--start .pf-stop-dot { width: 52px; height: 52px; box-shadow: 0 0 0 5px rgba(0,255,188,0.22), 0 0 26px rgba(0,255,188,0.45); }
.kg-path .pf-stop--end .pf-stop-dot svg { color: #0B141A; }
@keyframes pfPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(0,255,188,0.45); } 50% { box-shadow: 0 0 0 7px rgba(0,255,188,0); } }
@media (prefers-reduced-motion: reduce) { .kg-path .pf-start-badge { animation: none; } }

@media (max-width: 760px) {
  .kg-path { padding: 56px 8px 32px; }
  .kg-path .pf-title { font-size: 1.2rem; }
  .kg-path .pf-stop { width: 110px; }
  .kg-path .pf-stop-label { font-size: 0.7rem; }
}


/* Preview card on the dark graph surface: light-on-dark child styles */
.kg-preview h3 { color: var(--color-white); }
.kg-preview .kg-kicker { color: rgba(255,255,255,0.7); }
.kg-preview .kg-crumb { color: rgba(255,255,255,0.5); }
.kg-preview .kg-desc { color: rgba(255,255,255,0.78); }
.kg-preview .kg-close { color: rgba(255,255,255,0.55); }
.kg-preview .kg-close:hover { color: var(--color-white); }
.kg-preview .kg-meta { color: rgba(255,255,255,0.55); border-top-color: var(--color-border-dark); }
.kg-preview .kg-soon { color: rgba(255,255,255,0.6); border-color: rgba(255,255,255,0.3); }
.kg-preview .kg-domains span { color: var(--color-accent-1); background: rgba(0,255,188,0.10); }
.kg-preview .kg-reason { color: var(--color-accent-1); }
.kg-preview .kg-plate { border-top-color: var(--color-border-dark); }
.kg-preview .kg-plate-k { color: rgba(255,255,255,0.5); }
/* Objectives (PLA-44): the "Module/Course Objective(s):" label in brand green
   (Mountain Meadow), the objective text white — both legible on the dark card
   in either theme (the theme-var defaults read as dull brown in light mode). */
.kg-preview .kg-objective,
.kg-preview .kg-objective-list li { color: var(--color-white); }
.kg-preview .kg-objective-label { color: var(--color-meadow); }
/* The preview card sits permanently on the Gable gradient, so it is styled
   light-on-dark in BOTH themes. In dark mode --color-white flips to Gable,
   which turned the white title dark and invisible. Re-pin the white token on
   the card subtree so it renders identically in light and dark. */
:root[data-theme="dark"] .kg-preview { --color-white: #FFFFFF; }
.kg-preview .kg-plate-dots { border-bottom-color: rgba(255,255,255,0.2); }
.kg-preview .kg-plate-v { color: var(--color-white); }
.kg-preview .kg-cta { background: var(--gradient-accent); color: var(--color-primary); }
.kg-preview .kg-cta--disabled { background: rgba(255,255,255,0.12); color: rgba(255,255,255,0.5); }
.kg-preview .kg-cta--ghost { background: transparent; border-color: var(--color-accent-2); color: var(--color-accent-2); }
.kg-preview .kg-cta--ghost:hover { background: rgba(0,177,255,0.12); }

/* ── Shared select chevron: .lp-select ──────────────────────────────────────
   The native dropdown arrow is drawn hard against the right border with no
   inset, so it touches the field's edge. Any <select class="lp-select"> gets a
   chevron drawn 0.8rem in instead, with room reserved for it. Same treatment
   .xp-select-wrap already gives the explorer toolbar, available to any surface.

   A page-level rule must not set `padding-right` or the `background` shorthand
   on a .lp-select at equal-or-higher specificity: the shorthand resets
   background-image and silently wipes the chevron out. Use `background-color`,
   and give the padding an explicit right value of 2.1rem where a rule needs
   its own padding. */
select.lp-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 2.1rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23575756' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.8rem center;
}
:root[data-theme="dark"] select.lp-select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238AA0AE' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Custom select chevron with proper inset (native arrow hugged the edge) */
.xp-select-wrap select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 2.2rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23575756' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
}

/* ====================================================================
   Explorer toolbar polish (2026-06-12): the filter controls sit in a
   single quiet panel with consistent rhythm, clear separation from the
   graph stage below, and a proper search field.
   ==================================================================== */
/* PLA-87: this was the panel holding the search field and the facet controls.
   Both moved up into the view band, so what is left is the readout — the active
   chips and the match count. A bordered card around two lines of status text was
   heavier than the information in it, so the box is gone; .xp-active brings its
   own surface and .xp-count is bare text. */
#exploreToolbar {
  margin-bottom: var(--spacing-md);
}
#exploreToolbar[hidden] { display: none; }
/*
 * Idle, this element holds nothing — both children carry `hidden` until a filter
 * is on — but it still contributed its margin, leaving 76px of empty space
 * between the band and the first course card on a phone. `has-active-filters` is
 * js/explore.js's own isActive() verdict (set in render()), so it is exactly the
 * right signal: no filter, no readout, no space.
 */
body:not(.has-active-filters) #exploreToolbar { display: none; }
#exploreToolbar .xp-row { margin-bottom: 0.65rem; row-gap: 0.5rem; }
#exploreToolbar .xp-row:last-of-type { margin-bottom: 0; }
#exploreToolbar .xp-label { min-width: 52px; }

/* Search field: pill shape, inset icon, calm focus ring */
.xp-toolbar input[type=search] {
  border-radius: 99px;
  padding: 0.78rem 1.2rem 0.78rem 2.7rem;
  font-size: 0.92rem;
  background-color: var(--color-off-white);
  border-color: transparent;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7A88' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 1.05rem center;
  transition: background-color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}
.xp-toolbar input[type=search]::placeholder { color: var(--color-text-muted); }
.xp-toolbar input[type=search]:hover { background-color: var(--color-white); border-color: var(--color-border); }
.xp-toolbar input[type=search]:focus {
  background-color: var(--color-white);
  border-color: var(--color-accent-2);
  box-shadow: 0 0 0 3px rgba(0, 177, 255, 0.15);
}
/* WebKit's default magnifier/cancel decorations fight the custom icon */
.xp-toolbar input[type=search]::-webkit-search-decoration { -webkit-appearance: none; }

.xp-count { margin: 0.7rem 0 0; }

/* Selects share the search field's quiet treatment */
.xp-select-wrap select {
  background-color: var(--color-off-white);
  border-color: transparent;
  border-radius: 99px;
  padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 0.95rem;
  transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}
.xp-select-wrap select:hover { background-color: var(--color-white); border-color: var(--color-border); }
.xp-select-wrap select:focus { outline: none; background-color: var(--color-white); border-color: var(--color-accent-2); box-shadow: 0 0 0 3px rgba(0,177,255,0.15); }

/* ---- Active-filter clarity (shared by Graph + Catalogue views) ----------
   A dropdown set to anything other than "All …" now reads as clearly ON, a
   summary bar spells out exactly what's being filtered, and Clear all becomes
   a proper button. Together these make a filtered view unmistakable — and stop
   a filter silently carrying over when you switch between the two views. */
.xp-select-wrap.is-active select {
  background-color: rgba(0,177,255,0.10);
  border-color: var(--color-accent-2-accessible);
  color: var(--color-accent-2-accessible);
  font-weight: 700;
}
.xp-select-wrap.is-active select:hover { background-color: rgba(0,177,255,0.16); }

/* Clear all — an obvious reset button rather than faint blue text. */
#exploreToolbar .xp-clear {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0.5rem 0.95rem; border-radius: 99px;
  border: 1px solid var(--color-accent-2-accessible);
  background: var(--color-white); color: var(--color-accent-2-accessible);
  cursor: pointer; font-family: var(--font); white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
#exploreToolbar .xp-clear:hover { background: var(--color-accent-2-accessible); color: var(--color-white); text-decoration: none; }
#exploreToolbar .xp-clear:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
/* Author display rules beat the UA [hidden] rule, so restore it explicitly —
   without this the button shows before any filter is applied. */
#exploreToolbar .xp-clear[hidden] { display: none; }
.xp-clear__x { font-size: 1.05em; line-height: 1; font-weight: 400; }

/* Summary bar: "Filtered view — <chips>" */
.xp-active {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
  /* No top margin. This row is the readout for the control band directly above
     it, and the section it lives in already supplies the padding — the two
     stacked, leaving the chips floating in the middle of a gap and reading as a
     separate block rather than as the answer to what was just pressed. */
  margin-top: 0; padding: 0.15rem 0;
  /* No container. The chips are outlined and legible on their own; the tinted
     panel was drawing a box round something the eye had already found. */
  background: transparent;
  border: 0;
}
/* Restore [hidden] — the display:flex above would otherwise force the bar
   visible on first load, before any filter is active. */
.xp-active[hidden] { display: none; }
.xp-active__label {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-accent-2-accessible); margin-right: 0.15rem;
}
.xp-active__chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.xp-active-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font: inherit; font-size: 0.75rem; font-weight: 600;
  padding: 0.28rem 0.4rem 0.28rem 0.7rem; border-radius: 99px;
  border: 1px solid var(--color-accent-2-accessible);
  background: var(--color-white); color: var(--color-text-primary);
  cursor: pointer; transition: all var(--duration-fast) var(--ease-out);
}
.xp-active-chip:hover { background: var(--color-accent-2-accessible); color: var(--color-white); }
.xp-active-chip:focus-visible { outline: 2px solid var(--color-accent-2-accessible); outline-offset: 2px; }
.xp-active-chip__x { font-size: 1.05em; line-height: 1; opacity: 0.7; }
.xp-active-chip:hover .xp-active-chip__x { opacity: 1; }

/* Matching lessons on a filtered course card are individually clickable. */
.module-list-item--link { cursor: pointer; transition: background var(--duration-fast) var(--ease-out); }
.module-card .module-list-item--link:hover,
.module-card .module-list-item--link:focus-visible { background: rgba(255,255,255,0.06); }
.module-list-item--link:hover .module-list-item-title,
.module-list-item--link:focus-visible .module-list-item-title { color: var(--color-accent-2); text-decoration: underline; }
.module-list-item--link:focus-visible { outline: 2px solid var(--color-accent-2); outline-offset: 2px; }

/* ---- Mobile: keep the catalogue filter panel tidy on small screens ----
   The three dropdowns stack full-width (easy to tap), the search field goes
   full-width, and the toolbar tightens so it doesn't feel clunky on a phone. */
@media (max-width: 640px) {
  #exploreToolbar { padding: 0.9rem 0.85rem 0.85rem; }
  #exploreToolbar .xp-toolbar { gap: 0.5rem; }
  #exploreToolbar .xp-toolbar input[type=search] { flex: 1 1 100%; }
  #exploreToolbar .xp-clear { margin-left: auto; }
  #exploreToolbar .xp-row { gap: 0.4rem; }
  /* Filter dropdowns: two per row on mobile (a 2-column grid) rather than one. */
  #exploreToolbar .xp-row--selects { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
  #exploreToolbar .xp-row--selects .xp-select-wrap { display: block; width: 100%; min-width: 0; }
  #exploreToolbar .xp-row--selects .xp-select-wrap select { width: 100%; }
}

/* ====================================================================
   Dark theme: explorer toolbar + view switch (2026-06-12 QA pass)
   Fixes: (1) pressed chips/segments used --color-primary, which is the
   same Gable tone as dark surfaces — toggled controls vanished. Pressed
   state now uses the accent gradient with Gable text (Tier 3 on dark).
   (2) Adds an elevation scale so dark mode has depth: page canvas
   darkest, section panels lighter, toolbar/cards lighter again, with
   visible hairlines and stronger shadows.
   ==================================================================== */
:root[data-theme="dark"] #exploreToolbar {
  background: #1B2F3C;
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
}
:root[data-theme="dark"] .xp-toolbar input[type=search],
:root[data-theme="dark"] .xp-select-wrap select {
  background-color: rgba(255, 255, 255, 0.06);
  color: #FFFFFF;
  border-color: rgba(255, 255, 255, 0.08);
}
:root[data-theme="dark"] .xp-toolbar input[type=search]:hover,
:root[data-theme="dark"] .xp-select-wrap select:hover {
  background-color: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.2);
}
:root[data-theme="dark"] .xp-toolbar input[type=search]:focus,
:root[data-theme="dark"] .xp-select-wrap select:focus {
  background-color: rgba(255, 255, 255, 0.10);
  border-color: var(--color-accent-2);
}
:root[data-theme="dark"] .xp-toolbar input[type=search] {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238AA0AE' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .xp-select-wrap select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238AA0AE' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .xp-select-wrap select option { background: #1B2F3C; color: #fff; }

/* Match the multi-select triggers in the RESTING and HOVER states too.
   The grouped rule above gives selects a translucent white wash
   (rgba(255,255,255,0.06)), which sits LIGHTER than the card. The
   .xp-multi__trigger has no dark override at all, so it resolves to
   var(--color-off-white) — #152532, DARKER than the card. Side by side in one
   toolbar that read as two different families of control, when the only thing
   separating them is that one is a <select> and the other a <details>.
   Availability, Courses and the Library's Types now sit at the same weight as
   Departments, Superpowers, Depth, Subjects and Tools.

   In light both already resolved to var(--color-off-white), which is why this
   only ever showed in dark.

   Kept as its own block rather than edited into the rule above, because that
   one also styles .xp-toolbar input[type=search] — a text field, which should
   keep its own treatment. Equal specificity, later in the file, so it wins. */
:root[data-theme="dark"] .xp-select-wrap select {
  background-color: var(--color-off-white);
  border-color: transparent;
}
:root[data-theme="dark"] .xp-select-wrap select:hover {
  background-color: var(--color-white);
  border-color: var(--color-border);
}
/* Active-filter clarity — dark theme */
/* Match the multi-select triggers exactly (.xp-multi.is-active >
   .xp-multi__trigger below). Those have no dark override, so in dark they read
   as the card surface with an accent border and white semibold text — while
   these selects were filling with a translucent accent wash. Two active
   treatments in one toolbar, and the difference tracked nothing except which
   control happened to be a <select>. Availability, Courses and the Library's
   Types now look like Departments, Superpowers, Depth, Subjects and Tools. */
:root[data-theme="dark"] .xp-select-wrap.is-active select {
  background-color: var(--color-white);
  border-color: var(--color-accent-2);
  color: var(--color-text-primary);
  font-weight: var(--fw-semibold);
}
:root[data-theme="dark"] .xp-select-wrap.is-active select:hover { background-color: var(--color-off-white); }
:root[data-theme="dark"] #exploreToolbar .xp-clear { background: rgba(255,255,255,0.05); color: var(--color-accent-2); }
:root[data-theme="dark"] #exploreToolbar .xp-clear:hover { background: var(--color-accent-2); color: #08131B; }
:root[data-theme="dark"] .xp-active-chip { background: rgba(255,255,255,0.06); color: #FFFFFF; }
:root[data-theme="dark"] .xp-active-chip:hover { background: var(--color-accent-2); color: #08131B; }
:root[data-theme="dark"] .xp-chips button {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.14);
  color: #CFDBE4;
}
:root[data-theme="dark"] .xp-chips button:hover { border-color: var(--color-accent-2); color: var(--color-accent-2); }
:root[data-theme="dark"] .xp-chips button[aria-pressed=true] {
  background: var(--gradient-accent);
  color: #1B2F3C;
  border-color: transparent;
}
:root[data-theme="dark"] .xp-foryou { background: rgba(255, 255, 255, 0.05); }
/* View band (PLA-104): --color-white already flips to a dark surface, so the
   band only needs a firmer border and a shadow that reads on the dark canvas.
   The pressed accent-1 index chip keeps its dark ink — it sits on a bright
   turquoise fill in both themes. */
:root[data-theme="dark"] .view-band {
  background: #1B2F3C;
  border-bottom-color: rgba(255, 255, 255, 0.14);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
:root[data-theme="dark"] .view-band__divider { border-left-color: rgba(255, 255, 255, 0.18); }
:root[data-theme="dark"] .view-tab__idx { color: var(--color-accent-2); }
:root[data-theme="dark"] .view-tab--ref .view-tab__idx { color: var(--ink-muted); }
:root[data-theme="dark"] .view-tab[aria-pressed=true] .view-tab__idx { color: #1B2F3C; }
/* Graph stage + preview card pop against the section panel */
:root[data-theme="dark"] .kg-wrap { border-color: rgba(255, 255, 255, 0.14); box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45); }
:root[data-theme="dark"] .kg-preview { border-color: rgba(255, 255, 255, 0.14); box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45); }
/* Hero stats strip needs a touch more presence on the darker canvas */
:root[data-theme="dark"] .stats-strip--hero { background: rgba(255, 255, 255, 0.07); border-color: rgba(255, 255, 255, 0.18); }


/* ==========================================================================
   Inbox / Notifications  (js/inbox.js, 2026-06-18)
   Visible only to aia-internal + adobe members (feature-flag gated).
   ========================================================================== */

/* ── Mount point ──────────────────────────────────────────────────────────── */
[data-inbox-bell] {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

/* ── Bell button ─────────────────────────────────────────────────────────── */
.inbox-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 50%;
  color: rgba(255, 255, 255, 0.80);
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
  flex-shrink: 0;
}
.inbox-bell:hover,
.inbox-bell:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.20);
  color: #fff;
  outline: none;
}
.inbox-bell[aria-expanded="true"] {
  background: rgba(0, 255, 188, 0.12);
  border-color: rgba(0, 255, 188, 0.30);
  color: #00FFBC;
}

.inbox-bell__icon {
  display: block;
  flex-shrink: 0;
}

/* ── Unread badge ────────────────────────────────────────────────────────── */
.inbox-bell__badge {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  background: #FF4C6B;
  border: 2px solid #1B2F3C;   /* matches dark nav bg */
  border-radius: 9px;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  line-height: 13px;
  text-align: center;
  pointer-events: none;
}

/* ── Panel ───────────────────────────────────────────────────────────────── */
.inbox-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  /* Bounded by the viewport, not a fixed 340px. On a phone the bell sits close
     enough to the right edge that a fixed width ran off the LEFT of the screen,
     leaving about half the panel unreachable. The 16px keeps it clear of the
     edge rather than flush against it. */
  /* 24px, not 16: the panel is anchored right:0 to a bell that itself sits ~12px
     from the edge, so subtracting only 16 left about 4px on the LEFT and the
     panel read as pressed against the margin. 24 gives it the same 12px on both
     sides as the bell has on its own. */
  width: min(340px, calc(100vw - 24px));
  max-height: 480px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid #E4E8EC;
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
  z-index: 1100;
  overflow: hidden;
  font-family: 'Poppins', 'Inter', Arial, sans-serif;
}
.inbox-panel[hidden] { display: none; }

/* ── Panel header ────────────────────────────────────────────────────────── */
.inbox-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
  border-bottom: 1px solid #E4E8EC;
  flex-shrink: 0;
}
.inbox-panel__title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.inbox-panel__mark-all {
  font-size: 12px;
  font-weight: 500;
  color: var(--color-accent-2-accessible);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  transition: opacity 0.2s;
}
.inbox-panel__mark-all:hover { opacity: 0.75; }

/* ── Scrollable list ─────────────────────────────────────────────────────── */
.inbox-panel__list {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.inbox-panel__list::-webkit-scrollbar { width: 4px; }
.inbox-panel__list::-webkit-scrollbar-track { background: transparent; }
.inbox-panel__list::-webkit-scrollbar-thumb { background: rgba(27,47,60,0.15); border-radius: 2px; }

/* ── Empty state ─────────────────────────────────────────────────────────── */
.inbox-panel__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 16px;
  color: var(--ink-muted);
  text-align: center;
}
.inbox-panel__empty p {
  font-size: 13px;
  font-weight: 500;
}

/* ── Notification item ───────────────────────────────────────────────────── */
.inbox-item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(27,47,60,0.06);
  transition: background 0.15s;
  cursor: default;
}
.inbox-item:last-child { border-bottom: none; }
.inbox-item:hover { background: var(--surface-hover); }

/* Unread: left accent bar */
.inbox-item--unread {
  background: rgba(0, 177, 255, 0.04);
}
.inbox-item--unread:hover { background: rgba(0, 177, 255, 0.07); }

/* ── Type icon chip ──────────────────────────────────────────────────────── */
.inbox-item__icon-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  flex-shrink: 0;
  margin-top: 1px;
}
/* Type-specific tints */
.inbox-item__icon-wrap.type--content       { background: rgba(0, 177, 255, 0.12); color: #0071A1; }
.inbox-item__icon-wrap.type--unlocked      { background: rgba(0, 255, 188, 0.12); color: #007A5E; }
.inbox-item__icon-wrap.type--role          { background: rgba(255, 176, 0, 0.12);  color: #A07000; }
.inbox-item__icon-wrap.type--recommendation { background: rgba(140, 82, 255, 0.12); color: #6030CC; }

/* ── Item body ───────────────────────────────────────────────────────────── */
.inbox-item__content {
  flex: 1;
  min-width: 0;
}
.inbox-item__title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.4;
  margin: 0 0 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inbox-item--unread .inbox-item__title { color: var(--ink); }
.inbox-item__body {
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.5;
  margin: 0 0 6px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.inbox-item__footer {
  display: flex;
  align-items: center;
  gap: 10px;
}
.inbox-item__time {
  font-size: 11px;
  color: var(--ink-muted);
}
.inbox-item__link {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-accent-2-accessible);
  text-decoration: none;
}
.inbox-item__link:hover { text-decoration: underline; }

/* ── Unread dot ──────────────────────────────────────────────────────────── */
.inbox-item__dot {
  position: absolute;
  top: 16px;
  right: 14px;
  width: 7px;
  height: 7px;
  background: #00B1FF;
  border-radius: 50%;
  flex-shrink: 0;
}

/* ── Dark theme overrides ────────────────────────────────────────────────── */
:root[data-theme="dark"] .inbox-panel {
  background: #1B2F3C;
  border-color: rgba(255, 255, 255, 0.10);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.40);
}
:root[data-theme="dark"] .inbox-panel__header { border-bottom-color: rgba(255, 255, 255, 0.08); }
:root[data-theme="dark"] .inbox-item { border-bottom-color: rgba(255, 255, 255, 0.06); }
:root[data-theme="dark"] .inbox-item--unread { background: rgba(0, 177, 255, 0.06); }
:root[data-theme="dark"] .inbox-item--unread:hover { background: rgba(0, 177, 255, 0.10); }
:root[data-theme="dark"] .inbox-item__icon-wrap.type--content       { color: #4DD0FF; }
:root[data-theme="dark"] .inbox-item__icon-wrap.type--unlocked      { color: #00FFBC; }
:root[data-theme="dark"] .inbox-item__icon-wrap.type--role          { color: #FFD166; }
:root[data-theme="dark"] .inbox-item__icon-wrap.type--recommendation { color: #B08FFF; }
:root[data-theme="dark"] .inbox-bell__badge { border-color: #152532; }

/* ── Header icon cluster order ────────────────────────────────────────────────
   The cluster is a flex row, so `order` decides the layout and DOM order only
   breaks ties. The bell carries order:2, so without an explicit order the
   Settings gear (order:0 by default) rendered BEFORE it despite sitting last in
   the markup. Pin the gear last: theme, then inbox, then Settings. 3 matches the
   value module.html already sets under its 768px breakpoint, so both agree.
   Harmless on pages with no bell (analytics / manage / guide). */
header [data-inbox-bell] { order: 2; }
header [data-account-chip] { order: 3; }

/* ─── Trending (PLA-18, reshaped in PLA-87) ───────────────────────────────────
   The curated three-column "Trending now" panel that used to sit here is GONE,
   along with all of its CSS (.trend-row / .trend-col / .trend-item / .trend-dots
   and the #trendingRow view gate). It was a third full-width block between the
   toolbar and the first course card, which on a phone meant scrolling past two
   screens of chrome to reach the catalogue — and it answered a question the
   filters already answer.

   Trending is now: a facet in the view band's filter panel (#exploreTrending,
   wired in js/explore.js), and a per-lesson badge on the catalogue cards
   (.module-list-item-trend, below). js/trending.js kept the data and lost the
   rendering. */

/* "All Modules" heading above the course grid. */
.section-rowhead {
  font-weight: 700;
  font-size: 1rem;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 4px 0 12px;
}
#allModulesHead { display: none; }
body.view-browse #allModulesHead { display: block; }

/* ─── Trending lesson marker on a catalogue card (PLA-87) ─────────────────────
   The replacement for the trending panel, at the only place it actually helps:
   inside the "View lessons" list on a module card, on the lesson itself. Before,
   knowing a lesson was trending meant reading a separate section and matching
   the title by eye.

   #00FFBC (--color-accent-1) rather than the panel's #17CE95: the module card is
   an always-dark surface in both themes, and the accessible-on-light variant
   (#007A5E) is what would fail there. Both the title and the label take it, so
   the row reads as one marked thing. */
.module-list-item.is-trending .module-list-item-title { color: var(--color-accent-1); }
.module-list-item-trend {
  display: inline-block;
  margin-left: 0.55rem;
  padding: 2px 6px 1px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  vertical-align: 1px;
  color: #06231A;
  background: var(--color-accent-1);
}
/* Keep the hover/focus treatment for the row from overriding the marker green
   with the generic link blue. */
.module-list-item--link.is-trending:hover .module-list-item-title,
.module-list-item--link.is-trending:focus-visible .module-list-item-title {
  color: var(--color-accent-1);
}

/* ---- Walkthrough (standard-view fallback for the walkthrough interactive, PLA-19) ---- */
/* The companion view owns ticks / counter / auto-scroll; this renders the same
   content as readable numbered steps in the platform's existing visual language. */

.section-walkthrough {
  margin: var(--spacing-lg) 0 0;
}

.walkthrough-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--color-text-primary);
  margin: 0 0 var(--spacing-sm);
}

.walkthrough-intro {
  color: var(--color-text-secondary);
  margin-bottom: var(--spacing-md);
}

.walkthrough-steps {
  list-style: none;
  counter-reset: wt-step;
  margin: 0;
  padding: 0;
}

.walkthrough-step {
  counter-increment: wt-step;
  position: relative;
  padding: 0 0 var(--spacing-lg) 44px;
}

.walkthrough-step::before {
  content: counter(wt-step);
  position: absolute;
  left: 0;
  top: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid #1B2F3C;
  color: #1B2F3C;
  background: var(--color-white);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
}

.walkthrough-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 13px;
  top: 32px;
  bottom: 4px;
  width: 2px;
  background: var(--color-border, #e3e0d8);
}

.walkthrough-step-title {
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 3px 0 var(--spacing-xs);
}

.walkthrough-step-instruction {
  color: var(--color-text-secondary);
  font-size: 0.95rem;
}

.walkthrough-step-instruction p { margin: 0 0 var(--spacing-xs); }
.walkthrough-step-instruction p:last-child { margin-bottom: 0; }

.walkthrough-step-prompt {
  margin: var(--spacing-sm) 0;
}

.walkthrough-step-note {
  margin-top: var(--spacing-sm);
  padding: var(--spacing-sm) var(--spacing-md);
  background: rgba(27, 47, 60, 0.04);
  border-left: 3px solid #1B2F3C;
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  font-size: 0.9rem;
  color: var(--color-text-secondary);
}

.walkthrough-step-note p { margin: 0 0 var(--spacing-xs); }
.walkthrough-step-note p:last-child { margin-bottom: 0; }

.walkthrough-step-note-label {
  display: block;
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #1B2F3C;
  opacity: 0.75;
  margin-bottom: 4px;
}

:root[data-theme="dark"] .walkthrough-step::before {
  background: transparent;
  border-color: var(--color-text-primary, #e8e6e1);
  color: var(--color-text-primary, #e8e6e1);
}

:root[data-theme="dark"] .walkthrough-step-note {
  background: rgba(255, 255, 255, 0.05);
  border-left-color: var(--color-text-muted, #9aa5ad);
}

:root[data-theme="dark"] .walkthrough-step-note-label {
  color: var(--color-text-primary, #e8e6e1);
}

/* ---- Companion-mode nudge (lessons with a walkthrough exercise) ---- */

.companion-nudge {
  background: rgba(27, 47, 60, 0.04);
  border: 1px solid var(--color-border, #e3e0d8);
  border-left: 4px solid #1B2F3C;
  border-radius: var(--radius-md);
  padding: var(--spacing-md) var(--spacing-lg);
  margin: var(--spacing-lg) 0;
}

.companion-nudge__title {
  font-weight: 700;
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-xs);
  font-size: 0.95rem;
}

.companion-nudge__body {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  line-height: 1.55;
}

:root[data-theme="dark"] .companion-nudge {
  background: rgba(255, 255, 255, 0.05);
  border-left-color: var(--color-text-muted, #9aa5ad);
}

/* Clickable variant: the nudge sits directly above each walkthrough and
   opens companion mode deep-linked to that exercise. */
.companion-nudge--clickable {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow 160ms ease, border-color 160ms ease;
}

.companion-nudge--clickable:hover {
  border-color: #1B2F3C;
  box-shadow: var(--shadow-md);
}

.companion-nudge--clickable:focus-visible {
  outline: 2px solid #1B2F3C;
  outline-offset: 2px;
}

.companion-nudge__text { min-width: 0; }

.companion-nudge__cta {
  flex-shrink: 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: #1B2F3C;
  white-space: nowrap;
}

:root[data-theme="dark"] .companion-nudge--clickable:hover {
  border-color: var(--color-text-primary, #e8e6e1);
}

:root[data-theme="dark"] .companion-nudge__cta {
  color: var(--color-text-primary, #e8e6e1);
}

/* ---- Walkthrough completion signals in the self-help view (PLA-20 parity) ---- */
/* Mirrors companion mode's visual language: the numbered node is a tickable
   control that flips to a green check, and an "x / N steps done" chip sits in
   the walkthrough header, turning into a Completed badge. */

.walkthrough-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-sm);
}

.walkthrough-header .walkthrough-title { margin: 0; }

.walkthrough-progress {
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border, #e3e0d8);
  border-radius: 999px;
  padding: 4px 12px;
  white-space: nowrap;
}

.walkthrough-progress.is-complete {
  color: #fff;
  background: #00A57C;
  border-color: #00A57C;
}

/* When ticks are active the tick button replaces the CSS-counter number. */
.section-walkthrough--ticks .walkthrough-step::before { content: none; }

.walkthrough-step-tick {
  position: absolute;
  left: 0;
  top: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid #1B2F3C;
  color: #1B2F3C;
  background: var(--color-white);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}

.walkthrough-step-tick:hover { box-shadow: 0 0 0 3px rgba(0, 165, 124, 0.25); }
.walkthrough-step-tick:focus-visible { outline: 2px solid #00A57C; outline-offset: 2px; }

.walkthrough-step.is-done .walkthrough-step-tick {
  background: #00A57C;
  border-color: #00A57C;
  color: #fff;
}

.walkthrough-step.is-done .walkthrough-step-tick .walkthrough-step-n { display: none; }
.walkthrough-step.is-done .walkthrough-step-tick::after { content: "\2713"; }

.walkthrough-step.is-done .walkthrough-step-title,
.walkthrough-step.is-done .walkthrough-step-instruction,
.walkthrough-step.is-done .walkthrough-step-prompt,
.walkthrough-step.is-done .walkthrough-step-note { opacity: 0.62; }

.walkthrough-step.is-done:not(:last-child)::after { background: #00A57C; }

/* Completed-nudge state */
.companion-nudge--done { border-left-color: #00A57C; }
.companion-nudge--done .companion-nudge__cta { color: #00A57C; }

:root[data-theme="dark"] .walkthrough-step-tick {
  background: transparent;
  border-color: var(--color-text-primary, #e8e6e1);
  color: var(--color-text-primary, #e8e6e1);
}

:root[data-theme="dark"] .walkthrough-step.is-done .walkthrough-step-tick {
  background: #00A57C;
  border-color: #00A57C;
  color: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .walkthrough-step-tick,
  .walkthrough-step.is-done .walkthrough-step-title,
  .walkthrough-step.is-done .walkthrough-step-instruction,
  .walkthrough-step.is-done .walkthrough-step-prompt,
  .walkthrough-step.is-done .walkthrough-step-note { transition: none; }
}

/* ---- Multi-select facets (PLA-91) ---------------------------------------
   Replaces the single-select domain / superpower dropdowns. Built on <details>
   so disclosure semantics, keyboard handling and screen-reader behaviour come
   from the platform rather than from JS. Visual language deliberately matches
   .xp-select-wrap select above, so the toolbar still reads as one row of
   controls rather than a new component type. */
.xp-multi { position: relative; display: inline-block; }

.xp-multi__trigger {
  list-style: none;                     /* kill the default disclosure marker */
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.4rem;
  background-color: var(--color-off-white);
  border: 1px solid transparent;
  border-radius: 99px;
  padding: 0.5rem 0.95rem;
  /* 0.82rem matches `.xp-select-wrap select` exactly, so the multi-select
     triggers and the plain selects sit on one line at one size. This read
     `var(--fs-body-sm)`, a token that is DEFINED NOWHERE in the repo — an
     undefined custom property makes the declaration invalid at computed-value
     time, so font-size fell back to inherited body size and every one of these
     controls rendered noticeably larger than the selects beside it. */
  font-size: 0.82rem;
  color: var(--color-text-primary);
  white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}
.xp-multi__trigger::-webkit-details-marker { display: none; }

/* One size for every facet. They were sized by their own labels, so "Depth" was
   half the width of "Superpowers" and the row read as unrelated buttons rather
   than one set of filters. The icon carries the difference now; the box stays
   constant, and the LABEL is what gives way when a name is too long — never the
   icon or the caret, which are how the control is recognised. */
.xp-multi__label { flex: 1 1 auto; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xp-multi__trigger { min-width: 9.5rem; justify-content: flex-start; }
.xp-multi__icon { flex: 0 0 auto; width: 0.95rem; height: 0.95rem; opacity: 0.65; }
.xp-multi.is-active > .xp-multi__trigger .xp-multi__icon { opacity: 1; }
.xp-multi__trigger::after { margin-left: auto; }
.xp-multi__trigger::after {
  content: ''; width: 0.4rem; height: 0.4rem; margin-left: 0.15rem;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  opacity: 0.55;
}
.xp-multi__trigger:hover { background-color: var(--color-white); border-color: var(--color-border); }
.xp-multi__trigger:focus-visible {
  outline: none; background-color: var(--color-white);
  border-color: var(--color-accent-2); box-shadow: 0 0 0 3px rgba(0,177,255,0.15);
}
/* Reads as clearly ON when it is filtering, matching .is-active on the selects. */
.xp-multi.is-active > .xp-multi__trigger {
  background-color: var(--color-white);
  border-color: var(--color-accent-2);
  font-weight: var(--fw-semibold);
}

.xp-multi__menu {
  position: absolute; z-index: 40; top: calc(100% + 0.35rem); left: 0;
  min-width: 15rem; max-width: min(22rem, 90vw);
  max-height: 20rem; overflow-y: auto;
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: 0.6rem;
  box-shadow: 0 8px 24px rgba(27,47,60,0.12);
  padding: 0.35rem;
  display: flex; flex-direction: column; gap: 0.1rem;
}
/* Right-align the menu when the control sits near the viewport edge, so a
   late-in-the-row facet cannot push the page sideways. */
.xp-multi--end .xp-multi__menu { left: auto; right: 0; }

.xp-multi__opt {
  display: flex; align-items: center; gap: 0.55rem;
  padding: 0.4rem 0.55rem; border-radius: 0.4rem;
  font-size: 0.82rem; line-height: 1.3;   /* same undefined-token fix as above */
  cursor: pointer;
}
.xp-multi__opt:hover { background: var(--color-off-white); }
/* Single-select rows are buttons, not checkbox labels: one choice, so a tick
   box would promise a multi-select that does not exist. The current one is
   marked instead. */
.xp-multi__opt--single {
  width: 100%; font: inherit; font-size: 0.82rem; text-align: left;
  background: none; border: 0; justify-content: space-between;
}
.xp-multi__opt--single[aria-current="true"] {
  font-weight: var(--fw-semibold); color: var(--color-accent-2-accessible);
}
/* The native select stays as the source of truth and keeps working if the
   enhancement never runs; once it has, it is the menu that is visible. */
.xp-select-wrap:has(.xp-multi--single) select {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.xp-multi__opt input { margin: 0; flex-shrink: 0; accent-color: var(--color-deep-cerulean); }
.xp-multi__opt:focus-within { background: var(--color-off-white); box-shadow: inset 0 0 0 2px rgba(0,177,255,0.25); }
.xp-multi__count { color: var(--color-text-muted); font-variant-numeric: tabular-nums; }

.xp-multi__clear {
  margin-top: 0.2rem; border-top: 1px solid var(--color-border-subtle);
  padding-top: 0.4rem;
  background: none; border-left: none; border-right: none; border-bottom: none;
  font: inherit; font-size: var(--fs-caption); color: var(--color-deep-cerulean);
  text-align: left; padding-left: 0.55rem; cursor: pointer; border-radius: 0.4rem;
}
.xp-multi__clear:hover { background: var(--color-off-white); }
.xp-multi__clear[hidden] { display: none; }

@media (max-width: 640px) {
  /* Full-width sheet rather than a popover that would overflow the viewport. */
  /* `position: fixed` with only left/right set has no `top`, so the browser
     falls back to the element's STATIC position — which, once <details> has
     expanded inside a scrolling panel, is far down the document. Measured at
     390px: the menu opened 682px below its trigger, off the bottom of the
     screen. It read as "the filter button does nothing".
     Absolute keeps it tethered to .xp-multi, which is what makes it a
     dropdown rather than a sheet that lost its anchor. */
  .xp-multi__menu {
    position: absolute; top: calc(100% + 0.35rem);
    left: 0; right: auto;
    width: max-content; min-width: 12rem;
    max-width: min(19rem, calc(100vw - 3rem));
    max-height: min(45vh, 16rem);
  }
  .xp-multi[open] { z-index: 41; }
}

/* Tier heading inside the subject facet: separates families from the buckets
   above them, so the progressive disclosure reads as one list with sections
   rather than a flat jumble of two vocabularies. */
.xp-multi__tier {
  margin: 0.45rem 0 0.15rem;
  padding: 0.35rem 0.55rem 0;
  border-top: 1px solid var(--color-border-subtle);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
}
