/* GroundWire — dark editorial "blueprint" design system (2026-06-03).
   Near-black canvas, hairline borders, 8px radius, no shadows, mono technical accents,
   blueprint-grid texture, cyan primary + amber active/mastered. */
:root {
  --canvas: #0B0C0E;
  --surface: #121418;       /* card surface */
  --surface-2: #16191E;     /* lifted inset */
  --paper: #F4F1EA;         /* rare light inset */
  --text: #E7E9EC;          /* primary text on dark */
  --text-dim: #9AA3AD;      /* secondary */
  --muted: #7D8794;         /* tertiary / metadata — AA-safe: 5.37:1 on --canvas, 4.84:1 on --surface-2 */
  --line: hsl(0 0% 100% / .10);
  --line-strong: hsl(0 0% 100% / .18);
  --line-ui: rgba(255, 255, 255, 0.38);   /* interactive field boundary — >=3.5:1 non-text contrast on all surfaces */
  --cyan: #7BD3F7;          /* primary accent / learning */
  --cyan-soft: hsl(199 88% 73% / .14);
  --amber: #E8B65A;         /* mastered / active */
  --amber-soft: hsl(38 75% 63% / .15);
  --green: #7BD9A6;
  --green-soft: hsl(150 55% 67% / .14);
  --red: #E8796A;
  --red-soft: hsl(8 73% 66% / .14);
  --blue: #7BD3F7;
  --blue-soft: hsl(199 88% 73% / .12);
  --violet: #C4B6F7;        /* function / application accent (syntax fn, project-application) */
  /* --- Semantic STATUS token system (2026-06-04 UI overhaul) -------------------
     Use these everywhere a status is shown (lesson rows, graph nodes, chips, tiles,
     file rows). Never hardcode a status color in a view — reference these tokens or
     the .status-badge / .st-* utility classes below. Each status has a base color
     (text/icon foreground), a -muted fill tint (~12-14% on dark), and a -border.
     All base colors are light pastels on the near-black canvas → AA-contrast safe. */
  --status-locked: #828892;            /* muted neutral gray — locked / unavailable */
  --status-locked-muted: hsl(218 6% 53% / .12);
  --status-locked-border: hsl(218 6% 53% / .30);
  --status-todo: #A6B6C7;              /* cool slate — not started / unseen */
  --status-todo-muted: hsl(210 22% 72% / .10);
  --status-todo-border: hsl(210 22% 72% / .28);
  --status-progress: #E8B65A;          /* warm amber — in progress / learning / current */
  --status-progress-muted: hsl(38 75% 63% / .14);
  --status-progress-border: hsl(38 75% 63% / .34);
  --status-review: #F08A4B;            /* orange-red — needs review / shaky (warning, not error) */
  --status-review-muted: hsl(22 85% 62% / .14);
  --status-review-border: hsl(22 85% 62% / .34);
  --status-complete: #7BD9A6;          /* green — mastered / verified / passed / complete */
  --status-complete-muted: hsl(150 55% 67% / .14);
  --status-complete-border: hsl(150 55% 67% / .32);
  --status-active: #7BD3F7;            /* cyan — currently selected / focused / active route */
  --status-active-muted: hsl(199 88% 73% / .14);
  --status-active-border: hsl(199 88% 73% / .34);
  /* -foreground: the dark ink to use for TEXT/ICON sitting on a FILLED status background
     (a filled chip, segmented segment, or badge). Dark-on-pastel keeps AA contrast. */
  --status-locked-foreground: #0C0E12;
  --status-todo-foreground: #0C0E12;
  --status-progress-foreground: #1A1304;
  --status-review-foreground: #1A0E06;
  --status-complete-foreground: #06140D;
  --status-active-foreground: #07131A;
  /* Legacy aliases kept so any stray references resolve sensibly. */
  --ink: var(--canvas);
  --cream: var(--text);
  --coral: var(--cyan);
  --sky: var(--cyan);
  --blueprint-grid: hsl(0 0% 100% / .035);
  --radius-xl: 8px;
  --radius-lg: 8px;
  --radius-md: 6px;
  --shadow-soft: none;
  --shadow-lift: none;
  /* Motion tokens — durations + standard ease-out (Material decelerate). */
  --dur-fast: 120ms;
  --dur-base: 220ms;
  --dur-slow: 320ms;
  --ease-out: cubic-bezier(0, 0, .2, 1);
  --transition-smooth: var(--dur-base) cubic-bezier(.2, .7, .2, 1);
  /* Spacing scale (4/8/12/16/24/32px) + small-text rung. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --text-sm: 14px;
  /* Code surface — single source for the syntax-highlight background. */
  --code-bg: #0C0F13;       /* canvas-family inset for code; text 15.8:1, tokens >=10:1 */
  --font-display: "Bricolage Grotesque", "Inter Tight", system-ui, sans-serif;
  --font-main: "Inter", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  color-scheme: dark;
}

/* === STATUS UTILITIES + INTERACTION PRIMITIVES (2026-06-04 UI overhaul) =========
   Vanilla equivalents of the spec's Tailwind status utilities. Views compose these
   instead of hardcoding colors. Status is always conveyed by icon + color + text. */
.st-locked   { color: var(--status-locked); }
.st-todo     { color: var(--status-todo); }
.st-progress { color: var(--status-progress); }
.st-review   { color: var(--status-review); }
.st-complete { color: var(--status-complete); }
.st-active   { color: var(--status-active); }
.st-fill-locked   { background: var(--status-locked-muted); }
.st-fill-todo     { background: var(--status-todo-muted); }
.st-fill-progress { background: var(--status-progress-muted); }
.st-fill-review   { background: var(--status-review-muted); }
.st-fill-complete { background: var(--status-complete-muted); }
.st-fill-active   { background: var(--status-active-muted); }

/* Status badge: pill carrying an icon + label so state reads without color alone. */
.status-badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: 999px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
  border: 1px solid transparent; white-space: nowrap; }
.status-badge svg { width: 13px; height: 13px; flex: 0 0 auto; }
.status-badge.locked   { color: var(--status-locked);   background: var(--status-locked-muted);   border-color: var(--status-locked-border); }
.status-badge.todo     { color: var(--status-todo);     background: var(--status-todo-muted);     border-color: var(--status-todo-border); }
.status-badge.progress { color: var(--status-progress); background: var(--status-progress-muted); border-color: var(--status-progress-border); }
.status-badge.review   { color: var(--status-review);   background: var(--status-review-muted);   border-color: var(--status-review-border); }
.status-badge.complete { color: var(--status-complete); background: var(--status-complete-muted); border-color: var(--status-complete-border); }
.status-badge.active   { color: var(--status-active);   background: var(--status-active-muted);   border-color: var(--status-active-border); }

/* Left-accent stripe in a status color for cards/rows (replaces hairline-in-hairline). */
.st-accent { border-left: 2px solid var(--line-strong); padding-left: 14px; }
.st-accent.locked   { border-left-color: var(--status-locked); }
.st-accent.todo     { border-left-color: var(--status-todo); }
.st-accent.progress { border-left-color: var(--status-progress); }
.st-accent.review   { border-left-color: var(--status-review); }
.st-accent.complete { border-left-color: var(--status-complete); }
.st-accent.active   { border-left-color: var(--status-active); }

/* Status dot (for "current"/"in progress" indicators; only the dot pulses, never the row). */
.st-dot { width: 8px; height: 8px; border-radius: 999px; display: inline-block; background: currentColor; flex: 0 0 auto; }
@keyframes st-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.st-dot.pulsing { animation: st-pulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .st-dot.pulsing { animation: none; } }

/* Universal clickable affordance: cursor + hover lift + 150ms transition. */
.clickable { cursor: pointer; transition: background-color var(--transition-smooth), border-color var(--transition-smooth), transform var(--transition-smooth); }
.clickable:hover { border-color: var(--line-strong); background: hsl(0 0% 100% / .05); }
.clickable:active { transform: translateY(1px); }
.clickable[disabled], .clickable.is-locked { cursor: not-allowed; }
.clickable[disabled]:hover, .clickable.is-locked:hover { transform: none; background: inherit; border-color: inherit; }

/* Consistent keyboard focus ring on every interactive element (a11y). */
:where(button, a, [role="button"], [tabindex], input, select, textarea):focus-visible {
  outline: 2px solid var(--status-active); outline-offset: 2px; border-radius: var(--radius-md);
}

* { box-sizing: border-box; }
html { min-height: 100%; scroll-behavior: smooth; }
body {
  min-height: 100%;
  margin: 0;
  color: var(--text);
  font-family: var(--font-main);
  font-size: 15px;
  line-height: 1.6;
  background:
    radial-gradient(1100px 480px at 82% -8%, hsl(199 88% 73% / .06), transparent 60%),
    linear-gradient(var(--blueprint-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--blueprint-grid) 1px, transparent 1px),
    var(--canvas);
  background-size: 100% 100%, 32px 32px, 32px 32px, 100% 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button, input, textarea, select { font: inherit; }
button, a, .clickable { touch-action: manipulation; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--cyan-soft); }

/* Surfaces — depth via borders + grid, never shadows. */
.glass, .glass-strong, .panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  position: relative;
}
.glass-strong { background: var(--surface-2); border-color: var(--line-strong); }
.panel { background: var(--surface-2); }
.card.panel { scroll-margin-top: 96px; } /* so scroll-to-active-chunk clears the sticky topbar */
.learning-block .copy { max-width: 68ch; } /* cap line length for readability at mid widths */

.shell { min-height: 100vh; display: grid; grid-template-columns: 256px minmax(0, 1fr); }
/* Bare layout (mandatory placement exam): single column, no sidebar offset, brand + account menu only. */
.shell-bare { display: block; min-height: 100vh; }
.shell-bare .content { width: min(980px, calc(100vw - 48px)); margin: 0 auto; }
.topbar.topbar-bare { display: flex; align-items: center; justify-content: space-between; }
.topbar-bare .brand { margin: 0; }
.sidebar { padding: 14px 0 14px 14px; }
.sidebar-inner { min-height: calc(100vh - 28px); border-radius: var(--radius-lg); padding: 16px; display: flex; flex-direction: column; gap: 8px; }
.brand { display: flex; align-items: center; gap: 12px; padding: 8px; margin-bottom: 10px; border-radius: var(--radius-md); transition: background var(--transition-smooth); }
.brand:hover { background: hsl(0 0% 100% / .04); }
.brand-mark { width: 38px; height: 38px; display: grid; place-items: center; background: transparent; color: var(--cyan); border: 1px solid var(--cyan); border-radius: var(--radius-md); font-family: var(--font-mono); font-weight: 700; letter-spacing: -.02em; }
/* Top-right account dropdown (Settings / Sign out). The whole box is the clickable trigger. */
.user-menu-wrap { position: relative; z-index: 50; justify-self: end; }
.user-menu-trigger { cursor: pointer; }
.user-menu-trigger:hover { border-color: var(--line-strong); }
.user-menu-backdrop { position: fixed; inset: 0; z-index: 40; }
.user-menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 50; min-width: 210px; max-width: 260px; padding: 6px; border-radius: var(--radius-md); border: 1px solid var(--line-strong); background: var(--surface); box-shadow: 0 14px 36px hsl(0 0% 0% / .55); }
.user-menu-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--line); margin-bottom: 6px; }
.user-menu-name { font-size: 13px; font-weight: 600; color: var(--text); }
.user-menu-email { font-size: 11px; color: var(--text-dim); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 8px 10px; border: 0; background: transparent; color: var(--text); font-family: var(--font-main); font-size: 13px; border-radius: 8px; cursor: pointer; }
.user-menu-item:hover, .user-menu-item:focus-visible { background: var(--surface-2); color: var(--text); outline: none; }
.brand-title { display: block; font-family: var(--font-display); font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.brand-subtitle { color: var(--muted); font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .14em; }
.nav { display: grid; gap: 2px; }
.nav-link { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 0 12px; border-radius: var(--radius-md); color: var(--text-dim); font-size: 13px; font-weight: 500; border: 1px solid transparent; transition: color var(--transition-smooth), background var(--transition-smooth), border-color var(--transition-smooth); }
.nav-link:hover { color: var(--text); background: hsl(0 0% 100% / .04); }
.nav-link.active { color: var(--text); background: var(--status-active-muted); border-color: transparent; box-shadow: inset 2px 0 0 var(--status-active); }

.main { min-width: 0; }
.topbar { position: sticky; top: 0; z-index: 20; padding: 14px; display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; gap: 12px; align-items: center; background: var(--canvas); border-bottom: 1px solid var(--line); }
.top-chip, .search, .top-actions { min-height: 44px; border-radius: var(--radius-md); display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--surface); border: 1px solid var(--line); min-width: 0; }
.top-actions { min-width: max-content; }
/* Back area is not a heavy box — ghost button + plain breadcrumb on the page. min-width:0 lets
   the grid track shrink below the breadcrumb's intrinsic width at narrow viewports. */
.top-chip { background: transparent; border-color: transparent; padding-left: 2px; min-width: 0; }
/* Ellipsize instead of clipping mid-word ("LEARNING PAT" at 390px). display:block (not
   inline-flex) so text-overflow applies to the text itself; nowrap is kept. */
.breadcrumb { font-family: var(--font-mono); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .12em; color: var(--text-dim); display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bc-sep { color: var(--muted); opacity: .6; }
.kbd-hint { margin-left: auto; flex: 0 0 auto; font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 2px 6px; letter-spacing: .04em; }
/* Search gets a focus ring on the container (the input itself stays outline-free). */
.search:focus-within { border-color: var(--status-active); box-shadow: 0 0 0 2px var(--status-active-muted); }
.search input { width: 100%; min-height: 26px; border: 0; outline: 0; background: transparent; color: var(--text); padding: 0; font-size: 13px; font-family: var(--font-mono); }
.search input::placeholder, input::placeholder, textarea::placeholder { color: var(--muted); }
.content { width: min(1400px, calc(100vw - 286px)); margin: 0 auto; padding: 18px 22px 80px; scroll-margin-top: 96px; }
/* #content is focused programmatically after each route change as an SR landing point — it is a
   non-interactive container, so it must NOT paint a visible focus ring (that drew a box around the
   whole page). Interactive controls keep their :focus-visible ring via the global rule. */
.content:focus, .content:focus-visible { outline: none; }

.page { display: grid; gap: 28px; padding: 8px 0 44px; animation: rise var(--dur-slow) var(--ease-out); }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
/* Staggered page-load cascade: grid children rise in sequence (small, tasteful, capped at 6
   steps) reusing the `rise` keyframe. Inherits the global prefers-reduced-motion kill-switch. */
.grid > *, .dashboard-grid > *, .cols-3 > *, .cols-4 > * {
  animation: rise var(--dur-base) var(--ease-out) both;
}
.grid > *:nth-child(1), .dashboard-grid > *:nth-child(1), .cols-3 > *:nth-child(1), .cols-4 > *:nth-child(1) { animation-delay: 0ms; }
.grid > *:nth-child(2), .dashboard-grid > *:nth-child(2), .cols-3 > *:nth-child(2), .cols-4 > *:nth-child(2) { animation-delay: 50ms; }
.grid > *:nth-child(3), .dashboard-grid > *:nth-child(3), .cols-3 > *:nth-child(3), .cols-4 > *:nth-child(3) { animation-delay: 100ms; }
.grid > *:nth-child(4), .dashboard-grid > *:nth-child(4), .cols-3 > *:nth-child(4), .cols-4 > *:nth-child(4) { animation-delay: 150ms; }
.grid > *:nth-child(5), .dashboard-grid > *:nth-child(5), .cols-3 > *:nth-child(5), .cols-4 > *:nth-child(5) { animation-delay: 200ms; }
.grid > *:nth-child(n+6), .dashboard-grid > *:nth-child(n+6), .cols-3 > *:nth-child(n+6), .cols-4 > *:nth-child(n+6) { animation-delay: 250ms; }
/* Page headers sit directly on the grid-textured page background (no nested card box). */
.header { padding: 6px 2px 14px; display: flex; justify-content: space-between; gap: 18px; align-items: end; border-bottom: 1px solid var(--line); }
.kicker, .label { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .14em; font-weight: 500; }
h1 { margin: 12px 0 0; font-family: var(--font-display); font-size: clamp(30px, 4.4vw, 58px); font-weight: 700; line-height: 1.02; letter-spacing: -.025em; max-width: 980px; color: var(--text); }
h2 { margin: 0; font-family: var(--font-display); font-size: 14px; line-height: 1.2; font-weight: 700; letter-spacing: -.01em; }
/* Mid display tier between the huge h1 and 15px body (3-level hierarchy). */
.section-title { margin: 0; font-family: var(--font-display); font-size: 23px; line-height: 1.18; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
h3 { margin: 0; font-family: var(--font-display); font-size: 16px; line-height: 1.3; font-weight: 600; letter-spacing: -.01em; }
p { margin: 0; }
.copy { color: var(--text-dim); font-size: 15px; line-height: 1.65; }
.grid { display: grid; gap: 14px; }
.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.workspace-grid { grid-template-columns: minmax(0, 1fr) 320px; }
.lesson-grid { grid-template-columns: minmax(0, 1fr) 380px; }
.challenge-grid { grid-template-columns: 380px minmax(0, 1fr); }
.graph-grid { grid-template-columns: 230px minmax(0, 1fr) 340px; align-items: start; }
/* Graph + detail: the canvas takes the full content width (filter moved to a bar above) so nodes
   render at a legible scale instead of being crushed to fit a narrow column. */
.graph-detail-grid { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }
.graph-controls-main { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; }
.graph-legend-details { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.graph-legend-details > summary { cursor: pointer; color: var(--muted); list-style: none; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .12em; }
.graph-legend-details > summary::-webkit-details-marker { display: none; }
.graph-legend-details > summary::before { content: '▸ '; }
.graph-legend-details[open] > summary::before { content: '▾ '; }
.graph-legend-body { display: flex; flex-wrap: wrap; gap: 14px 32px; margin-top: 12px; align-items: flex-start; }
@media (max-width: 900px) { .graph-detail-grid { grid-template-columns: minmax(0, 1fr); } }
.node.graph-dim { opacity: .18; }
input[type="range"] { padding: 0; border: 0; background: transparent; accent-color: var(--cyan); height: 22px; }
.dashboard-grid { grid-template-columns: minmax(0, 1.5fr) minmax(300px, .8fr); }
.path-grid, .concept-grid { grid-template-columns: 320px minmax(0, 1fr); }
.new-project-grid { grid-template-columns: minmax(0, 1fr) 360px; }
.planning-grid { grid-template-columns: minmax(0, 1fr) 340px; }

.card { border-radius: var(--radius-lg); padding: 20px; background: var(--surface); border: 1px solid var(--line); transition: border-color var(--transition-smooth); }
.card.glass:hover, .tile:hover { border-color: var(--line-strong); }
.card-head { display: flex; justify-content: space-between; gap: 12px; align-items: start; padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.card-head h2 { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .12em; color: var(--text-dim); font-weight: 500; }
.tile { border-radius: var(--radius-md); padding: 16px; border: 1px solid var(--line); background: var(--surface-2); transition: border-color var(--transition-smooth); }
button.tile { text-align: left; color: inherit; }
.metric-value { margin-top: 10px; font-family: var(--font-display); font-size: 44px; line-height: 1; font-weight: 700; letter-spacing: -.03em; color: var(--text); font-variant-numeric: tabular-nums; }
.mini-bar { height: 4px; background: hsl(0 0% 100% / .08); border-radius: 2px; overflow: hidden; margin-top: 14px; }
.mini-bar > span { display: block; height: 100%; background: var(--cyan); border-radius: inherit; }
/* Status-colored progress bars (dashboard metric cards). */
.mini-bar.bar-progress > span { background: var(--status-progress); }
.mini-bar.bar-complete > span { background: var(--status-complete); }
.mini-bar.bar-review > span { background: var(--status-review); }
.mini-bar.bar-active > span { background: var(--status-active); }
/* Status-colored stat tile head: label + corner status icon. */
.metric-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.metric-ic svg { width: 15px; height: 15px; }
.metric-value.st-complete { color: var(--status-complete); }
.metric-value.st-progress { color: var(--status-progress); }
.metric-value.st-review { color: var(--status-review); }
.metric-value.st-active { color: var(--status-active); }
/* Detail-drawer 'Mark for review' (disabled — review is evidence-driven, never set by hand). */
.btn-review { color: var(--status-review); border-color: var(--status-review-border); }
.btn-review svg { width: 15px; height: 15px; }
/* Workspace: file rows with type icons, locked editor (review accent), empty run log. */
.file-name { display: inline-flex; align-items: center; gap: 8px; }
.file-name svg { color: var(--text-dim); flex: 0 0 auto; }
.empty-log { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 16px; text-align: center; border-radius: var(--radius-md);
  background-image: linear-gradient(var(--blueprint-grid) 1px, transparent 1px), linear-gradient(90deg, var(--blueprint-grid) 1px, transparent 1px);
  background-size: 22px 22px; }
.empty-log svg { color: var(--text-dim); }
.empty-log .copy { color: var(--muted); }
.locked-panel .button svg { width: 15px; height: 15px; }
/* Progress BAR. Renamed from .progress → .progress-bar: the bare .progress selector
   collided with the .status-badge.progress status modifier (forcing badges to 6px + clip). */
.progress-bar { height: 6px; border-radius: 3px; background: hsl(0 0% 100% / .08); overflow: hidden; }
.progress-bar > span { display: block; height: 100%; background: var(--cyan); border-radius: inherit; }
/* Source-analyze loading affordance: reassurance copy + shimmer skeleton so the multi-second LLM
   wait never reads as frozen; a slow-hint fades in after ~8s. Reduced-motion keeps everything visible. */
.ingest-loading { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
.ingest-loadhint { color: var(--text-dim); font-size: 13px; }
.skeleton-row { height: 14px; border-radius: var(--radius-md); background: linear-gradient(90deg, var(--surface-2) 25%, hsl(0 0% 100% / .07) 50%, var(--surface-2) 75%); background-size: 200% 100%; animation: shimmer 1.4s ease-in-out infinite; }
.skeleton-row:nth-child(3) { width: 82%; }
.skeleton-row:nth-child(4) { width: 60%; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.ingest-slowhint { color: var(--muted); font-size: 12px; opacity: 0; animation: fadein .4s var(--ease-out) forwards; animation-delay: 8s; }
@keyframes fadein { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .ingest-slowhint { opacity: 1; } }

.button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 40px; padding: 0 16px; border-radius: var(--radius-md); border: 1px solid var(--cyan); background: var(--cyan); color: var(--status-active-foreground); font-size: 13px; font-weight: 600; transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.button:hover { background: #9adcf8; border-color: #9adcf8; }
.button.secondary { color: var(--text); background: transparent; border: 1px solid var(--line-strong); }
.button.secondary:hover { border-color: var(--cyan); color: var(--cyan); background: var(--cyan-soft); }
.button.accent { background: var(--amber); border-color: var(--amber); color: #1A1304; }
.button.accent:hover { background: #f0c777; border-color: #f0c777; }
.button.ghost { color: var(--text-dim); background: transparent; border: 1px solid var(--line); }
.button.ghost:hover { color: var(--text); border-color: var(--line-strong); }
.button:disabled, .button.secondary:disabled { opacity: .55; cursor: not-allowed; border-color: var(--line-strong); }
/* Loading affordance: a small spinner before the label while .is-loading is set. */
@keyframes spin { to { transform: rotate(360deg); } }
.button.is-loading { position: relative; }
.button.is-loading::before {
  content: ''; width: 1em; height: 1em; border-radius: 999px;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: spin var(--dur-slow) linear infinite; flex: 0 0 auto;
}
@media (prefers-reduced-motion: reduce) {
  .button.is-loading::before { content: '…'; width: auto; height: auto; border: 0; animation: none; }
}
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
.pill { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--line); background: transparent; color: var(--text-dim); font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: .02em; white-space: nowrap; }
.pill.dark { background: hsl(0 0% 100% / .06); color: var(--text); border-color: var(--line-strong); }
.pill.green { color: var(--green); background: var(--green-soft); border-color: hsl(150 55% 67% / .3); }
.pill.amber { color: var(--amber); background: var(--amber-soft); border-color: hsl(38 75% 63% / .3); }
.pill.red { color: var(--red); background: var(--red-soft); border-color: hsl(8 73% 66% / .3); }
/* Informational/category label — neutral so cyan stays reserved for active/interactive states. */
.pill.blue { color: var(--text-dim); background: var(--surface-2); border-color: var(--line); }

.field { display: grid; gap: 6px; }
.field .label, label.label { font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em; }
input, textarea, select { width: 100%; border-radius: var(--radius-md); border: 1px solid var(--line-ui); background: var(--canvas); color: var(--text); padding: 11px 12px; outline: 0; font-size: var(--text-sm); transition: border var(--transition-smooth), box-shadow var(--transition-smooth); }
input:focus, textarea:focus, select:focus { border-color: var(--cyan); box-shadow: 0 0 0 3px var(--cyan-soft); }
/* Focus ring is defined once above via the tokenized --status-active rule. */
.search input:focus-visible { outline: 0; }
textarea { min-height: 120px; resize: vertical; line-height: 1.6; }
.code-editor { min-height: 460px; background: var(--code-bg); color: var(--text); border-radius: var(--radius-md); padding: 16px; border: 1px solid var(--line); font-family: var(--font-mono); font-size: 13px; line-height: 1.65; tab-size: 2; }
.monaco-host { height: 460px; border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--line); }
.dark-output { background: var(--code-bg); color: var(--text); border-radius: var(--radius-md); padding: 14px; min-height: 160px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7; border: 1px solid var(--line); }
.tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.tab { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 8px 12px; background: transparent; color: var(--text-dim); font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: .04em; transition: color var(--transition-smooth), border-color var(--transition-smooth); }
.tab:hover { color: var(--text); border-color: var(--line-strong); }
.tab.active { background: hsl(0 0% 100% / .06); color: var(--text); border-color: var(--cyan); }
/* Dashboard ingest chips (dedicated so the shared .tab is untouched). Icon + color + text. */
.src-chip, .depth-chip { display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: var(--radius-md); padding: 8px 12px; background: transparent; color: var(--text-dim); font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: .04em; cursor: pointer; transition: color var(--transition-smooth), border-color var(--transition-smooth), background var(--transition-smooth); }
.src-chip svg { width: 14px; height: 14px; flex: 0 0 auto; }
.src-chip:hover, .depth-chip:hover { color: var(--text); border-color: var(--line-strong); }
.src-chip.active { color: var(--status-active); background: var(--status-active-muted); border-color: var(--status-active-border); }
/* Depth chips carry a tone dot always (intensity readable without color alone), filled when selected. */
.depth-chip .tone-dot { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 auto; }
.depth-chip.tone-todo .tone-dot { background: var(--status-todo); }
.depth-chip.tone-progress .tone-dot { background: var(--status-progress); }
.depth-chip.tone-active .tone-dot { background: var(--status-active); }
.depth-chip.tone-todo.active { color: var(--status-todo); background: var(--status-todo-muted); border-color: var(--status-todo-border); }
.depth-chip.tone-progress.active { color: var(--status-progress); background: var(--status-progress-muted); border-color: var(--status-progress-border); }
.depth-chip.tone-active.active { color: var(--status-active); background: var(--status-active-muted); border-color: var(--status-active-border); }
/* Prominent generate CTA: full-width on mobile, auto on desktop; trailing/leading icons. */
.cta-generate { min-height: 44px; font-size: 14px; }
.cta-generate svg { width: 15px; height: 15px; }
@media (max-width: 720px) { .cta-generate { width: 100%; } }

/* Code-block syntax highlight tokens (on the dark .dark-output bg). */
.code-example { margin-top: 14px; display: grid; gap: 8px; }
.code-example .dark-output { margin: 0; }
.code-hl .tok-kw { color: var(--cyan); }
.code-hl .tok-const { color: var(--amber); }
.code-hl .tok-fn { color: var(--violet); }
.code-hl .tok-num { color: var(--green); }
.code-hl .tok-str { color: var(--amber); }
.code-hl .tok-com { color: var(--text-dim); font-style: italic; }

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th { text-align: left; color: var(--muted); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .1em; border-bottom: 1px solid var(--line); padding: 10px; }
.table td { border-bottom: 1px solid var(--line); padding: 10px; }

/* ---- Knowledge-graph honeycomb launcher (ported from the Apple-Watch UI) ----
   A black viewport holds a hex lattice of circular lesson tiles. The fisheye engine (main.js,
   initGraphPanZoom→applyHoneycomb) sets each tile's transform/opacity from its distance to the
   viewport center; drag pans, wheel zooms, click opens the detail modal. */
.hc-canvas { position: relative; max-width: 100%; height: clamp(500px, 70vh, 760px); overflow: hidden; border-radius: var(--radius-lg); border: 1px solid var(--line); cursor: grab; touch-action: none;
  background-color: #050608; background-image: radial-gradient(circle at 50% 42%, hsl(199 88% 60% / .07), transparent 62%); }
.hc-canvas:active { cursor: grabbing; }
.hc-lattice { position: absolute; left: 50%; top: 50%; width: 0; height: 0; will-change: transform; }
.hex-tile { position: absolute; display: grid; place-items: center; padding: 0; border: 0; background: transparent; cursor: pointer; transform-origin: center center; will-change: transform, opacity; }
.hex-disc { display: grid; place-items: center; width: 100%; height: 100%; border-radius: 999px; border: 2px solid var(--line-strong); color: var(--text);
  background: radial-gradient(circle at 32% 26%, var(--surface-2), #0c0e11);
  box-shadow: 0 6px 18px hsl(0 0% 0% / .55), inset 0 1px 0 hsl(0 0% 100% / .06);
  transition: border-color var(--transition-smooth), box-shadow var(--transition-smooth); }
.hex-tile:hover .hex-disc { border-color: var(--text); }
.hex-tile.is-focused .hex-disc { box-shadow: 0 10px 28px hsl(0 0% 0% / .6), 0 0 0 4px hsl(0 0% 100% / .06); }
.hex-tile:active { transform: scale(.9); }
/* status ring colours (mirror the node-colour legend); applied to the disc in both tile + modal */
.hex-disc.verified { border-color: var(--status-complete); color: var(--status-complete); box-shadow: 0 0 0 3px var(--status-complete-border), 0 8px 22px hsl(0 0% 0% / .5); }
.hex-disc.tested { border-color: var(--status-progress); color: var(--status-progress); }
.hex-disc.needs-review { border-color: var(--status-review); border-style: dashed; color: var(--status-review); }
.hex-disc.introduced { border-color: var(--status-todo-border); color: var(--text-dim); }
.hex-disc.locked-node { border-color: var(--status-locked-border); border-style: dashed; color: var(--muted); }
/* Placement-diagnostic tints — all DASHED (provisional, never challenge-verified), so the whole
   placement map reads as one group distinct from the solid real-progress rings above.
   comfortable = green (tested out), needs-work = amber (reinforce), unknown = cyan (new/to-learn). */
.hex-disc.placement { border-color: var(--status-complete); border-style: dashed; color: var(--status-complete); }
.hex-disc.placement-review { border-color: var(--status-progress); border-style: dashed; color: var(--status-progress); }
.hex-disc.placement-new { border-color: var(--status-active); border-style: dashed; color: var(--status-active); }
.hex-verified { position: absolute; right: 1px; bottom: 1px; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 999px; background: var(--canvas); color: var(--status-complete); }
/* Title under each disc so nodes are identifiable without clicking; the fisheye engine fades it in
   as a tile nears the focus center (opacity set per-frame in applyHoneycomb). */
.hex-label { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 5px; width: 112px; text-align: center;
  font-size: 11px; line-height: 1.16; font-weight: 500; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  text-shadow: 0 1px 3px #000, 0 0 3px #000; pointer-events: none; opacity: 0; }
/* right gutter (140px) keeps the centered caption clear of the bottom-right zoom controls so the
   two never overlap. */
.hc-caption { position: absolute; left: 12px; right: 170px; bottom: 14px; text-align: center; pointer-events: none; font-family: var(--font-mono); font-size: 12px; letter-spacing: .04em; color: var(--text); text-shadow: 0 1px 10px #000, 0 0 2px #000; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* detail modal (the watch "open app" overlay) */
.hc-modal-overlay { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 20px; background: hsl(0 0% 0% / .8); backdrop-filter: blur(6px); }
.hc-modal { position: relative; width: min(560px, 94vw); max-height: 86vh; overflow-y: auto; border-radius: var(--radius-lg); border: 1px solid var(--line-strong); background: var(--surface); padding: 26px; box-shadow: 0 30px 80px hsl(0 0% 0% / .6); }
.hc-modal-close { position: absolute; right: 14px; top: 14px; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface-2); color: var(--text-dim); cursor: pointer; }
.hc-modal-close:hover { color: var(--text); border-color: var(--line-strong); }
.hc-modal-head { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.hc-modal-head .hex-disc { width: 54px; height: 54px; flex: none; }
.hc-modal-head h2 { font-size: 20px; line-height: 1.2; }
.hc-modal-head .min-w-0 { min-width: 0; }
.graph-zoom { position: absolute; right: 12px; bottom: 12px; z-index: 8; display: flex; gap: 6px; }
.graph-zoom .button { min-height: 34px; min-width: 34px; padding: 0 10px; background: var(--surface); border-color: var(--line-strong); color: var(--text); }
.graph-zoom .button:hover { background: var(--surface-2); }
.graph-mobile-hint { display: none; }
@media (max-width: 720px) { .graph-mobile-hint { display: block; } }
/* ---- Mandatory placement diagnostic exam ---- */
.exam-card { max-width: 780px; margin: 0 auto; }
.exam-options { display: grid; gap: 10px; margin-top: 16px; }
.exam-option { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 14px 16px; border-radius: var(--radius-md); border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--text); font: inherit; font-size: 14px; cursor: pointer; transition: border-color var(--transition-smooth), background var(--transition-smooth); }
.exam-option:hover { border-color: var(--text); }
.exam-option.is-selected { border-color: var(--status-active); box-shadow: inset 0 0 0 1px var(--status-active); background: hsl(199 88% 60% / .08); }
.exam-option-mark { display: inline-flex; width: 18px; flex: none; color: var(--status-active); }
.chip-count { margin-left: 6px; font-family: var(--font-mono); font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.graph-time-readout { font-variant-numeric: tabular-nums; }
.graph-controls { display: grid; gap: 12px; }
.legend { display: flex; gap: 14px; flex-wrap: wrap; color: var(--muted); font-family: var(--font-mono); font-size: 11px; }
.legend span { display: inline-flex; align-items: center; gap: 7px; }
/* Legend dots are reconciled to the actual node status tokens (was amber/cyan/amber, which
   mismatched the green/amber/orange node borders and used amber for two different states). */
.legend-dot { width: 9px; height: 9px; border-radius: 999px; display: inline-block; background: var(--status-todo); }
.legend-dot.mastered { background: var(--status-complete); }
.legend-dot.placement { background: transparent; box-shadow: inset 0 0 0 2px var(--status-complete); }
.legend-dot.placement-review { background: transparent; box-shadow: inset 0 0 0 2px var(--status-progress); }
.legend-dot.placement-new { background: transparent; box-shadow: inset 0 0 0 2px var(--status-active); }
.legend-dot.tested { background: var(--status-progress); }
.legend-dot.review { background: var(--status-review); box-shadow: 0 0 0 1.5px var(--status-review-muted); }
.legend-dot.locked { background: var(--status-locked); opacity: .6; }
.detail-list { display: grid; gap: 8px; }
.status-row { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 11px; border-radius: var(--radius-md); background: var(--surface-2); border: 1px solid var(--line); }
.status-row:disabled, .locked { opacity: .5; cursor: not-allowed; }
/* Narrow widths (e.g. planning milestone rows at 390px): pills/buttons/badges keep their
   intrinsic size; the text span is the one that shrinks and wraps. */
.status-row > .pill, .status-row > .button, .status-row > .status-badge { flex-shrink: 0; }
.status-row > span { min-width: 0; }

.learning-block { margin-top: 14px; border-radius: var(--radius-md); padding: 14px; background: var(--surface-2); border: 1px solid var(--line); }
.chunk-frame { margin-top: 14px; display: grid; gap: 14px; }
.template-banner { border-radius: var(--radius-md); padding: 16px; background: var(--surface-2); border: 1px solid var(--line); display: grid; gap: 10px; }
.template-map { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.template-step { border-radius: var(--radius-md); padding: 12px; background: var(--surface); border: 1px solid var(--line); display: grid; gap: 6px; }
.template-step span { font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .08em; color: var(--text-dim); }
.template-step small { color: var(--muted); line-height: 1.5; }
.visual-policy { margin-top: 14px; border-radius: var(--radius-md); padding: 16px; background: var(--cyan-soft); border: 1px solid hsl(199 88% 73% / .25); display: grid; gap: 12px; }
.policy-list { display: grid; gap: 8px; }
.policy-item { display: grid; grid-template-columns: 30px 1fr; align-items: start; gap: 10px; border-radius: var(--radius-md); padding: 11px; background: var(--surface); border: 1px solid var(--line); color: var(--text-dim); font-size: 13px; line-height: 1.5; }
.reflection-prompt { margin: 10px 0 0; padding: 9px 11px; border-radius: var(--radius-md); background: hsl(0 0% 100% / .04); color: var(--text-dim); font-size: 13px; line-height: 1.5; }
.callout-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.callout-grid .learning-block { margin-top: 0; }
.warning-card { background: var(--amber-soft); border-color: hsl(38 75% 63% / .3); }
.safety-card { background: var(--red-soft); border-color: hsl(8 73% 66% / .3); }
.artifact-ladder { border-radius: var(--radius-md); padding: 14px; background: var(--surface-2); border: 1px solid var(--line); display: grid; gap: 10px; }
.artifact-item { display: grid; grid-template-columns: 30px 1fr; gap: 10px; align-items: start; border-radius: var(--radius-md); padding: 11px; background: var(--surface); border: 1px solid var(--line); }
.artifact-step { width: 24px; height: 24px; border-radius: 999px; display: grid; place-items: center; background: var(--cyan-soft); color: var(--cyan); border: 1px solid hsl(199 88% 73% / .35); font-family: var(--font-mono); font-size: 11px; font-weight: 600; }
.artifact-item b { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: var(--text-dim); font-weight: 500; }
.artifact-item span span { display: block; margin-top: 4px; color: var(--text-dim); font-size: 13px; line-height: 1.55; }
.evidence-strip { border-radius: var(--radius-md); padding: 14px; background: var(--cyan-soft); border: 1px solid hsl(199 88% 73% / .25); display: grid; gap: 8px; }
.criteria-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.criteria-chip { border-radius: 999px; padding: 6px 10px; background: var(--surface); border: 1px solid var(--line); color: var(--text-dim); font-family: var(--font-mono); font-size: 11px; font-weight: 500; }
.gate-rubric { margin-top: 12px; border-radius: var(--radius-md); padding: 13px; background: var(--surface-2); border: 1px solid var(--line); }
.term-primer { margin-top: 14px; border-radius: var(--radius-md); padding: 14px; background: var(--cyan-soft); border: 1px solid hsl(199 88% 73% / .25); }
/* A11y: .label's --muted (#7D8794) only hits ~3.8:1 on these tinted card fills (effective bgs
   ~#212E37 / #322C22 / #302223). --text-dim (#9AA3AD) clears 4.5:1 on all three (worst 5.41:1). */
.term-primer .label, .warning-card .label, .safety-card .label { color: var(--text-dim); }
.term-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 10px; }
.term-card { border-radius: var(--radius-md); padding: 12px; background: var(--surface); border: 1px solid var(--line); }
.term-card b { display: block; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--cyan); margin-bottom: 6px; font-weight: 500; }
.term-card span { display: block; color: var(--text-dim); font-size: 13px; line-height: 1.55; }
.gate-panel { margin-top: 16px; border-radius: var(--radius-md); padding: 16px; background: var(--surface-2); border: 1px solid var(--line-strong); }
.locked-panel { border-radius: var(--radius-md); padding: 16px; background: var(--red-soft); border: 1px solid hsl(8 73% 66% / .3); }
.mini-answer { margin: 12px 0 0; border-radius: var(--radius-md); padding: 13px; background: var(--canvas); border: 1px solid var(--line); color: var(--text); white-space: pre-wrap; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.6; }

/* Visual-aid SVG diagrams — light line-art on the dark canvas. */
.visual-aid { margin: 16px 0 0; border-radius: var(--radius-md); background: var(--canvas); border: 1px solid var(--line); overflow: hidden; }
.visual-source-note { margin-top: 8px; border-radius: var(--radius-md); padding: 11px; background: var(--surface-2); border: 1px solid var(--line); display: grid; gap: 6px; color: var(--muted); font-family: var(--font-mono); font-size: 11px; line-height: 1.5; }
.visual-source-note b { color: var(--text); }
.visual-aid svg { width: 100%; height: auto; display: block; fill: none; stroke: var(--text); stroke-width: 2; overflow: visible; }
.visual-aid text { fill: var(--text); stroke: none; font-family: var(--font-mono); font-size: 16px; font-weight: 500; text-transform: uppercase; letter-spacing: .04em; }
.visual-aid .small { font-size: 13px; }
.visual-aid .muted { fill: var(--muted); }
.diagram-frame { fill: hsl(0 0% 100% / .02); stroke: var(--line-strong); }
.diagram-chip, .diagram-box { fill: var(--surface-2); stroke: var(--text); stroke-width: 2; }
.diagram-box.accent, .diagram-callout.accent { fill: var(--cyan-soft); stroke: var(--cyan); }
.diagram-callout { fill: var(--surface-2); stroke: var(--line-strong); }
.diagram-wire, .diagram-axis { stroke: var(--text); stroke-linecap: round; }
.diagram-wire.strong { stroke-width: 3; }
.diagram-dashed { stroke: var(--muted); stroke-dasharray: 6 6; stroke-linecap: round; }
.diagram-node { fill: var(--surface); stroke: var(--text); stroke-width: 2; }
.diagram-led { fill: hsl(199 88% 73% / .18); stroke: var(--cyan); stroke-width: 2; }
.diagram-ground { stroke: var(--text); stroke-linecap: round; }
.diagram-resistor { stroke: var(--amber); stroke-width: 2.5; fill: none; }
.visual-aid .signal { stroke: var(--cyan); stroke-width: 4; fill: none; stroke-linejoin: round; }
.board-body { fill: hsl(199 88% 73% / .08); stroke: var(--text); stroke-width: 2; }
.board-port { fill: hsl(0 0% 100% / .14); stroke: var(--text); stroke-width: 1.6; }
.header-row rect { fill: hsl(0 0% 100% / .1); stroke: var(--line-strong); }
.header-row circle { fill: var(--canvas); stroke: var(--muted); stroke-width: 1.4; }
.header-plastic { fill: hsl(0 0% 0% / .5); stroke: var(--line-strong); stroke-width: 2; }
.header-holes circle { fill: var(--canvas); stroke: var(--muted); stroke-width: 2; }
.accent-wire { stroke: var(--cyan); }
.accent-node { fill: hsl(199 88% 73% / .16); stroke: var(--cyan); stroke-width: 3; }
.large-chip { fill: hsl(0 0% 0% / .5); stroke: var(--line-strong); }
.large-chip + .chip-legs, .chip-legs rect { fill: hsl(0 0% 100% / .3); stroke: var(--muted); stroke-width: 1.5; }
.diagram-led-dot { fill: hsl(199 88% 73% / .22); stroke: var(--cyan); stroke-width: 2.5; }
.diagram-led-off { fill: hsl(0 0% 100% / .06); stroke: var(--muted); stroke-width: 2.5; }
.diagram-led-on { fill: hsl(38 75% 63% / .26); stroke: var(--amber); stroke-width: 3; }
.light-ray { stroke: var(--amber); stroke-width: 3; stroke-linecap: round; fill: none; }

/* Mono treatment for metadata-ish labels. */
.kicker, .label, .pill, .tab, .brand-subtitle, .criteria-chip, .node small, .node-recall, .legend, .cluster-label { font-family: var(--font-mono); }

.mobile-nav { display: none; }
.hidden { display: none !important; }
/* Visually-hidden (screen-reader only) — standard clip pattern. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* Skip-to-content link: hidden until focused, then top-left and on-surface. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 1000;
  padding: 10px 14px; border-radius: var(--radius-md);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line-strong); font-family: var(--font-mono);
  font-size: 13px; font-weight: 600;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ---- 3-pane lesson view ---- */
.lesson3 { grid-template-columns: 240px minmax(0, 1fr) 320px; align-items: start; }
.lesson-side { gap: 14px; }
.lesson-footer { margin-top: 4px; border: 1px solid var(--line-strong); border-radius: var(--radius-lg); background: var(--surface-2); padding: 14px 16px; display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; }
.lesson-foot-progress { min-width: 200px; flex: 1; display: grid; gap: 8px; }
.mini-graph { display: grid; gap: 6px; justify-items: stretch; }
.mini-node { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 8px 10px; font-size: 12px; color: var(--text-dim); background: var(--surface); }
.mini-node.here { border-color: var(--cyan); color: var(--text); box-shadow: inset 2px 0 0 var(--cyan); }
.mini-node.prev { border-style: dashed; }
.mini-edge { width: 1px; height: 12px; background: var(--line-strong); margin: 0 auto; }

/* ---- Intake stepper ---- */
.stepper { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.step { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }
.step-n { width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; font-family: var(--font-mono); font-size: 11px; border: 1px solid var(--line-strong); color: var(--muted); }
.step-name { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: var(--text-dim); }
.step-n svg { width: 14px; height: 14px; }
/* current: active ring + filled number */
.step.active { border-color: var(--status-active-border); background: var(--status-active-muted); box-shadow: 0 0 0 1px var(--status-active-border); }
.step.active .step-n { background: var(--status-active); color: var(--status-active-foreground); border-color: var(--status-active); }
.step.active .step-name { color: var(--text); }
/* completed: filled green + check icon */
.step.done .step-n { background: var(--status-complete); color: var(--status-complete-foreground); border-color: var(--status-complete); }
.step.done .step-name { color: var(--text-dim); }
/* future: locked outline */
.step.todo { border-color: var(--status-locked-border); }
.step.todo .step-n { color: var(--status-locked); border-color: var(--status-locked-border); }
.step-sep { flex: 1; min-width: 12px; height: 2px; border-radius: 2px; background: var(--line); transition: background var(--transition-smooth); }
.step-sep.filled { background: var(--status-complete); }
/* Compact concept-graph preview for the empty 'Maps onto your graph' rail. */
.graph-preview { display: flex; align-items: center; gap: 4px; padding: 8px 4px; }
.gp-node { width: 34px; height: 34px; border-radius: 999px; display: grid; place-items: center; border: 1px solid var(--line-strong); flex: 0 0 auto; }
.gp-node.complete { color: var(--status-complete); background: var(--status-complete-muted); border-color: var(--status-complete-border); }
.gp-node.progress { color: var(--status-progress); background: var(--status-progress-muted); border-color: var(--status-progress-border); }
.gp-node.locked { color: var(--status-locked); background: var(--status-locked-muted); border-color: var(--status-locked-border); border-style: dashed; }
.gp-edge { flex: 1; height: 2px; border-radius: 2px; background: linear-gradient(90deg, var(--status-complete-border), var(--status-locked-border)); }
.graph-preview-legend { display: flex; gap: 14px; margin-top: 6px; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .1em; }

/* Learn page — Path Progress rows: circular status badge + title + per-lesson concept bar. */
.path-row { display: flex; align-items: flex-start; gap: 12px; width: 100%; text-align: left; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface); }
.path-badge { width: 30px; height: 30px; border-radius: 999px; display: grid; place-items: center; flex: 0 0 auto; border: 1px solid var(--line-strong); margin-top: 1px; }
.path-badge.complete { color: var(--status-complete); background: var(--status-complete-muted); border-color: var(--status-complete-border); }
.path-badge.progress { color: var(--status-progress); border-color: var(--status-progress-border); }
.path-badge.locked { color: var(--status-locked); border-color: var(--status-locked-border); border-style: dashed; }
.path-row-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.path-title { font-size: 13px; color: var(--text-dim); }
.path-title.bold { color: var(--text); font-weight: 600; }
.path-title.muted { color: var(--muted); }
.path-desc { font-family: var(--font-main); font-size: 11px; color: var(--muted); }
.sim-label { font-family: var(--font-mono); font-size: 11px; color: var(--text-dim); }
/* Challenge page real-engine mini-simulation (avr8js onboard-LED preview + serial). */
.minisim-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.minisim-status { font: 11px/1.5 var(--font-mono); color: var(--muted); white-space: pre-wrap; }
.minisim-status[data-kind="error"] { color: var(--status-review-foreground, #f2b8b8); }
.minisim-status[data-kind="ok"] { color: var(--green); }
.minisim-stage { display: flex; align-items: stretch; gap: 14px; flex-wrap: wrap; }
.minisim-led { display: flex; flex-direction: column; align-items: center; gap: 8px; justify-content: center; padding: 14px 20px; background: var(--canvas); border: 1px solid var(--line); border-radius: var(--radius-md); }
.minisim-serial { flex: 1; min-width: 200px; min-height: 96px; max-height: 200px; overflow: auto; margin: 0; background: var(--canvas); color: var(--green); border: 1px solid var(--line); border-radius: 8px; padding: 10px; font: 12px/1.5 ui-monospace, monospace; white-space: pre-wrap; word-break: break-word; }
/* Embedded in-lesson "lab moment": a live mini-sim inside the active chunk. Reuses .minisim* above;
   only the outer block frame + the compact read-only circuit canvas need their own scoped rules. */
.lab-moment-block .lab-moment-prompt { margin: 0 0 12px; }
/* A chunk card holding a live lab moment must be allowed to shrink to its grid track: the circuit
   canvas (.lab-stage) is a fixed 980px, and without this the card's default min-width:auto lets that
   width force the whole page wider than the viewport. min-width:0 hands the overflow to
   .lab-moment-canvas-wrap, which already scrolls (overflow:auto) — so the circuit scrolls in its own
   box instead of pushing the layout off-screen. Scoped via :has so no other card layout changes. */
.card.panel:has(.lab-moment-block) { min-width: 0; }
.lab-moment-block, .lab-moment, .lab-moment .minisim { min-width: 0; }
.lab-moment { padding: 14px; border-radius: var(--radius-md); }
.lab-moment .minisim-controls { margin-bottom: 12px; }
.lab-moment-canvas-wrap {
  flex: 1; min-width: 220px; max-width: 100%; max-height: 280px; overflow: auto; border-radius: 8px; border: 1px solid var(--line);
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--canvas);
}
/* Schemdraw-rendered circuit schematic (SVG injected by initSchematics). Light strokes on canvas. */
.schematic-visual { display: block; margin: 0; }
.schematic-slot { display: flex; align-items: center; justify-content: center; min-height: 110px; padding: 22px 18px; border-radius: var(--radius-md); background: var(--canvas); border: 1px solid var(--line); overflow: auto; }
.schematic-slot svg { max-width: 100%; height: auto; }
.path-bar { display: block; height: 4px; border-radius: 2px; background: hsl(0 0% 100% / .08); overflow: hidden; margin-top: 4px; }
.path-bar > span { display: block; height: 100%; background: var(--status-progress); border-radius: inherit; }
.path-count { font-family: var(--font-mono); font-size: 11px; color: var(--muted); letter-spacing: .04em; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .step-sep { display: none; } .stepper { gap: 6px; } }

/* ---- Auth (/login) ---- */
/* Layout extracted from inline styles in login.js (same tokens/values, no visual change). */
.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: var(--space-5); }
/* align-items:center so the login card sits at its natural (compact) height, vertically centered
   against the taller hero column — rather than stretching to match its height. */
.auth-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 18px; max-width: 920px; width: 100%; align-items: center; }
.auth-hero { position: relative; overflow: hidden; background: var(--canvas); display: flex; flex-direction: column; justify-content: center; gap: 14px; }
/* Generated dark-blueprint ambiance (Higgsfield z_image, 9:16) behind the auth-hero schematic +
   content, faded from the top so the brand + step cards stay clean. */
.auth-hero::before { content: ''; position: absolute; inset: 0; z-index: 0; background: url(/login-ambiance.webp) center bottom / cover no-repeat; opacity: .55; -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 42%); mask-image: linear-gradient(180deg, transparent 0%, #000 42%); pointer-events: none; }
.auth-hero h1 { font-size: clamp(30px, 3.4vw, 46px); line-height: 1; margin: 6px 0 0; }
/* Inline text button (the auth-mode toggle): looks like a cyan link, not a chip. */
.link-button { font-weight: 600; color: var(--cyan); background: transparent; border: none; padding: 0; min-height: 0; display: inline; font-size: inherit; cursor: pointer; }
.auth-schem { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--text); opacity: .06; z-index: 0; pointer-events: none; }
.auth-hero > *:not(.auth-schem) { position: relative; z-index: 1; }
.auth-error { margin: 12px 0; padding: 10px 14px; border-radius: var(--radius-md); background: var(--red-soft); border: 1px solid hsl(8 73% 66% / .3); color: var(--red); font-size: 13px; }
.auth-google { width: 100%; }
.auth-divider { display: flex; align-items: center; gap: 12px; margin: 14px 0; color: var(--muted); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .1em; }
.auth-divider::before, .auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ---- Landing page (public /) ---- */
.landing { width: min(1080px, calc(100vw - 40px)); margin: 0 auto; padding: 20px 0 64px; }
.landing-nav { display: flex; justify-content: space-between; align-items: center; padding: 8px 0 24px; }
.landing-hero { position: relative; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); padding: clamp(28px, 6vw, 72px) clamp(20px, 4vw, 48px); margin-bottom: 20px; }
/* Generated dark-blueprint ambiance (Higgsfield z_image). Sits BEHIND the SVG line-art + text,
   kept subtle (low opacity) and faded from the left via a mask so the headline area stays clean. */
.landing-hero::before { content: ''; position: absolute; inset: 0; z-index: 0; background: url(/hero-ambiance.webp) center right / cover no-repeat; opacity: .2; -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 58%); mask-image: linear-gradient(90deg, transparent 0%, #000 58%); pointer-events: none; }
@media (prefers-reduced-motion: no-preference) { .landing-hero::before { transition: opacity var(--dur-slow) var(--ease-out); } }
.landing-schem { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; color: var(--text); opacity: .06; pointer-events: none; }
.landing-hero-inner { position: relative; z-index: 2; }
.landing-hero h1 { font-size: clamp(36px, 6.4vw, 76px); margin-top: 14px; }
.lp-sub { max-width: 70ch; margin-top: 20px; font-size: clamp(15px, 1.6vw, 18px); }
/* Local scrim: at ~1024px the tagline crosses the brightest schematic traces — a soft dark
   text-shadow keeps the copy legible without dimming the artwork (scoped to the hero only). */
.landing-hero h1, .landing-hero .lp-sub { text-shadow: 0 1px 2px hsl(220 14% 5% / .9), 0 0 16px hsl(220 14% 5% / .65); }
.landing-sec { margin-top: 36px; }
.lp-strip { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.lp-url { font-family: var(--font-mono); font-size: 12px; color: var(--text-dim); border: 1px solid var(--line); border-radius: var(--radius-md); padding: 8px 12px; }
.lp-arrow { color: var(--cyan); font-size: 20px; }
.lp-out { display: grid; gap: 8px; flex: 1; min-width: 260px; }
.lp-graph-wrap { color: var(--cyan); display: flex; justify-content: center; }
.lp-graph { width: 100%; height: auto; max-width: 640px; display: block; margin: 0 auto; }
.lp-node { fill: var(--surface-2); stroke: var(--line-strong); }
.lp-node.mastered { stroke: var(--amber); }
.lp-node.learning { stroke: var(--cyan); }
.lp-node.unseen { stroke: var(--line-strong); stroke-dasharray: 4 4; }
.lp-node-t { fill: var(--text); font-family: var(--font-display); font-size: 14px; font-weight: 600; }
.lp-node-s { fill: var(--muted); font-family: var(--font-mono); font-size: 10px; }
.landing-foot { margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--line); }
.lp-link { display: block; margin-top: 8px; color: var(--text-dim); font-size: 13px; }
.lp-link:hover { color: var(--cyan); }
.lp-stamp { display: block; margin-top: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); white-space: nowrap; } /* never wrap mid-date */
@media (max-width: 640px) { .landing-foot .cols-4 { grid-template-columns: repeat(2, 1fr); } }

/* TABLET TIER (769–1050px): hide sidebar, collapse 3-pane → main + ONE rail,
   keep 2-pane layouts as 2 columns, .cols-3/.cols-4 → 2 columns. */
@media (max-width: 1050px) {
  .shell { display: block; }
  .sidebar { display: none; }
  .content { width: 100%; padding: 14px 14px 92px; }
  .topbar { grid-template-columns: 1fr auto; padding: 10px; }
  .search { display: none; }
  .header { display: grid; align-items: start; }
  /* 3-pane → main content + one side rail (drop the left/secondary rail) */
  .lesson3, .graph-grid, .workspace-grid { grid-template-columns: minmax(0, 1fr) 320px; }
  /* dense card grids → 2 columns at tablet */
  .cols-3, .cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 2-pane layouts (.lesson-grid, .challenge-grid, .dashboard-grid, .path-grid,
     .concept-grid, .new-project-grid, .planning-grid) intentionally stay 2-column here. */
  .card, .header, .page > *, .grid > * { min-width: 0; }
  .mobile-nav { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; position: fixed; left: 12px; right: 12px; bottom: 12px; gap: 4px; padding: 6px; border-radius: var(--radius-md); z-index: 50; background: var(--surface); border: 1px solid var(--line-strong); }
  .mobile-nav a { flex: 0 0 auto; min-width: 60px; min-height: 44px; scroll-snap-align: start; display: grid; place-items: center; padding: 0 10px; border-radius: var(--radius-md); font-family: var(--font-mono); font-size: 11px; font-weight: 500; color: var(--text-dim); }
  /* Right-edge fade cue: several destinations sit off-screen (scrollWidth ~610 vs ~364
     viewport) with zero affordance. A sticky gradient flex item pins to the scrollport's
     right edge so the cut-off link reads as "more to scroll". Zero layout width
     (margin-left cancels flex-basis), inert to taps; scroll-snap is untouched. */
  .mobile-nav::after { content: ''; position: sticky; right: 0; flex: 0 0 28px; margin-left: -28px; align-self: stretch; pointer-events: none; background: linear-gradient(90deg, transparent, var(--surface) 85%); }
  /* Tap targets (mobile only — desktop look unchanged): graph filter chips (36px) and the
     lab palette select (34px) grow to >=40px; landing footer/header links and the auth-mode
     toggle (~21px) gain padding. .link-button is display:inline, so vertical padding expands
     the hit area without shifting line layout; negative h-margin cancels the h-padding. */
  .src-chip, .depth-chip, .tab { min-height: 40px; }
  .lab-select { min-height: 40px; }
  .lp-link { padding: 10px 0; }
  .landing-nav .brand { padding: 8px 0; }
  .link-button { padding: 12px 8px; margin: 0 -8px; }
}
/* SINGLE-COLUMN TIER (<=768px): collapse everything to one column. */
@media (max-width: 768px) {
  .cols-2, .cols-3, .cols-4, .workspace-grid, .lesson-grid, .lesson3, .challenge-grid, .graph-grid, .dashboard-grid, .path-grid, .concept-grid, .new-project-grid, .planning-grid { grid-template-columns: minmax(0, 1fr); }
  .grid { grid-template-columns: minmax(0, 1fr); }
  .template-map, .callout-grid, .term-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .top-actions .pill { display: none; }
  .top-chip { min-width: 0; }
  h1 { font-size: clamp(28px, 11vw, 44px); }
  .metric-value { font-size: 38px; }
}
/* TOUCH TARGETS (Bencium): grow tappable area to >=44px on coarse pointers
   while keeping glyphs visually small, via a transparent ::before expander. */
@media (pointer: coarse) {
  .cluster-toggle, .seg, .pill, .tab { position: relative; }
  .cluster-toggle::before, .seg::before, .pill::before, .tab::before {
    content: ""; position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    min-width: 44px; min-height: 44px; width: 100%; height: 100%;
  }
}
/* Graph timeline scrubber: explicit focus ring (the range input strips native border). */
.scrubber:focus-visible { outline: 2px solid var(--status-active); outline-offset: 2px; }
/* ---- Simulation Lab (Wokwi-class avr8js workbench) ----------------------------------------- */
.lab-root { margin-top: 18px; }
.lab-grid {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(0, 1.5fr);
  grid-template-rows: auto auto;
  gap: 14px;
}
.lab-diagram-pane { grid-row: span 2; }
/* min-width:0 — grid items default to min-width:auto, so the 980px intrinsic .lab-stage width
   would otherwise propagate through the 1fr track and overflow the page on small viewports.
   The canvas stays internally scrollable via .lab-canvas-wrap{overflow:auto}. */
.lab-pane { padding: 14px; border-radius: var(--radius-md); display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.lab-pane-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; row-gap: 8px; margin-bottom: 10px; flex-wrap: wrap; } /* controls drop to their own row cleanly at 390px */
.lab-pane-head .label { font: 600 12px/1 var(--mono, ui-monospace, monospace); letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.lab-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lab-controls .button { padding: 7px 12px; font-size: 13px; }
.lab-select {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--line-ui);
  border-radius: 8px; padding: 7px 10px; font-size: 13px;
}
.lab-code {
  flex: 1; min-height: 280px; width: 100%; resize: vertical;
  background: var(--canvas); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 12px;
  font: 13px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; tab-size: 2;
}
.lab-status {
  margin-top: 10px; padding: 8px 10px; border-radius: 8px; white-space: pre-wrap;
  font: 12px/1.5 ui-monospace, monospace; color: var(--text-dim);
  background: var(--surface-2); border: 1px solid var(--line); max-height: 160px; overflow: auto;
}
.lab-status[data-kind="error"] { color: var(--status-review-foreground, #f2b8b8); border-color: var(--status-review-border, #5a2b2b); background: var(--status-review-muted, rgba(120,40,40,.18)); }
.lab-status[data-kind="ok"] { color: var(--green); border-color: var(--green-soft); background: var(--green-soft); }
.lab-canvas-wrap {
  flex: 1; overflow: auto; max-width: 100%; border-radius: 8px; border: 1px solid var(--line);
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--canvas);
}
.lab-stage { user-select: none; }
/* A11y: the focusable <wokwi-arduino-uno> board (and other stage parts) is a custom element the
   global :where(...) focus rule doesn't reach — give it the same ring as the global rule (:142). */
.lab-stage [tabindex]:focus-visible, .lab-parts > *:focus-visible { outline: 2px solid var(--status-active); outline-offset: 2px; }
.lab-part { transition: filter .12s ease; }
.lab-part.selected { outline: 1.5px dashed var(--cyan); outline-offset: 3px; border-radius: 6px; }
.lab-pin:hover { fill: var(--cyan) !important; }
.lab-hint { font-size: 12px; color: var(--muted); margin-top: 8px; }
.lab-serial-pane { min-height: 200px; }
.lab-serial {
  flex: 1; min-height: 160px; overflow: auto; margin: 0;
  background: var(--canvas); color: var(--green); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px; font: 12.5px/1.5 ui-monospace, monospace; white-space: pre-wrap; word-break: break-word;
}
.lab-run-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line-strong); }
.lab-run-dot.live { background: var(--green); box-shadow: 0 0 0 3px var(--green-soft); animation: lab-pulse 1.1s ease-in-out infinite; }
@keyframes lab-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (max-width: 980px) {
  .lab-grid { grid-template-columns: 1fr; }
  .lab-diagram-pane { grid-row: auto; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* --- Notes overhaul: rendered Markdown, notebook, revision viewer, note card ------------------- */
.note-rendered { font-size: 14px; line-height: 1.6; color: var(--text); min-width: 0; overflow-wrap: anywhere; }
.note-rendered .note-h { margin: 14px 0 6px; font-weight: 700; letter-spacing: .01em; }
.note-rendered h4.note-h { font-size: 15px; }
.note-rendered h5.note-h, .note-rendered h6.note-h { font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .05em; }
.note-rendered .note-p { margin: 8px 0; }
.note-rendered .note-p:first-child { margin-top: 0; }
.note-rendered .note-list { margin: 8px 0 8px 18px; padding: 0; }
.note-rendered .note-list li { margin: 3px 0; }
.note-rendered .note-ic { font-family: var(--font-mono, ui-monospace, monospace); font-size: .9em; background: hsl(0 0% 100% / .06); border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px; }
.note-rendered .note-code { margin: 10px 0; padding: 12px 14px; background: var(--bg, #0b0c0e); border: 1px solid var(--line); border-radius: var(--radius-md); overflow-x: auto; max-width: 100%; }
.note-rendered .note-code code { font-family: var(--font-mono, ui-monospace, monospace); font-size: 12.5px; color: var(--text); white-space: pre; }
.note-rendered .note-quote { margin: 10px 0; padding: 6px 14px; border-left: 3px solid var(--status-active); color: var(--text-dim); }
.note-rendered a { color: var(--status-active); text-decoration: underline; }
.note-rendered strong { font-weight: 700; }
.note-rendered em { font-style: italic; }

.note-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 12px; }
.note-status { font-size: 12px; display: inline-flex; align-items: center; gap: 5px; }
.note-status.saved { color: var(--status-active); }
.note-status.unsaved { color: var(--text-dim); }
.note-md-hint { font-size: 11px; color: var(--text-dim); margin-top: 8px; }
.note-preview-box { margin-top: 12px; min-height: 80px; }

.revision-viewer { margin-top: 12px; }
.revision-toggle { display: inline-flex; align-items: center; gap: 7px; background: none; border: none; color: var(--text-dim); font-size: 12px; cursor: pointer; padding: 4px 0; font-family: inherit; }
.revision-toggle:hover { color: var(--text); }
.revision-caret { margin-left: 2px; }
.revision-list { margin-top: 8px; display: grid; gap: 8px; }
.revision-item { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 10px 12px; }
.revision-meta { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.revision-preview { font-size: 12px; color: var(--text-dim); margin: 6px 0 8px; }

.notebook-search-bar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; margin-bottom: 16px; }
.notebook-search-bar input { flex: 1; min-width: 0; background: none; border: none; color: var(--text); font-size: 14px; font-family: inherit; outline: none; }
.notebook-grid { gap: 16px; min-width: 0; }
/* Sectioned notebook: sticky chapter/sub-lesson navigator beside the notes column */
.notebook-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 18px; align-items: start; }
.notebook-index { position: sticky; top: 84px; padding: 14px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; min-width: 0; max-height: calc(100vh - 110px); overflow-y: auto; }
.notebook-index > .label { margin-bottom: 4px; }
.nb-chapter { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; min-width: 0; }
.nb-chapter-link { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: none; border: none; color: var(--text); font-family: inherit; font-size: 13px; font-weight: 600; padding: 6px 6px; border-radius: 6px; cursor: pointer; }
.nb-chapter-link:hover { background: hsl(0 0% 100% / .06); }
.nb-chapter-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb-chapter-num { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex-shrink: 0; border-radius: 5px; background: hsl(0 0% 100% / .07); border: 1px solid var(--line); font-size: 11px; font-family: var(--font-mono, ui-monospace, monospace); margin-right: 8px; }
.nb-chapter-link .nb-chapter-num { margin-right: 0; }
.nb-sublessons { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; margin: 0 0 6px 28px; min-width: 0; }
.nb-jump { text-align: left; background: none; border: none; color: var(--text-dim); font-family: inherit; font-size: 12px; padding: 4px 6px; border-radius: 5px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb-jump:hover { background: hsl(0 0% 100% / .05); color: var(--status-active); }
.notebook-lesson .card-head h2 { display: flex; align-items: center; }
@media (max-width: 1050px) {
  .notebook-layout { grid-template-columns: minmax(0, 1fr); }
  .notebook-index { position: static; max-height: none; }
}
.notebook-lesson .card-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 12px; }
.notebook-notes { display: grid; gap: 14px; min-width: 0; }
.notebook-lesson { min-width: 0; }
.notebook-note { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 14px; min-width: 0; }
.notebook-note-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 8px; }
.notebook-note-head h3 { font-size: 14px; margin: 0; }

.concept-note { margin-top: 10px; min-width: 0; }
.concept-note + .concept-note { border-top: 1px solid var(--line); padding-top: 10px; }
.review-row + .review-row { margin-top: 6px; }
.review-notes { margin-top: 6px; }
.review-notes summary { font-size: 12px; color: var(--status-active); cursor: pointer; }
.review-notes-body { margin-top: 8px; }

/* Selection toolbar — floating actions above highlighted lesson text */
.selection-toolbar { position: fixed; z-index: 60; display: none; align-items: center; gap: 2px;
  background: var(--surface, #121418); border: 1px solid var(--line); border-radius: 8px;
  padding: 4px; box-shadow: 0 8px 24px hsl(0 0% 0% / .45); }
.selection-toolbar.visible { display: flex; }
.selection-toolbar button { background: none; border: none; color: var(--text); font-family: inherit;
  font-size: 12.5px; padding: 6px 12px; border-radius: 6px; cursor: pointer; white-space: nowrap; }
.selection-toolbar button:hover { background: hsl(0 0% 100% / .08); color: var(--status-active); }
.selection-toolbar-sep { width: 1px; align-self: stretch; background: var(--line); margin: 4px 0; }
.selection-toolbar-caret { position: absolute; left: 50%; bottom: -5px; transform: translateX(-50%) rotate(45deg);
  width: 9px; height: 9px; background: var(--surface, #121418); border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line); }
.selection-toolbar.below .selection-toolbar-caret { bottom: auto; top: -5px; transform: translateX(-50%) rotate(225deg); }
