/* ==========================================================================
   TPEE.app — styles.css
   Session 1 (Build 183 · v1.0.0) — static site skeleton.
   Design tokens copied VERBATIM from TEAM_REPORT_Design_UX.md §3.2.
   No webfonts, no external requests, no glassmorphism, no glow.

   Session 9 (Jacques): page flipped from dark-only to LIGHT (warm white /
   beige body) with dark chrome retained: the sticky header, the footer and
   the two index app replicas (app-preview / pew-preview — they mirror the
   dark tpee.exe UI) keep the original dark palette via the scoped token
   override block right below :root. All light-theme text/background pairs
   verified >= 4.5:1 (WCAG AA) — see session notes.

   Session 10 (Jacques): inert "Functions" item added to the primary nav
   between Screenshots and Features (.nav-soon + .nav-tag pill) — content
   lands in the NEXT session, so it is an aria-disabled span (zero 404s,
   same pattern as the language switcher's "soon" items). Brand link fixed
   index.html -> / (same-document, no more 308 reload + scroll restore).

   Session 11 (Jacques): "Functions" is now a REAL nav link to the new
   #functions home section (the .nav-soon/.nav-tag rules are retired).
   That section hosts the User's Manual replica (.fn-demo + .manual-modal):
   a modal window mirroring src/manual.rs (4 document buttons, filterable
   TOC, content pane) that loads the COMPLETE manuals from
   assets/manuals/*.html (generated by tools/build_manuals.py). The modal
   joins the dark-chrome token group below. Also: prominent "Run from USB
   Stick" feature card, and the #pew-demo / #prompt-enhancing
   cross-reference pair (GO TO VISUAL DEMO button).

   Session 12 (Jacques): second Functions demo — the Learning Center replica
   (.fn-demo + .learn-modal, shell classes shared with the manual window):
   a modal mirroring src/learning.rs (Students + 80-lesson list, lesson pane
   with Knowledge Check quiz, in-memory grading) that loads the COMPLETE
   course from assets/learning/*.json (generated by tools/build_learning.py).
   .learn-modal joined the dark-chrome token group.

   Session 13 (Jacques): third Functions demo — the IDE Selection combobox
   replica (.fn-demo + INLINE .ide-preview frame, NOT a modal: the combobox
   lives in the app's toolbar row). Mirrors src/main.rs session2_ide_selector
   (light-blue "IDE:" label, 200px ComboBox, "🖥️ <name>" items, "IDE changed
   to: <name>" status line) with the COMPLETE 23-profile catalogue from
   assets/ide/ide-profiles.json (generated by tools/build_ide_profiles.py).
   .ide-preview joined the dark-chrome token group.

   Session 14 (Jacques): fourth Functions demo — the Model Selection
   combobox replica (.fn-demo + INLINE .model-preview frame, NOT a modal:
   the combobox lives in the app's toolbar row). Mirrors src/main.rs
   session2_model_selector (light-green "Model:" label, 350px ComboBox,
   "Provider — Name (Released …)" items grouped under yellow provider
   headers, the Build-091 type-to-filter box with auto-focus + X clear +
   no-match message, filter auto-clear on close, "Model changed to: <name>"
   status line) with the COMPLETE 150-model / 14-provider catalogue from
   assets/models/model-profiles.json (generated by
   tools/build_model_profiles.py). .model-preview joined the dark-chrome
   token group.

   Session 15 (Jacques): fifth Functions demo — the API Character Limits
   replica (.fn-demo with the Show/Hide API Limits toggle button +
   .apil-modal, shell classes shared with the manual window). Mirrors
   src/main.rs Build 183: the toggle (label flips "Show API Limits" /
   "Hide API Limits") and the panel it opens (heading row + "Last Updated"
   label, YELLOW provider headers, model cards newest-first per provider
   with usage bar, "0/N tokens" and "Input: $X.XXX / Output: $Y.YY per 1M
   tokens" pricing, 3px gold "★ name ★" frame on the selected model) with
   the COMPLETE 150-model / 14-provider data from
   assets/api-limits/api-limits.json (generated by
   tools/build_api_limits.py). .apil-modal joined the dark-chrome token
   group.

   Session 16 (Jacques): sixth Functions demo — the Model / Commands
   reference replica (.fn-demo with the DYNAMIC Show/Hide <Family> /
   Commands toggle button + .cmd-modal, shell classes shared with the
   manual window). Mirrors src/model_commands_reference.rs Build 183:
   button_label_for_model ("Show Kimi / Commands" when a Kimi model is
   selected) and render_panel (heading "<Family> / Commands (reference)",
   italic REF_DATE_LINE, "Selected:" banner, three default-open collapsing
   sections + the default-closed Claude-only section) with the COMPLETE
   14-family command sheets from assets/commands/model-commands.json
   (generated by tools/build_model_commands.py). The demo FOLLOWS the
   Session-14 Model combobox selection (tpee:model-selected event) and
   starts on Kimi K3 per Jacques's instruction. .cmd-modal joined the
   dark-chrome token group.

   Session 17 (Jacques): seventh Functions demo — the Optimization Tips
   replica (.fn-demo with the "💡 Show Tips" / "💡 Hide Tips" toggle
   button + .tips-modal, shell classes shared with the manual window).
   Mirrors src/main.rs Build 183 (the toggle at lines 11817-11830 and the
   right side panel at lines 12510-12720: heading "💡 Optimization Tips",
   separator, "🖥️ <IDE> + 🤖 <model>" context line in LIGHT_BLUE, tip
   groups with per-category colours) with the COMPLETE tips engine data
   from assets/tips/optimization-tips.json (generated by
   tools/build_optimization_tips.py from src/optimization_tips.rs). The
   demo FOLLOWS both comboboxes (tpee:ide-selected + tpee:model-selected
   events) and re-renders live while open. .tips-modal joined the
   dark-chrome token group.

   Session 18 (Jacques): eighth Functions demo — the Projects Prefixes
   replica (TWO parts, exactly like the app: an INLINE .pfx-preview frame
   mirroring the File Name / Project Prefix toolbar row, src/main.rs Build
   183 lines 11948-11989, with the Build-068 "📋 Projects Prefixes"
   STATIC-label toggle button; and the .pfx-modal window it opens — the
   app feature really IS an egui::Window, lines 19118-19294, so no
   structural override). Full CRUD mirror: add (empty input falls back to
   the current prefix, trimmed, duplicates rejected), conditional "➕ Add
   Current: 'X'" quick-add, click-to-select, 🗑 remove, verbatim status
   messages. In-memory only (the app persists to tpee_preferences.json —
   honest fn-under note). .pfx-modal + .pfx-preview joined the dark-chrome
   token group.

   Session 19 (Jacques): NEW home #editors section (nav "Editors" between
   "Screenshots" and "Functions" on all 12 pages, anchored just below the
   hero) with its first demo — the Persona editor replica (.fn-demo +
   INLINE .persona-preview frame, NOT a modal: the app feature is an
   inline Frame::group in the central panel, src/main.rs Build 183 lines
   12870-13176). Mirrors the title bar with the live quality icon/dot,
   the "🎭 Select Persona:" filter row + Build-127 dropdown (275 personas
   from assets/personas/personas.json, generated by
   tools/build_personas.py from the PERSONAS const), the copy button,
   the auto-growing TextEdit, the character counter, the "📋 Quality
   Guidance" collapsing header and the live Good / Needs Work / Poor
   indicator (analyze_persona_quality re-implemented in app.js section
   (r)). .persona-preview joined the dark-chrome token group.

   Session 20 (Jacques): second Editors demo, directly below the Persona
   editor — the Instructions editor replica (.fn-demo + INLINE
   .instr-preview frame, NOT a modal: the app feature is an inline
   Frame::group in the central panel, src/main.rs Build 183 lines
   13178-13345 — same structure as the Persona editor but WITHOUT the
   library / select row, so there is no JSON asset and no fetch).
   Mirrors the title bar with the live quality icon/dot (tooltips via
   get_tooltip("Instructions")), the "Enter your instructions below:"
   label + "📋 Copy Instructions to Clipboard" button (min 180x18), the
   auto-growing TextEdit (hint "Enter instructions here..."), the
   character counter, the "📋 Quality Guidance" collapsing header with
   the Instructions guidance lines verbatim (main.rs:13301), and the
   live Good / Needs Work / Poor indicator (analyze_instruction_quality,
   main.rs:4068-4114, re-implemented 1:1 in app.js section (s) —
   action-verb + no vague words + >=8 words → Good; action-verb +
   >=4 words → Needs Work; substring contains() semantics mirrored, not
   "fixed"). .instr-preview joined the dark-chrome token group.

   Session 22 (Jacques): Editors demos 8-12, directly below the Tone
   editor — the Data, Example(s), Graphics, MCP Servers and Agents editor
   replicas (.fn-demo + INLINE .*-preview frames, NOT modals: all five app
   features are inline Frame::group editors in the central panel,
   src/main.rs Build 183 lines 14972-15721 — the Editors section now shows
   all 12 prompt-section editors). GRILL-ADJUDICATED VARIANTS: Data uses
   the 26px title-bar variant like Format/Audience/Tone (16px STRONG
   title, "Quality:" + text readout, NO icon) with a FIXED-120px MONOSPACE
   TextEdit; Example(s)/MCP Servers/Agents use the 30px variant like
   Instructions/Context (20px title, live quality icon + "●" with
   tooltips) with DYNAMIC-rows TextEdits; Graphics is drawn by the app's
   shared draw_editor_block (main.rs:7488-7700) — 30px variant but NO copy
   button and NO hint text (mirrored 1:1). Quality engines re-implemented
   1:1 in app.js sections (y)-(ac): analyze_general_quality for
   Data/Graphics/MCP/Agents, analyze_example_quality for Example(s)
   (substring contains() semantics mirrored, not "fixed"). All five
   previews joined the dark-chrome token group.

   Session 23 (Jacques): hero "📋 Copy to Clipboard" + "👁 Preview" demo
   (.cpb-preview inline frame directly below the PEW strip — exactly where
   the row sits in the app's top panel, main.rs:12183-12215) + the
   "Content Preview" window replica (.cpb-modal, Session-11 .manual-* shell
   reused, 800x600 / min-400 like the app's egui::Window,
   main.rs:15853-15937) with a FIXED complete 12-section demo prompt
   (GreenHouse-One). .cpb-preview + .cpb-modal joined the dark-chrome
   token group. Also this session: the hero's "Twelve sections..." h1/sub
   moved to the top of #editors (classes unchanged — no CSS impact), and
   the pricing grid gained the 6th card (Family $79) — the existing
   responsive pricing-grid rules cover it, no new grid CSS.

   Session 24 (Jacques): VERTICAL message carousel at the TOP of the home
   page (.vmsg) — one very-high-contrast message box (#000 background,
   3px #ffff00 border, #fff bold text: 21:1 / 19.56:1, WCAG AAA) with an
   UP arrow button on its LEFT (previous) and a DOWN arrow button on its
   RIGHT (next). js/messages.js rotates every 12 s (message slides UP,
   next enters from below), the arrows step manually and re-arm the
   timer; rotation pauses on hover/focus/hidden-tab and is disabled under
   prefers-reduced-motion. Hardcoded #000/#ffff00 values (NOT tokens) —
   the box is deliberately maximum-contrast on the light page. In its
   no-JS state the box is a normal stacked list of all messages; JS adds
   .vmsg--js to turn it into the fixed-height viewport + sliding track.

   Session 25 (Jacques): the home-page trust chrome REMOVED at his
   request — the hero .trust-line ("100% offline · No telemetry ·
   Windows 10/11 · Build 183") and the home "Trust highlights" strip
   (Offline-by-design / SHA-256 published / Secure checkout by Stripe /
   One-time purchase). The now-unused .trust-line rule was deleted;
   .trust-strip/.chip STAY (security.html still uses its own strip).

   Session 26 (Jacques): the hero -> #editors dead gap (~284px: CTA row
   margin 1.75rem + hero bottom pad + #editors top pad, both
   var(--section-pad)) reduced to exactly the cap height of the "E" in
   the "Editors" title: .hero bottom padding and .hero-ctas margin
   zeroed, #editors padding-top = 0.7 x the title's clamp() font-size
   (~25px desktop / ~20px mobile, tracks the title at every viewport).
   .hero/.hero-ctas/#editors are index-only — the other 11 pages keep
   the standard section rhythm.

   Session 30 (Jacques): full-site aesthetic review ("make it look like a
   million-dollar website") — specialist grill (aesthetics, colour
   psychology, typography, Apple/Microsoft benchmark, a11y, conversion UX),
   adjudicated CSS-only improvements:
   - NEW --shadow-soft (low-alpha two-layer) for LIGHT surfaces: carousel
     slides, gallery/noscript images, the Learning callout. --shadow-1
     (0.35 alpha, dark-theme weight) stays on the dark-chrome replicas.
   - NEW --shadow-accent elevation on the ONE recommended card per set:
     .plan-card--popular + .feature-card--prominent.
   - .pricing-grid desktop 5 -> 3 columns: with 6 plans the 5-col grid
     orphaned Business on its own row; 3x2 is balanced.
   - .plan-card hover lift (translateY -2px + soft shadow).
   - .section-title letter-spacing -0.01em (matches .hero-title).
   Palette UNCHANGED — the warm-paper + deep-cyan + navy-chrome scheme
   reviewed as on-brand (trust, warmth, longevity); all text/background
   pairs re-verified >= 4.5:1.
   ========================================================================== */

/* ----- Design tokens (TEAM_REPORT_Design_UX.md §3.2, names final) -------- */
:root {
  /* Color — LIGHT page (Session 9) */
  --bg-0: #faf8f1;                 /* page — warm white */
  --bg-1: #f1ecdf;                 /* section alt — beige */
  --surface: #ffffff;              /* cards */
  --surface-2: #efe9db;            /* raised/hover */
  --line: rgba(25, 38, 56, 0.16);  /* hairlines */
  --text-1: #182230;               /* 15.1:1 on bg-0 */
  --text-2: #45536b;               /* muted (6.4:1 worst-case, verified) */
  --text-3: #57677f;               /* captions (4.7:1 worst-case, verified) */
  --accent: #0c6a84;               /* deep cyan, links/actions (>=5.1:1) */
  --accent-ink: #ffffff;           /* text on accent (6.2:1) */
  --green: #15803d;                /* success/trust dots (5.0:1) */
  --amber: #8a5a00;                /* warnings, sparing (>=5.6:1) */
  --red: #b91c1c;                  /* errors only (6.5:1) */
  --gradient-hero: linear-gradient(180deg, #f0ead9 0%, #faf8f1 70%);

  /* Type */
  --font-ui: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
    "Helvetica Neue", Arial, sans-serif;
  --font-display: "Segoe UI Variable Display", var(--font-ui);
  --font-mono: "Cascadia Code", ui-monospace, "SF Mono", Consolas, monospace;

  /* Radius */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-pill: 999px;

  /* Elevation + motion */
  --shadow-1: 0 8px 30px rgba(0, 0, 0, 0.35);
  /* Session 30: light-surface elevation. --shadow-1 was authored for the
     DARK theme (Session 1) — 35%-alpha black reads heavy and dated on the
     warm-white page (Apple/Microsoft/Stripe/Linear all use low-alpha,
     diffuse shadows on light). Dark-chrome regions (app replicas, modals,
     dropdowns, the fullscreen viewer) KEEP --shadow-1; light-page surfaces
     use this soft two-layer shadow instead. */
  --shadow-soft: 0 1px 2px rgba(16, 24, 40, 0.05),
    0 8px 24px rgba(16, 24, 40, 0.08);
  /* Session 30: soft accent-tinted elevation for the ONE recommended card
     in a set (Most-popular plan, prominent feature card). */
  --shadow-accent: 0 8px 24px rgba(12, 106, 132, 0.18);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* Layout */
  --header-h: 64px;
  --section-pad: clamp(56px, 8vw, 88px);
}

/* ----- Dark chrome regions (Session 9) -------------------------------------
   The sticky header, the footer, and the two index app replicas keep the
   original Session-1 dark palette (Jacques: "The footer and the title bar
   can stay black"; the replicas mirror the dark tpee.exe UI). Custom
   properties inherit, so overriding them on the container re-themes every
   descendant rule that uses var(--…) — no per-component rewrites. */
.site-header,
.site-footer,
.app-preview,
.pew-preview,
.manual-modal,
.learn-modal,
.classroom-modal,
.apil-modal,
.cmd-modal,
.tips-modal,
.pfx-modal,
.ide-preview,
.model-preview,
.pfx-preview,
.persona-preview,
.instr-preview,
.context-preview,
.techspec-preview,
.format-preview,
.audience-preview,
.tone-preview,
.data-preview,
.examples-preview,
.graphics-preview,
.mcp-preview,
.agents-preview,
.tsp-modal,
.cpb-preview,
.cpb-modal {
  --bg-0: #060d18;
  --bg-1: #0a1626;
  --surface: #0e1e33;
  --surface-2: #12263f;
  --line: rgba(148, 184, 220, 0.14);
  --text-1: #e8f0f8;
  --text-2: #a7bcd2;
  --text-3: #7d93ab;
  --accent: #3fd4e0;
  --accent-ink: #04222a;
  --green: #3ddc97;
  --amber: #f2b84b;
  color: var(--text-1);
  color-scheme: dark;
}

/* ----- Base -------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg-0);
  color: var(--text-1);
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.6;
  text-wrap: pretty;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.15;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

p { margin: 0 0 1em; }
ul { margin: 0; }

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

/* WCAG 1.4.1 (Use of Color): links inside running prose must not rely on
   color alone — underline them (Session 5 Lighthouse a11y finding). Buttons,
   nav, and card chrome keep their non-underlined look. */
main p a:not(.btn),
main li a:not(.btn) {
  text-decoration: underline;
  text-underline-offset: 2px;
}

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

/* WCAG 2.4.7 — visible focus everywhere */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.mono { font-family: var(--font-mono); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
  border-radius: var(--r-sm);
  transition: top 160ms var(--ease);
}
.skip-link:focus { top: 8px; text-decoration: none; }

/* ----- Layout containers ------------------------------------------------- */
.container {
  width: min(1024px, calc(100% - 48px));
  margin-inline: auto;
}
.container-wide {
  width: min(1280px, calc(100% - 48px));
  margin-inline: auto;
}

.section { padding-block: var(--section-pad); }
.section--alt { background: var(--bg-1); }
section[id] { scroll-margin-top: calc(var(--header-h) + 16px); } /* WCAG 2.4.11 */

/* Session 30: display tracking matches .hero-title (-0.01em) — section
   titles read as the same display voice (Apple/Microsoft large-type cue). */
.section-title { 
  font-size: clamp(1.875rem, 3.25vw, 2.5rem); 
  letter-spacing: -0.02em; 
}
.section-intro {
  color: var(--text-2);
  font-size: 1.125rem;
  max-width: 62ch;
  margin-bottom: 1.5rem;
}

/* ----- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 650;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 160ms var(--ease),
    border-color 160ms var(--ease), color 160ms var(--ease);
}
.btn:hover { text-decoration: none; }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
  box-shadow: 0 2px 8px rgba(12, 106, 132, 0.2);
}
.btn-primary:hover { 
  background: #0a5f6c; 
  box-shadow: 0 4px 12px rgba(12, 106, 132, 0.3);
  transform: translateY(-1px);
}

.btn-ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--text-1);
}
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }

/* ----- Sticky header ------------------------------------------------------ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  background: var(--bg-0);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  height: 100%;
  display: flex;
  align-items: center;
  gap: 24px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-1);
  margin-right: auto;
}
.brand:hover { text-decoration: none; }
.brand-icon {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 8px;
  border: 1px solid var(--line);
}
.brand-mark {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.375rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.brand-sub {
  font-size: 0.875rem;
  color: var(--text-3);
  white-space: nowrap;
}
/* Jacques: Toptronic is a registered trademark — keep the ® superscripted
   and visually quiet wherever the brand line appears. */
.brand-sub sup {
  font-size: 0.62em;
  line-height: 0;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: 0.938rem;
  transition: color 160ms var(--ease), background-color 160ms var(--ease);
}
.site-nav a:hover {
  color: var(--text-1);
  background: var(--surface);
  text-decoration: none;
}
.site-nav .nav-cta {
  margin-left: 8px;
  min-height: 44px;
  color: var(--accent-ink);
  background: var(--accent);
}
.site-nav .nav-cta:hover { background: #6fe0e9; }

/* Session 10/11: the inert "Functions" placeholder became a real nav link
   (/#functions) in Session 11 — the .nav-soon/.nav-tag rules were removed. */

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 10px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.nav-toggle-bar {
  display: block;
  height: 2px;
  margin: 5px 0;
  background: var(--text-1);
  border-radius: 1px;
}

/* ----- Hero (the ONE gradient on the site) -------------------------------- */
.hero {
  background: var(--gradient-hero);
  /* Session 8 (Jacques): the space above the "The app, right in your browser"
     eyebrow was a full 72-140px — reduced to 1.25rem, i.e. the height of one
     line of that eyebrow text itself. */
  /* Session 26 (Jacques): bottom padding ZEROED — after the Session-25
     removal of the trust-line + trust strip, the hero -> #editors gap was
     1.75rem (CTA margin) + 2 x var(--section-pad) ≈ 284px of dead space.
     He wants the gap to be exactly the cap height of the "E" in the
     "Editors" title, so the whole gap now lives on #editors padding-top
     below. .hero/.hero-ctas/#editors exist ONLY on index.html (grep-
     verified), so the section rhythm on the other 11 pages is untouched. */
  padding-block: 1.25rem 0;
}
.hero-title {
  font-size: clamp(2.25rem, 5.5vw, 3.25rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  max-width: 22ch;
  margin-bottom: 0.4em;
}
.hero-sub {
  font-size: clamp(1.0625rem, 1.6vw, 1.375rem);
  color: var(--text-2);
  max-width: 56ch;
  margin-bottom: 2rem;
}
.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 0; /* Session 26: was 1.75rem — see .hero comment above */
}
/* Session 26 (Jacques): the gap below the "Get TPEE"/"See every screen"
   buttons and above the "Editors" title = the cap height of the letter E
   in that title. Cap height ≈ 0.7 x font-size; the title font-size is
   clamp(1.75rem, 3vw, 2.25rem), so the gap tracks it at every viewport
   (≈25px desktop, ≈20px mobile). #editors keeps its bottom padding and
   its section[id] scroll-margin-top (anchor landing unchanged). */
#editors { padding-top: calc(clamp(1.75rem, 3vw, 2.25rem) * 0.7); }
/* Session 25: .trust-line rule REMOVED (its only user, the home hero
   trust-line, was removed at Jacques's request). .trust-strip/.chip
   below STAY — security.html still uses them. */

/* ----- Trust strip -------------------------------------------------------- */
.trust-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding-block: 20px;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 4px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 0.875rem;
  color: var(--text-2);
  white-space: nowrap;
}
.chip::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green);
  flex: none;
}

/* ----- Screenshot carousel (Session 2 — adapted PlazdiezCarousel) --------- */
/* Bare, styled slides: 16px radius, hairline border, soft shadow — no
   phone-frame mockups (design report §2.1). Track geometry: slide k sits at
   k * (width + 24px) on a static rail; carousel.js owns the translate. */
.carousel { margin-bottom: 1.5rem; }

/* Tab bar (role=tablist) */
.carousel-tabbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-bottom: 2rem;
}
.carousel-tab {
  font: inherit;
  font-size: 0.875rem;
  padding: 10px 18px;
  min-height: 44px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.carousel-tab:hover { background: var(--surface-2); color: var(--text-1); }
.carousel-tab[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
}

/* Stage: clipped viewport; slides are absolutely positioned by JS */
.carousel-stage {
  position: relative;
  overflow: hidden;
  padding-block: 8px;
}
.carousel-track {
  position: relative;
  transition: transform 350ms var(--ease);
  will-change: transform;
}
.carousel-track.no-anim { transition: none; }
.carousel-slide {
  position: absolute;
  top: 0;
  width: 30%;
  aspect-ratio: 9 / 19.5;
}
.carousel-slide picture,
.carousel-slide img {
  display: block;
  width: 100%;
  height: 100%;
}
.carousel-slide img {
  object-fit: cover;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-soft); /* Session 30: was --shadow-1 (dark-theme weight) */
  background: var(--surface);
}
.carousel-slide:not(.active) img {
  opacity: 0.5;
  transition: opacity 350ms var(--ease);
}
.carousel-slide.active img { opacity: 1; }
@media (max-width: 768px) {
  .carousel-slide { width: 76%; }
}

/* Arrows */
.carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: rgba(6, 13, 24, 0.8); /* dark chrome over the slide image — theme-independent */
  color: #3fd4e0;
  font-size: 1.25rem;
  cursor: pointer;
}
.carousel-arrow:hover { background: #12263f; }
.carousel-arrow-left { left: 8px; }
.carousel-arrow-right { right: 8px; }

/* Caption chip */
.carousel-caption {
  text-align: center;
  color: var(--text-2);
  min-height: 1.6em;
  margin-top: 1rem;
}

/* Toolbar: counter + Play/Pause + fullscreen */
.carousel-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 0.75rem;
}
.carousel-counter {
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  min-width: 4.5ch;
  text-align: center;
}
.carousel-pause-btn,
.carousel-fs-btn {
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-1);
  font-size: 1rem;
  cursor: pointer;
}
.carousel-pause-btn:hover,
.carousel-fs-btn:hover { background: var(--surface-2); }
.carousel-pause-btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Progress bar (8s autoplay countdown) */
.carousel-progress {
  height: 3px;
  margin-top: 1rem;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.carousel-progress-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
}

/* Filmstrip (thumb targets exceed 44px — WCAG 2.5.8) */
.carousel-filmstrip {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding: 16px 4px 8px;
}
.carousel-thumb {
  flex: 0 0 auto;
  width: 64px;
  min-height: 44px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface);
  cursor: pointer;
}
.carousel-thumb img { display: block; width: 100%; height: auto; }
.carousel-thumb:hover { border-color: var(--text-3); }
.carousel-thumb.active,
.carousel-thumb[aria-current="true"] {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

/* Lightbox / fullscreen overlay */
.fullscreen-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(4, 8, 14, 0.94);
}
.fullscreen-overlay.active { display: flex; }
.fullscreen-media img {
  max-height: 92vh;
  max-width: 92vw;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-1);
}
.fullscreen-hint {
  position: absolute;
  bottom: 24px;
  left: 0;
  right: 0;
  text-align: center;
  color: #a7bcd2; /* sits on the dark overlay regardless of page theme (Session 9) */
  font-size: 0.875rem;
}
.fullscreen-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: rgba(6, 13, 24, 0.8); /* dark chrome over the overlay — theme-independent */
  color: #3fd4e0;
  font-size: 1.5rem;
  cursor: pointer;
}
.fullscreen-arrow:hover { background: var(--surface-2); }
.fullscreen-arrow-left { left: 16px; }
.fullscreen-arrow-right { right: 16px; }

@media (prefers-reduced-motion: reduce) {
  .carousel-track,
  .carousel-slide:not(.active) img { transition: none; }
}

/* <noscript> Best-of grid + /gallery page (the true no-JS experience) */
.noscript-grid,
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 24px;
  margin-top: 1.5rem;
}
.noscript-item,
.gallery-item { margin: 0; }
.noscript-item img,
.gallery-item img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-soft); /* Session 30: was --shadow-1 */
  background: var(--surface);
}
.noscript-item figcaption,
.gallery-item figcaption {
  color: var(--text-2);
  font-size: 0.875rem;
  margin-top: 8px;
}
/* Session 55: gallery tiles open fullscreen on double-click (see app.js (am)).
   The cursor + focus ring advertise the affordance; the no-JS experience is
   untouched. */
.gallery-item--zoomable { cursor: zoom-in; touch-action: manipulation; }
.gallery-item--zoomable img {
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.gallery-item--zoomable:hover img,
.gallery-item--zoomable:focus-visible img {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}
.gallery-item--zoomable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-lg);
}
.gallery-page { padding-block: var(--section-pad); }
.gallery-tab { margin-bottom: 1.5rem; }
.gallery-tab-title {
  font-size: 1.375rem;
  margin-bottom: 0.5rem;
  scroll-margin-top: calc(var(--header-h) + 16px);
}

.carousel-note {
  color: var(--text-3);
  font-size: 0.875rem;
  text-align: center;
  margin: 0;
}

/* ----- Features 3×3 ------------------------------------------------------- */
.features-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.feature-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 24px;
  transition: background-color 160ms var(--ease),
    border-color 160ms var(--ease);
}
.feature-card:hover {
  background: var(--surface-2);
  border-color: rgba(25, 38, 56, 0.30);
}
.feature-card h3 { font-size: 1.125rem; margin-bottom: 0.4em; }
.feature-card p {
  color: var(--text-2);
  font-size: 0.938rem;
  margin: 0;
}

/* ----- Audiences ---------------------------------------------------------- */
.audience-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
}
.audience-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 20px;
}
.audience-card h3 { font-size: 1rem; margin-bottom: 0.3em; }
.audience-card p {
  color: var(--text-2);
  font-size: 0.875rem;
  margin: 0;
}
.audience-card .chip { margin-top: 12px; }

/* ----- Learning Center callout -------------------------------------------- */
.learning-callout {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(28px, 5vw, 48px);
  box-shadow: var(--shadow-soft); /* Session 30: was --shadow-1 (heavy on light) */
}
.learning-callout h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); }
.learning-callout p { color: var(--text-2); max-width: 62ch; }
.learning-callout .mono {
  color: var(--accent);
  font-size: 0.938rem;
}

/* ----- Pricing ------------------------------------------------------------ */
.pricing-grid {
  display: grid;
  /* Session 61 (Jacques): FOUR plans (Student & Job Seeker, Starter,
     Professional, Gift) must sit 2 x 2 on desktop — the previous 3-col grid
     left the 4th card orphaned alone on row two (verified live). 2 columns
     is balanced at every width: 2x2 desktop, 2x1 tablet, 1-col phone. */
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  align-items: stretch;
  margin-bottom: 2rem;
}

/* Session 61 (Jacques): the "Estimated" local-currency line under each USD
   price. Filled by app.js (ag) from the visitor's country (Cloudflare
   /cdn-cgi/trace, same-origin) with a locale fallback. Hidden until filled
   so an empty line never renders (no CLS, honest no-JS fallback = nothing). */
.plan-estimate {
  margin: -6px 0 10px;
  font-size: 0.9rem;
  color: var(--text-2);
  display: none;
}
.plan-estimate .est-label { font-weight: 600; }
.plan-estimate.is-visible { display: block; }
.plan-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 24px 20px;
  /* Session 30: subtle hover lift (2px) + soft shadow — user-initiated, and
     the global reduced-motion block already makes the transition instant. */
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease),
    border-color 160ms var(--ease);
}
.plan-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-soft); }
/* Session 30: the recommended plan gets soft accent-tinted elevation on top
   of the accent border + badge — the eye lands on Professional first. */
.plan-card--popular { border-color: var(--accent); box-shadow: var(--shadow-accent); }
.plan-badge {
  position: absolute;
  top: -12px;
  left: 20px;
  padding: 2px 12px;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: var(--r-pill);
  font-size: 0.75rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  /* Session 46: badges carry the podium stars — inline-flex so the
     decorative ★ glyphs sit on one line with the rank text. */
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.plan-badge-stars { letter-spacing: 0.05em; }
/* Session 46 (Jacques): race-podium tiers — Professional GOLD (winner),
   Business SILVER (2nd), The Gift of the Future BRONZE (3rd). Badge ink is
   --text-1: gold 7.62:1 AAA, silver 7.78:1 AAA, bronze 5.10:1 AA (agent-
   verified contrast on the #faf8f1 surface). Placed AFTER .plan-card--popular
   so --gold overrides the teal chrome at equal specificity. Equal card
   heights keep the 3x2 grid and the badge overlap math intact. */
.plan-card--gold   { border-color: #C9A227; box-shadow: 0 8px 24px rgba(201, 162, 39, 0.20); }
.plan-card--gold .plan-badge   { background: #D4AF37; color: var(--text-1); }
.plan-card--gold:hover   { box-shadow: 0 8px 24px rgba(201, 162, 39, 0.26); }
.plan-card--silver { border-color: #A39E96; box-shadow: 0 8px 24px rgba(120, 116, 110, 0.16); }
.plan-card--silver .plan-badge { background: #B9B4AC; color: var(--text-1); }
.plan-card--silver:hover { box-shadow: 0 8px 24px rgba(120, 116, 110, 0.22); }
.plan-card--bronze { border-color: #CD7F32; box-shadow: 0 8px 24px rgba(205, 127, 50, 0.18); }
.plan-card--bronze .plan-badge { background: #CD7F32; color: var(--text-1); }
.plan-card--bronze:hover { box-shadow: 0 8px 24px rgba(205, 127, 50, 0.24); }
.plan-name { font-size: 1.125rem; margin-bottom: 0.15em; }
.plan-price {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 0.75em;
}
.plan-price-term {
  font-family: var(--font-ui);
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--text-3);
}
.plan-features {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  font-size: 0.875rem;
  color: var(--text-2);
}
.plan-features li {
  padding: 8px 0;
  border-top: 1px solid var(--line);
}
.plan-features li:first-child { border-top: 0; }
.plan-cta { margin-top: auto; width: 100%; }
.plan-cta-link { margin-top: auto; width: 100%; }
.plan-status {
  min-height: 1.4em; /* reserved — no CLS when app.js writes the status */
  margin: 10px 0 0;
  font-size: 0.813rem;
  color: var(--amber);
}
.plan-note {
  color: var(--text-2);
  font-size: 0.938rem;
  max-width: 70ch;
  margin-inline: auto;
  text-align: center;
}
.pricing-meta {
  color: var(--text-3);
  font-size: 0.875rem;
  text-align: center;
  margin-top: 1.25rem;
}

/* ----- FAQ ----------------------------------------------------------------- */
.faq-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 24px;
  align-items: start;
}
.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.faq-item summary {
  cursor: pointer;
  padding: 16px 20px;
  font-weight: 600;
  font-size: 0.969rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  border-radius: var(--r-md);
  min-height: 44px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  font-family: var(--font-mono);
  color: var(--accent);
  flex: none;
}
.faq-item[open] summary::after { content: "–"; }
.faq-item p {
  padding: 0 20px 16px;
  margin: 0;
  color: var(--text-2);
  font-size: 0.938rem;
}

/* ----- Security summary ---------------------------------------------------- */
.security-summary {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(28px, 5vw, 48px);
}
.security-summary .trust-strip { padding-block: 0 8px; }
.security-summary p { color: var(--text-2); max-width: 68ch; }

/* ----- Final CTA (hero gradient reversed) ---------------------------------- */
.final-cta {
  background: linear-gradient(0deg, #f0ead9 0%, #faf8f1 70%);
  text-align: center;
}
.final-cta .section-title { margin-bottom: 1.5rem; }

/* ----- Footer --------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 48px 0 32px;
  background: var(--bg-0);
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}
.footer-heading {
  font-family: var(--font-ui);
  font-size: 0.813rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-3);
  margin-bottom: 0.75em;
}
.footer-col a {
  display: block;
  padding: 4px 0;
  color: var(--text-2);
  font-size: 0.938rem;
  min-height: 32px;
}
.footer-col a:hover { color: var(--text-1); }
/* External links (Founder, About Toptronic) open in a new tab — say so */
.footer-col a[target="_blank"]::after {
  content: "↗";
  margin-left: 4px;
  font-size: 0.75em;
  color: var(--text-3);
}
.footer-note {
  color: var(--text-3);
  font-size: 0.875rem;
  margin: 8px 0 0;
}
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 32px;
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  color: var(--text-3);
  font-size: 0.875rem;
}
.footer-bottom p { margin: 0; }
.footer-bottom a { color: var(--text-2); }
.footer-bottom a:hover { color: var(--accent); }

/* ----- Stub pages (Sessions 2–4 fill these in) ------------------------------ */
.stub-page { padding-block: var(--section-pad); }
.stub-notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 24px;
  color: var(--text-2);
  max-width: 68ch;
}

/* ----- Responsive ------------------------------------------------------------ */
@media (max-width: 1100px) {
  .pricing-grid { grid-template-columns: repeat(2, 1fr); }
  .audience-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 900px) {
  .features-grid { grid-template-columns: repeat(2, 1fr); }
  .pricing-grid { grid-template-columns: repeat(2, 1fr); }
  .audience-grid { grid-template-columns: repeat(2, 1fr); }
  .faq-grid { grid-template-columns: 1fr; }

  .brand-sub { display: none; }
  .nav-toggle { display: block; }
  .site-nav {
    display: none;
    position: absolute;
    top: var(--header-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 12px 24px 20px;
    background: var(--bg-1);
    border-bottom: 1px solid var(--line);
  }
  .site-nav.open { display: flex; }
  .site-nav a { padding: 10px 12px; }
  .site-nav .nav-cta { margin: 8px 0 0; justify-content: center; }
}

@media (max-width: 640px) {
  .features-grid,
  .pricing-grid,
  .audience-grid,
  .footer-grid {
    grid-template-columns: 1fr;
  }
  .hero-ctas .btn { width: 100%; }
}

/* ----- Reduced motion (WCAG 2.3.3) — no non-essential animation ------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ----- Session 3: commerce pages (success.html / download.html) -------------- */
.page-narrow { max-width: 860px; padding-bottom: 40px; }

.order-line {
  color: var(--text-2);
  margin: 0 0 20px;
}

.section-sub {
  font-family: var(--font-display);
  font-size: 1.25rem;
  color: var(--text-1);
  margin: 24px 0 12px;
}

.notice-amber {
  background: color-mix(in srgb, var(--amber) 12%, var(--surface));
  border: 1px solid var(--amber);
  border-radius: var(--r-md);
  padding: 16px 20px;
  color: var(--text-1);
  margin: 0 0 24px;
}
.notice-amber strong { color: var(--amber); }

.notice-plain {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 16px 20px;
  color: var(--text-2);
  margin: 0 0 24px;
}

.status-line {
  color: var(--text-3);
  font-size: 0.9375rem;
  min-height: 1.4em;
}

.dl-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin: 8px 0 8px;
}
.dl-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 20px;
}
.dl-title {
  font-size: 1rem;
  color: var(--text-2);
  margin: 0 0 12px;
}
.dl-btn { width: 100%; justify-content: center; }
.dl-meta { color: var(--text-3); font-size: 0.8125rem; margin: 10px 0 0; }

.hash-block {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 12px 16px;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  color: var(--text-1);
}
.hash-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 10px 16px;
  margin: 8px 0;
}
.hash-label {
  color: var(--accent);
  font-size: 0.8125rem;
  flex: none;
}
.hash-value {
  font-size: 0.75rem;
  color: var(--text-2);
  word-break: break-all;
  flex: 1;
}
.copy-btn { flex: none; min-height: 32px; padding: 4px 14px; }

.steps { color: var(--text-2); padding-left: 22px; }
.steps li { margin: 10px 0; }

.next-step {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 16px 20px;
  color: var(--text-1);
  margin: 28px 0 0;
}

.support-line {
  color: var(--text-3);
  margin-top: 40px;
  border-top: 1px solid var(--line);
  padding-top: 20px;
}

.form-inline {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin: 12px 0;
}
.field {
  flex: 1;
  min-width: 240px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--text-1);
  font: inherit;
  padding: 12px 16px;
  min-height: 44px;
}
.field:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

@media (max-width: 700px) {
  .dl-grid { grid-template-columns: 1fr; }
}

/* === Session 4: application form, prominent feature, Turnstile ========== */
.feature-card--prominent { border-color: var(--accent); box-shadow: var(--shadow-accent); } /* Session 30: soft accent elevation, matches .plan-card--popular */
.feature-card--prominent .chip { display: inline-block; margin-top: 12px; }

.form-stack { max-width: 620px; }
.form-stack .field { width: 100%; }
.field-label { display: block; color: var(--text-2); font-weight: 600; margin: 18px 0 8px; }
.form-hint { color: var(--text-3); font-size: 0.8125rem; margin: 6px 0 0; }
.field--area { min-height: 140px; resize: vertical; }
.choice-fieldset { border: 0; padding: 0; margin: 18px 0 0; }
.choice-fieldset .field-label { margin-top: 0; }
.choice-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.choice {
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 12px 14px;
  cursor: pointer;
}
.choice:has(input:checked) { border-color: var(--accent); }
.choice:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
.choice input { accent-color: var(--accent); }
.choice-title { display: block; color: var(--text-1); font-weight: 600; margin-top: 6px; }
.choice-sub { display: block; color: var(--text-3); font-size: 0.8125rem; margin-top: 2px; }
.turnstile-box { margin: 18px 0; min-height: 65px; } /* reserves widget height (CLS) */

@media (max-width: 700px) {
  .choice-grid { grid-template-columns: 1fr; }
}

/* === Session 6: language switcher ==========================================
   Adapted from jacquesbotte.com (Toptronic-owned, proven pattern): a
   <details>/<summary> globe button with a drop-down language list. Only
   English is live; the other 24 languages render as visible-but-disabled
   "soon" entries so the UI is final while translations are pending.
   Behaviour (aria-expanded sync, Esc, outside-click close): app.js (e). */
.lang-switcher {
  position: relative;
  margin-left: 8px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  font-size: 0.875rem;
}
.lang-switcher summary {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  cursor: pointer;
  list-style: none; /* hide the default disclosure triangle */
  transition: color 160ms var(--ease), background-color 160ms var(--ease);
}
.lang-switcher summary::-webkit-details-marker { display: none; }
.lang-switcher summary:hover { color: var(--text-1); background: var(--surface); }
.lang-switcher summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lang-switcher[open] summary { color: var(--accent); }
.lang-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 12rem;
  max-height: 70vh;
  overflow-y: auto;
  margin: 0;
  padding: 8px;
  list-style: none;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.lang-option {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  color: var(--text-3);
  white-space: nowrap;
}
.lang-option--active { color: var(--accent); font-weight: 700; }
.lang-tag {
  margin-left: auto;
  padding: 1px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 0.72rem;
  color: var(--text-3);
}

/* === Build 373: country flags + a filter box in the language switcher ======
   Jacques: "on the top right, under the language selection, add a filter to
   filter the language selection ... and add the flag(s) corresponding to the
   language." The flags sit on the LEFT of every language, several of them when
   a language is spoken in more than one country; the artwork is bundled at
   /assets/flags/<cc>.svg, so nothing is fetched from a third party. The filter
   is the first <li> of the list, so it scrolls with it and inherits the
   dropdown's own background and border; app.js (e2) drives it. */
.lang-filter-item {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 2px 2px 8px;
  margin: -2px -2px 4px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}
.lang-filter {
  width: 100%;
  box-sizing: border-box;
  min-height: 34px;
  padding: 6px 10px;
  font: inherit;
  font-size: 0.875rem;
  color: var(--text-1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.lang-filter::placeholder { color: var(--text-3); }
.lang-filter:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lang-filter-empty {
  padding: 8px 10px;
  font-size: 0.82rem;
  color: var(--text-3);
}
.lang-list li[hidden] { display: none; }
.lang-flags {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: none;
}
.lang-flag {
  display: block;
  height: 14px;
  width: auto;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
}
.lang-switcher summary .lang-flag { height: 12px; }

@media (max-width: 900px) {
  .lang-switcher {
    margin: 8px 0 0;
    padding: 12px 0 0;
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .lang-switcher summary { padding: 10px 12px; }
  .lang-list {
    position: static;
    min-width: 0;
    max-height: 50vh;
    margin-top: 4px;
    box-shadow: none;
    background: var(--surface);
  }
}

/* === Session 7: tpee.exe top-bar simulation (index hero only) ==============
   Interactive replica of the application's menu bar + IDE/Model selector row,
   mirrored verbatim from src/main.rs (Build 183). Same <details>/<summary>
   pattern as the Session-6 language switcher: works with JS disabled; app.js
   section (f) adds aria-expanded sync, sibling close, Esc, outside-click and
   desktop hover-switching. Desktop (>=901px): horizontal tab row that WRAPS
   to two lines at mid widths, dropdown panels, submenus fly out sideways.
   Mobile (<=900px): vertically stacked accordion, panels in-flow. Items are
   illustrative (inert) — the caption under the frame says so. */
.app-preview-eyebrow {
  margin: 0 0 10px;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.app-preview {
  margin: 0 0 2.5rem;
  max-width: 980px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  overflow: visible; /* dropdown panels must escape the frame */
  font-size: 0.875rem;
}
.app-chrome {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.app-chrome-icon { display: block; }
.app-chrome-title { font-weight: 650; color: var(--text-1); }
.app-chrome-build {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-3);
  white-space: nowrap;
}
.app-menubar {
  display: flex;
  flex-wrap: wrap; /* mid-width desktops: tabs flow onto a second line */
  align-items: center;
  row-gap: 2px;
  padding: 4px 6px;
  border-bottom: 1px solid var(--line);
}
.app-menu { position: relative; }
.app-menu > summary,
.app-menu-static {
  display: flex;
  align-items: center;
  min-height: 34px;
  padding: 5px 10px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  white-space: nowrap;
  list-style: none; /* hide default disclosure triangle */
  transition: color 160ms var(--ease), background-color 160ms var(--ease);
}
.app-menu > summary { cursor: pointer; }
.app-menu > summary::-webkit-details-marker { display: none; }
.app-menu > summary:hover { color: var(--text-1); background: var(--surface-2); }
.app-menu > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-menu[open] > summary { color: var(--accent); background: var(--surface-2); }
.app-menu-static { cursor: default; }
.app-menu-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 40;
  min-width: 15rem;
  max-width: min(34rem, 86vw);
  max-height: 70vh;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
/* Right-edge menus open leftward so panels stay inside the viewport. */
.app-menu--end > .app-menu-panel { left: auto; right: 0; }
.app-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 30px;
  padding: 4px 10px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  white-space: nowrap;
  cursor: pointer; /* clicking an item closes the menu, like the real app */
}
.app-menu-item:hover { color: var(--text-1); background: var(--surface); }
.app-menu-item--weak { color: var(--text-3); cursor: default; }
.app-menu-item--weak:hover { color: var(--text-3); background: transparent; }
.app-menu-item--active { color: var(--accent); font-weight: 650; }
.app-item-label { overflow: hidden; text-overflow: ellipsis; }
.app-shortcut {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-3);
  background: transparent;
  border: 0;
}
.app-menu-group {
  padding: 8px 10px 2px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text-1);
}
.app-menu-sep {
  height: 1px;
  margin: 6px 4px;
  background: var(--line);
}
.app-check { margin-right: 8px; color: var(--green); }
.app-font-current { color: var(--accent); }
.app-font-size-row { justify-content: flex-start; gap: 10px; }
.app-font-size { min-width: 2ch; text-align: center; color: var(--text-1); }
.app-font-btn {
  padding: 1px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--text-2);
}
/* Submenus: a summary row inside a panel; desktop = sideways flyout. */
.app-sub { position: relative; }
.app-sub > .app-menu > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 30px;
  padding: 4px 10px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}
.app-sub > .app-menu > summary::-webkit-details-marker { display: none; }
.app-sub > .app-menu > summary::after {
  content: "▸";
  margin-left: auto;
  color: var(--text-3);
}
.app-sub > .app-menu > summary:hover { color: var(--text-1); background: var(--surface); }
.app-sub > .app-menu > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-sub > .app-menu[open] > summary { color: var(--text-1); background: var(--surface); }
.app-sub > .app-menu > .app-menu-panel {
  top: -7px;
  left: calc(100% + 2px);
  min-width: 13rem;
}
.app-menu--end .app-sub > .app-menu > .app-menu-panel {
  left: auto;
  right: calc(100% + 2px); /* fly LEFT out of right-edge menus */
}
.app-selectors {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  padding: 10px 14px;
  color: var(--text-2);
}
.app-selector strong { color: var(--text-1); }
.app-preview-note {
  margin: 0;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  color: var(--text-3);
}

@media (max-width: 900px) {
  /* Vertically stacked menu: tabs become full-width accordion rows and
     every panel renders in-flow (no absolute positioning to overflow). */
  .app-preview { font-size: 0.9375rem; }
  .app-chrome-build { display: none; }
  .app-menubar {
    flex-direction: column;
    align-items: stretch;
    row-gap: 0;
    padding: 4px;
  }
  .app-menu > summary,
  .app-menu-static {
    min-height: 44px;
    padding: 10px 12px;
    white-space: normal;
  }
  .app-menu > summary::after {
    content: "▾";
    margin-left: auto;
    color: var(--text-3);
  }
  .app-menu[open] > summary::after { content: "▴"; }
  .app-menu > summary::after { transition: none; }
  .app-menu-panel,
  .app-sub > .app-menu > .app-menu-panel,
  .app-menu--end .app-sub > .app-menu > .app-menu-panel {
    position: static;
    min-width: 0;
    max-width: none;
    width: 100%;
    max-height: 60vh;
    margin: 2px 0 6px;
    box-shadow: none;
    background: var(--surface);
  }
  .app-menu-item {
    min-height: 40px;
    white-space: normal;
  }
  .app-sub > .app-menu > summary { min-height: 40px; white-space: normal; }
}

/* ===== Session 8: "USE PROMPT ENHANCING WORKFLOW" replica (index only) =====
   Colours and behaviour mirrored VERBATIM from src/prompt_enhancing.rs
   (Build 183): STEP_GREEN rgb(0,168,70), STEP_WHITE rgb(245,245,245),
   INDICATOR_RED rgb(225,60,50), ARROW_YELLOW rgb(255,230,0),
   ARROW_DIM rgb(110,102,55), DARK_BUTTON rgb(45,45,45),
   BUTTON_YELLOW rgb(255,230,0), OUTLINE rgb(50,50,50).
   Disabled look = egui's add_enabled(false) fade (~45% opacity). Circles and
   arrows are custom-painted in the app, so they do NOT fade — only the dim
   arrow colour changes; buttons and indicators fade. */
.pew-eyebrow {
  margin: 0 0 10px;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.pew-preview {
  margin: 0 0 2.5rem;
  max-width: 980px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  font-size: 0.875rem;
}
.pew-strip {
  display: flex;
  flex-wrap: wrap; /* narrow widths: groups flow onto extra lines */
  align-items: center;
  gap: 10px 5px;
  padding: 12px 14px 6px;
}
.pew-label {
  font-size: 0.5625rem; /* 9px, like the app's RichText::size(9.0) */
  font-weight: 700;
  line-height: 1.25;
  color: var(--text-1);
  margin-right: 5px;
}
.pew-tick {
  width: 16px;
  height: 16px;
  margin: 0 8px 0 0;
  accent-color: var(--accent);
  cursor: pointer;
  flex: none;
}
.pew-walk { flex: 1 1 auto; min-width: 320px; }
.pew-walk-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 5px;
}
.pew-caption {
  margin: 6px 0 0;
  text-align: center; /* centered between the two arrows, like the app */
  font-size: 0.71875rem; /* 11.5px */
  color: var(--text-1);
}
/* Numbered step circle: green when it is the current step, white otherwise.
   Clickable (jump to step) only for 2..=5 while the workflow is enabled. */
.pew-step {
  width: 22px;
  height: 22px;
  flex: none;
  padding: 0;
  border: 1.5px solid #323232; /* OUTLINE */
  border-radius: 50%;
  background: #f5f5f5; /* STEP_WHITE */
  color: #000;
  font-size: 13px;
  line-height: 1;
  font-weight: 500;
  cursor: default;
}
.pew-step.is-current { background: #00a846; } /* STEP_GREEN */
.pew-step:not(:disabled) { cursor: pointer; }
/* Yellow triangle arrow (24x20 in the app): bright when the workflow is
   enabled, dim olive otherwise. */
.pew-arrow {
  width: 24px;
  height: 20px;
  flex: none;
  padding: 0;
  border: 0;
  background: #6e6637; /* ARROW_DIM */
  cursor: default;
}
.pew-arrow--left { clip-path: polygon(100% 0, 0 50%, 100% 100%); }
.pew-arrow--right { clip-path: polygon(0 0, 100% 50%, 0 100%); }
.pew-arrow.is-on { background: #ffe600; cursor: pointer; } /* ARROW_YELLOW */
/* Red/green rounded indicator (EDIT PRE-PROMPT / EDIT POST-PROMPT): green when
   its step is active, red otherwise; faded while the workflow is off. */
.pew-indicator {
  min-width: 92px;
  min-height: 26px;
  flex: none;
  padding: 2px 10px;
  border: 0;
  border-radius: 10px;
  background: #e13c32; /* INDICATOR_RED */
  color: #000;
  font-size: 9.5px;
  font-weight: 700;
  line-height: 1.2;
  cursor: default;
}
.pew-indicator.is-active { background: #00a846; } /* STEP_GREEN */
.pew-indicator:not(:disabled) { cursor: pointer; }
.pew-indicator:disabled { opacity: 0.45; }
/* Dark rounded button with yellow text (COMBINE / OPEN / COPY). COMBINE turns
   green with black text from step 4 (highlight_green in the app). OPEN/COPY
   are enabled at step 5 only. */
.pew-dark {
  min-width: 120px;
  min-height: 26px;
  flex: none;
  padding: 3px 12px;
  border: 0;
  border-radius: 8px;
  background: #2d2d2d; /* DARK_BUTTON */
  color: #ffe600; /* BUTTON_YELLOW */
  font-size: 9.5px;
  font-weight: 700;
  line-height: 1.25;
}
.pew-dark.is-lit { background: #00a846; color: #000; } /* STEP_GREEN highlight */
.pew-dark:not(:disabled) { cursor: pointer; }
.pew-dark:disabled { opacity: 0.45; }
.pew-status {
  margin: 0;
  min-height: 1.2em;
  padding: 0 14px;
  font-size: 0.75rem;
  color: var(--accent);
}
.pew-status:empty { padding: 0; }
.pew-note {
  margin: 0;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  color: var(--text-3);
}

@media (max-width: 900px) {
  /* The strip wraps group-by-group; touch targets grow to 44px where the
     app's fixed sizes would be too small to tap. */
  .pew-strip { gap: 10px 8px; }
  .pew-walk { min-width: 0; flex-basis: 100%; order: 3; }
  .pew-walk-row { gap: 8px 6px; }
  .pew-step { width: 32px; height: 32px; font-size: 15px; }
  .pew-arrow { width: 34px; height: 28px; }
  .pew-indicator { min-height: 36px; font-size: 10.5px; }
  .pew-dark { min-height: 36px; font-size: 10.5px; }
  .pew-caption { text-align: left; }
}

/* ===== Session 11: Functions section + User's Manual window replica ======
   The demo block (.fn-demo) sits on the LIGHT page; the modal window
   (.manual-modal) mirrors the dark tpee.exe "User's Manual" window from
   src/manual.rs (default size 1000x640, min 600x420) and therefore joined
   the dark-chrome token group at the top of this file. */

/* #pew-demo is the scroll target of the GO TO VISUAL DEMO button — it is a
   <p>, not a section, so the global section[id] scroll-margin doesn't cover
   it. Same 80px clearance under the sticky header. */
#pew-demo { scroll-margin-top: calc(var(--header-h) + 16px); }

.pew-goto { margin: 1.5rem 0 0; }

.fn-demo {
  max-width: 720px;
  margin: 0 auto;
  text-align: center;
}
.fn-title { margin-bottom: 0.25em; }
/* Session 61: editor headings carry a right-aligned "try" hint, mirroring the
   screenshots/gallery .section-head pattern. */
.fn-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.25em;
}
.fn-title-row .fn-title { margin-bottom: 0; }
.fn-above {
  margin: 0 0 0.9rem;
  color: var(--text-2);
}
.fn-under {
  margin: 0.9rem 0 0;
  font-size: 0.9rem;
  color: var(--text-3);
}

/* The "User's Manual" button, painted like the app's dark egui button. */
.manual-open-btn {
  min-height: 44px;
  padding: 10px 28px;
  border: 1px solid #323232; /* OUTLINE, like the app's dark buttons */
  border-radius: 8px;
  background: #2d2d2d;       /* DARK_BUTTON rgb(45,45,45) */
  color: #f5f5f5;            /* STEP_WHITE rgb(245,245,245) */
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}
.manual-open-btn:hover { background: #3a3a3a; }

/* ----- Modal window (mirrors egui::Window "User's Manual") --------------- */
.manual-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vh 3vw;
}
.manual-modal[hidden] { display: none; }
.manual-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 8, 14, 0.66); /* hardcoded: overlay sits on the page */
}
.manual-window {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(1000px, 100%);   /* the app's default_size [1000, 640] */
  height: min(640px, 100%);
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.manual-chrome {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line);
}
.manual-chrome .app-chrome-title { flex: 1 1 auto; }
.manual-close {
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-2);
  font-size: 0.9rem;
  cursor: pointer;
}
.manual-close:hover { background: var(--surface-2); color: var(--text-1); }

/* Toolbar: 4 document buttons + heading + Print/Reload (src/manual.rs). */
.manual-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
}
.manual-docs { display: flex; flex-wrap: wrap; gap: 6px; }
.manual-doc-btn {
  min-height: 32px;
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-1);
  font-size: 0.8125rem;
  cursor: pointer;
}
.manual-doc-btn:hover { border-color: var(--accent); }
.manual-doc-btn.is-selected {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: 700;
}
.manual-heading {
  flex: 1 1 auto;
  text-align: center;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--text-1);
  white-space: nowrap;
}
.manual-tools { display: flex; gap: 6px; }
.manual-tool-btn {
  min-height: 32px;
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-1);
  font-size: 0.8125rem;
  cursor: pointer;
}
.manual-tool-btn:hover { background: var(--surface-2); }

/* Body: left TOC (230px, like the app) + right content pane. */
.manual-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
}
.manual-toc {
  flex: 0 0 230px; /* toc_panel_width in src/manual.rs */
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 8px;
  border-right: 1px solid var(--line);
}
.manual-filter-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.manual-filter {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
  color: var(--text-1);
  font-size: 0.8125rem;
}
.manual-count {
  margin: 6px 0;
  font-size: 0.75rem;
  color: var(--text-3);
}
.manual-toc-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  border-top: 1px solid var(--line);
  padding-top: 6px;
}
.manual-toc-item {
  display: block;
  width: 100%;
  padding: 4px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-2);
  font-size: 0.78rem;
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
}
.manual-toc-item:hover { background: var(--surface-2); color: var(--text-1); }
.manual-toc-item[hidden] { display: none; }

.manual-content {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 12px 18px 24px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--text-1);
}
.manual-content h1 { font-size: 1.35rem; margin: 0.4em 0; }
.manual-content h2 { font-size: 1.15rem; margin: 1.2em 0 0.4em; color: var(--accent); }
.manual-content h3 { font-size: 1rem; margin: 1em 0 0.3em; }
.manual-content h4, .manual-content h5 { font-size: 0.9rem; margin: 0.9em 0 0.3em; }
.manual-content p { margin: 0 0 0.7em; }
.manual-content ul, .manual-content ol { margin: 0 0 0.7em; padding-left: 22px; }
.manual-content li { margin: 3px 0; }
.manual-content a { color: var(--accent); }
.manual-content code {
  font-family: var(--font-mono);
  font-size: 0.8em;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 1px 5px;
}
.manual-content pre {
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  overflow-x: auto;
}
.manual-content pre code { background: none; border: 0; padding: 0; }
.manual-content blockquote {
  margin: 0 0 0.7em;
  padding: 6px 12px;
  border-left: 3px solid var(--accent);
  background: var(--bg-1);
  color: var(--text-2);
  font-size: 0.85em;
}
.manual-content hr { border: 0; border-top: 1px solid var(--line); margin: 1.2em 0; }
.manual-content table {
  border-collapse: collapse;
  margin: 0 0 0.9em;
  font-size: 0.82rem;
  max-width: 100%;
}
.manual-content th, .manual-content td {
  border: 1px solid var(--line);
  padding: 4px 10px;
  text-align: left;
  vertical-align: top;
}
.manual-content th { background: var(--surface-2); }

.manual-status {
  margin: 0;
  min-height: 1.4em;
  padding: 4px 12px;
  border-top: 1px solid var(--line);
  font-size: 0.75rem;
  color: var(--accent);
}
.manual-status:empty { padding: 0; border-top: 0; }

@media (max-width: 900px) {
  .manual-modal { padding: 0; }
  .manual-window { width: 100%; height: 100%; border-radius: 0; }
  .manual-heading { order: 3; flex-basis: 100%; text-align: left; }
  .manual-body { flex-direction: column; }
  .manual-toc {
    flex: 0 0 auto;
    max-height: 32vh;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .manual-doc-btn, .manual-tool-btn { min-height: 44px; }
}

/* ===== Session 12: Learning Center window replica ==========================
   Mirrors src/learning.rs render_learning_window (Build 183): the egui window
   "Learning Center - TPEE Professional AI Course" (min 760x460, default up to
   1120x760), intro line, left 330px panel (Students + Lessons) and right
   lesson pane with the "Knowledge Check" quiz. The shell (modal, window,
   chrome, close, status) REUSES the Session-11 .manual-* classes; only the
   Learning-specific layout below is new. .learn-modal joined the dark-chrome
   token group at the top of this file. */

.learn-window {
  width: min(1040px, 100%);  /* app default band: 760..1120 px wide */
  height: min(720px, 100%);  /* app default band: 500..760 px high */
}

.learn-intro {
  margin: 0;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 0.85rem;
  color: var(--text-2);
}
.learn-intro strong { color: var(--text-1); }

.learn-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
}

/* Left panel: 330px exactly like the app (render_left_panel). */
.learn-left {
  flex: 0 0 330px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 8px 10px;
  border-right: 1px solid var(--line);
}
.learn-h {
  margin: 0.5em 0 0.35em;
  font-size: 0.95rem;
  color: var(--text-1);
}
.learn-add-row {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.learn-name {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
  color: var(--text-1);
  font-size: 0.8125rem;
}
.learn-students {
  flex: 0 0 auto;
  max-height: 120px;           /* the app's ScrollArea max_height(120.0) */
  overflow-y: auto;
}
.learn-lessons {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  border-top: 1px solid var(--line);
  padding-top: 6px;
}
.learn-item {
  display: block;
  width: 100%;
  padding: 4px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-2);
  font-size: 0.78rem;
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
}
.learn-item:hover { background: var(--surface-2); color: var(--text-1); }
.learn-item.is-selected {
  background: var(--surface-2);
  color: var(--accent);
  font-weight: 700;
}

/* Right lesson pane (render_lesson_panel). */
.learn-right {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 12px 18px 24px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--text-1);
}
.learn-right h3 { font-size: 1.1rem; margin: 0.2em 0 0.3em; color: var(--accent); }
.learn-right h4 { font-size: 1rem; margin: 1em 0 0.4em; }
.learn-meta {
  margin: 0 0 0.3em;
  font-size: 0.8rem;
  color: var(--text-2);
}
.learn-right p.learn-para { margin: 0 0 0.7em; }
.learn-rule { border: 0; border-top: 1px solid var(--line); margin: 0.9em 0; }

.learn-q {
  margin: 0 0 10px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
}
.learn-q p { margin: 0 0 6px; font-weight: 700; font-size: 0.85rem; }
.learn-opt {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 4px 0;
  font-size: 0.83rem;
  color: var(--text-2);
  cursor: pointer;
}
.learn-opt input { margin-top: 3px; accent-color: var(--accent); }
.learn-opt:hover { color: var(--text-1); }

.learn-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.learn-submit {
  min-height: 32px;
  padding: 4px 14px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 0.8125rem;
  font-weight: 700;
  cursor: pointer;
}
.learn-submit:hover { filter: brightness(1.1); }

@media (max-width: 900px) {
  .learn-window { width: 100%; height: 100%; } /* beat the later-source-order
     .learn-window size rule, same full-bleed as .manual-window */
  .learn-body { flex-direction: column; }
  .learn-left {
    flex: 0 0 auto;
    max-height: 42vh;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .learn-submit { min-height: 44px; }
}

/* ===== Session 67: ClassRoom Presentation window replica ====================
   Mirrors src/classroom_presentation.rs Build 355 (render_window,
   draw_mire_pattern, draw_alignment_target, the lesson panes and
   render_lecturer_notes). The shell (.manual-modal / .manual-window /
   .manual-chrome / .manual-close / .manual-status) is REUSED from the
   Session-11 manual window, exactly as the Session-12 Learning replica does;
   only the .classroom-* layout below is new. .classroom-modal joined the
   dark-chrome token group at the top of this file (mandatory: without it the
   replica renders in the page's light tokens).
   The app's windowed band is 760..1600 x 420..900 px, so the replica opens at
   1120 x 760 and Maximize becomes a full-bleed state with the title bar and
   the toolbar still visible (the part that matters — an OS window cannot be
   reproduced in a page). */
.classroom-window {
  width: min(1120px, 100%);
  height: min(760px, 100%);
}

/* Maximize: the window fills the screen; chrome and toolbar stay. */
.classroom-modal.is-max { padding: 0; }
.classroom-modal.is-max .classroom-window {
  width: 100%;
  height: 100%;
  border-radius: 0;
}

/* The highlight band triples. These are the two the app's highlight_palette()
   produces (Build 349): fill / ink / edge, each pair clearing the 7:1 AAA level
   for normal-size text — measured 12.80:1 on the light slide and 9.84:1 on the
   black slide. The site has one light theme plus this replica's dark mode, so
   the band does NOT claim to follow a theme. The bullet tip's ratio is measured
   from THESE values at runtime by app.js. */
.classroom-modal {
  --band-fill: #FFD54F;
  --band-ink: #1A160A;
  --band-edge: #785000;
}
.classroom-modal.is-dark {
  --band-fill: #483A08;
  --band-ink: #FFF0C8;
  --band-edge: #FFCA28;
}

/* `hidden` must beat the display rules below: the attribute selector outranks
   the bare class (no !important needed). */
.classroom-mire[hidden],
.classroom-body[hidden],
.classroom-styles[hidden],
.classroom-counter[hidden],
.classroom-divider[hidden],
.classroom-notes[hidden],
.classroom-notice[hidden],
.classroom-say-set[hidden] { display: none; }

/* Toolbar: WRAPPED, mirroring egui's horizontal_wrapped — a clipped Close
   button is a trap. */
.classroom-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
}
.classroom-heading {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--text-1);
}
.classroom-btn {
  min-height: 32px;
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-1);
  font-size: 0.8125rem;
  cursor: pointer;
}
.classroom-btn:hover { background: var(--surface-2); }
/* an egui selectable_label */
.classroom-btn.is-selected {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: 700;
}
.classroom-styles { display: flex; flex-wrap: wrap; gap: 6px; }
.classroom-counter {
  font-size: 0.8125rem;
  color: var(--text-2);
  white-space: pre; /* keeps the app's two spaces either side of the bullet */
}

/* TV-MIRE surface: #181818 (from_gray(24)), black in dark mode or on the
   Target card — the Target card is on black either way. */
.classroom-mire {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background: #181818;
}
.classroom-modal.is-dark .classroom-mire,
.classroom-mire.is-target { background: #000; }
.classroom-caption {
  position: absolute;
  top: 10px;
  left: 0;
  right: 0;
  margin: 0;
  text-align: center;
  color: #fff;
  font-size: 18px;
}
@media (max-height: 800px) { .classroom-caption { font-size: 15px; } }
.classroom-canvas { display: block; width: 100%; height: 100%; }

/* Lesson panes */
.classroom-body { display: flex; flex: 1 1 auto; min-height: 0; }
.classroom-modal.is-dark .classroom-body { background: #000; }
.classroom-left {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 8px 10px;
  border-right: 1px solid var(--line);
  flex: 0 0 260px; /* the stored splitter width is set inline from state */
}
.classroom-strong { margin: 0.5em 0 0.35em; font-size: 0.9rem; color: var(--text-1); }
.classroom-goto {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8125rem;
  color: var(--text-2);
}
.classroom-num {
  width: 5.5em;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
  color: var(--text-1);
  font: inherit;
}
.classroom-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin: 6px 0;
}
.classroom-lessons { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-top: 6px; }

/* The two drag handles carry the app's dot markers. One 8 px radial tile gives
   a COLUMN of dots on the 6 px vertical splitter and a ROW on the 10 px
   horizontal divider, because the box is narrower than one tile across. */
.classroom-splitter,
.classroom-divider {
  background-color: #BEBEBE;
  background-image: radial-gradient(#8C8C8C 1.4px, transparent 1.5px);
  background-size: 8px 8px;
  background-position: center;
}
.classroom-splitter { flex: 0 0 6px; cursor: ew-resize; }
.classroom-divider { flex: 0 0 10px; cursor: ns-resize; }
.classroom-splitter:hover,
.classroom-divider:hover { background-color: var(--surface-2); }
.classroom-modal.is-dark .classroom-splitter,
.classroom-modal.is-dark .classroom-divider { background-color: #606060; }

.classroom-right {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  flex: 1 1 auto;
}
.classroom-slide { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px 18px 24px; }
.classroom-slide-title { font-size: 1.75rem; margin: 0.2em 0 0.3em; color: var(--text-1); }
.classroom-slide-meta { font-size: 1.125rem; margin: 0 0 0.3em; color: var(--text-2); }
.classroom-label { font-size: 0.8125rem; color: var(--text-2); }

/* Bullet rows: inner margin symmetric(10, 6), rounding 6. */
.classroom-bullets {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.classroom-bullet {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  font-size: 1.125rem; /* the app's 18 px paragraph */
  cursor: pointer;
}
/* the app's 1 px hover outline — suppressed on the selected row below */
.classroom-bullet:hover { border-color: var(--accent); }
.classroom-glyph { font-size: 24px; font-weight: 700; line-height: 1.15; }
.classroom-text { flex: 1 1 auto; }
/* The selected line: a fill, a 1.5 px outline and a solid 4 px left accent bar
   — "this one" carried in SHAPE, not colour alone, readable from the back of a
   room and for a colour-blind viewer. */
.classroom-bullet.is-selected {
  background: var(--band-fill);
  color: var(--band-ink);
  border-color: var(--band-edge);
  border-width: 1.5px;
  box-shadow: inset 4px 0 0 0 var(--band-edge);
}
.classroom-bullet.is-selected:hover { border-color: var(--band-edge); }

/* The Lecturer Notes pane (render_lecturer_notes) */
.classroom-notes {
  border-top: 1px solid var(--line);
  overflow-y: auto;
  padding: 8px 14px;
  font-size: 0.875rem;
  color: var(--text-1);
}
.classroom-notes-head { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: baseline; }
.classroom-notes-head .classroom-strong { font-size: 1rem; }
.classroom-notes-where { font-size: 0.875rem; color: var(--text-2); }
.classroom-aim { margin: 0.4em 0; }
.classroom-notes-q { margin: 0.5em 0 0.1em; }
/* 5-space indent in the app; leading spaces collapse in HTML, so use padding */
.classroom-answer { margin: 0; padding-left: 2.2em; font-style: italic; }
.classroom-why { margin: 0 0 0.3em; padding-left: 2.2em; color: var(--text-2); }
.classroom-next { margin: 0.6em 0 0; color: var(--text-2); }
.classroom-notice { margin: 0; padding: 8px 12px; color: var(--text-2); font-size: 0.875rem; }

/* The captive short-window state (the app's notes_mode == 2), driven by the
   measured pane height, not by a viewport media query. */
.classroom-window.is-short .classroom-divider,
.classroom-window.is-short .classroom-notes { display: none; }

@media (max-width: 900px) {
  .classroom-window { width: 100%; height: 100%; } /* same full-bleed as
     .manual-window / .learn-window */
  .classroom-body { flex-direction: column; }
  .classroom-left {
    flex: 0 0 auto;
    max-height: 42vh;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .classroom-splitter { display: none; } /* nothing to resize side-by-side */
  .classroom-btn { min-height: 44px; }
}

/* ===== Session 13: IDE Selection combobox replica ==========================
   The .ide-preview frame is INLINE on the light page (unlike the manual /
   learning modals) because in the real app the combobox lives in the IDE &
   Model Selection Toolbar Row (src/main.rs Build 183, session2_ide_selector,
   lines ~11380-11452) — it is not a window. The frame joined the dark-token
   group at the top of this file so the replica keeps the app's dark egui
   palette. Data: assets/ide/ide-profiles.json (tools/build_ide_profiles.py,
   1:1 from src/ide_profiles.rs + src/ide_profiles_002.rs). */

.ide-preview {
  position: relative;
  margin: 0 auto;
  max-width: 560px;
  padding: 14px 16px 10px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}

/* The toolbar row: "IDE:" strong light-blue label + 200px ComboBox, like
   the app's ui.horizontal row (label color egui Color32::LIGHT_BLUE). */
.ide-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ide-label {
  font-weight: 700;
  color: #8cb4ff; /* LIGHT_BLUE label, as in src/main.rs */
}

/* ComboBox button: 200px wide (the app's .width(200.0)), dark egui button
   styling shared with .manual-open-btn but left-aligned with a caret. */
.ide-combo-wrap { position: relative; }
.ide-combo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 200px; /* the app's ComboBox width */
  min-height: 36px;
  padding: 6px 10px;
  border: 1px solid #323232;
  border-radius: 6px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.ide-combo:hover { background: #3a3a3a; }
.ide-caret { color: var(--text-3); }

/* The popup: egui paints it at the button's width with a vertical
   ScrollArea (max combo_height ~200px in egui); items are
   "🖥️ <name>" selectable rows that highlight on hover/active. */
.ide-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 30;
  width: 200px; /* popup width = button width, like egui */
  max-height: 260px;
  overflow-y: auto;
  background: #1b1b1b;
  border: 1px solid #323232;
  border-radius: 6px;
  box-shadow: var(--shadow-1);
  padding: 2px;
}
.ide-dropdown[hidden] { display: none; }
.ide-option {
  display: block;
  width: 100%;
  padding: 6px 10px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.ide-option:hover,
.ide-option.is-active { background: #3a3a3a; }
.ide-option.is-selected { color: var(--accent); }

/* The status line, mono like the app's status bar
   ("IDE changed to: <name>"). */
.ide-status {
  min-height: 1.2em;
  margin: 8px 0 0;
  font-size: 0.78rem;
  color: var(--text-3);
}

/* The profile card: what TPEE stores about the selected IDE (the
   IdeProfile struct fields), shown after a selection. */
.ide-info {
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.ide-info[hidden] { display: none; }
.ide-info-name {
  margin: 0 0 2px;
  font-size: 1rem;
  color: var(--text-1);
}
.ide-info-desc {
  margin: 0 0 8px;
  font-size: 0.875rem;
  color: var(--text-2);
}
.ide-info-meta {
  margin: 0 0 8px;
  font-size: 0.78rem;
  color: var(--text-3);
}
.ide-info-h {
  margin: 8px 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3);
}
.ide-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.ide-chip {
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.75rem;
  color: var(--text-2);
}
.ide-tips {
  margin: 0;
  padding-left: 18px;
  font-size: 0.8125rem;
  color: var(--text-2);
}
.ide-tips li { margin: 2px 0; }

@media (max-width: 900px) {
  .ide-preview { max-width: 100%; }
  .ide-combo { min-height: 44px; } /* touch target, like .learn-submit */
}

/* ===== Session 14: Model Selection combobox replica =======================
   The .model-preview frame is INLINE on the light page (like the Session-13
   IDE demo) because in the real app the combobox lives in the IDE & Model
   Selection Toolbar Row (src/main.rs Build 183, session2_model_selector,
   lines ~11456-11701) — it is not a window. The frame joined the dark-token
   group at the top of this file so the replica keeps the app's dark egui
   palette. Data: assets/models/model-profiles.json
   (tools/build_model_profiles.py, 1:1 from get_api_limits() in src/main.rs
   + the provider tables in src/model_profiles.rs). */

.model-preview {
  position: relative;
  margin: 0 auto;
  max-width: 620px;
  padding: 14px 16px 10px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}

/* The toolbar row: "Model:" strong light-green label + 350px ComboBox,
   like the app's ui.horizontal row (label color egui Color32::LIGHT_GREEN
   = rgb(144,238,144)). */
.model-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
}
.model-label {
  font-weight: 700;
  color: #90ee90; /* LIGHT_GREEN label, as in src/main.rs */
}

/* ComboBox button: 350px wide (the app's .width(350.0) — "wide enough for
   Provider — Model Name"), dark egui button styling shared with the
   Session-13 IDE combo but left-aligned with a caret. */
.model-combo-wrap { position: relative; }
.model-combo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 350px; /* the app's ComboBox width */
  min-height: 36px;
  padding: 6px 10px;
  border: 1px solid #323232;
  border-radius: 6px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.model-combo:hover { background: #3a3a3a; }
.model-caret { color: var(--text-3); }

/* The popup: egui paints it at the button's width with a vertical
   ScrollArea (max combo_height in egui); the Build-091 filter row sits at
   the very top, then provider group headers (yellow, bold) with
   separators between groups, then "Provider — Name (Released …)"
   selectable rows that highlight on hover/active. */
.model-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 30;
  width: 350px; /* popup width = button width, like egui */
  background: #1b1b1b;
  border: 1px solid #323232;
  border-radius: 6px;
  box-shadow: var(--shadow-1);
  padding: 2px;
}
.model-dropdown[hidden] { display: none; }

/* Build-091 filter row: small light-blue "Filter:" label + TextEdit
   (250px desired width in the app) + tiny X clear button. */
.model-filter-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  border-bottom: 1px solid #323232; /* the app's ui.separator() */
}
.model-filter-label {
  font-size: 0.78rem;
  color: #8cb4ff; /* LIGHT_BLUE, as in src/main.rs */
}
.model-filter {
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.8125rem;
  font-family: inherit;
}
.model-filter::placeholder { color: var(--text-3); }
.model-filter:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.model-filter-clear {
  flex: 0 0 auto;
  padding: 1px 7px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.75rem;
  font-family: inherit;
  cursor: pointer;
}
.model-filter-clear:hover { background: #3a3a3a; }
.model-filter-clear[hidden] { display: none; }

/* The scrollable list under the filter row. */
.model-list {
  max-height: 260px;
  overflow-y: auto;
  padding: 2px 0;
}
.model-group {
  margin: 0;
  padding: 6px 10px 2px;
  font-size: 0.875rem;
  font-weight: 700;
  color: #ffff00; /* egui Color32::YELLOW provider header */
}
.model-group + .model-group,
.model-group--separated { border-top: 1px solid #323232; margin-top: 4px; }
.model-option {
  display: block;
  width: 100%;
  padding: 6px 10px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.model-option:hover,
.model-option.is-active { background: #3a3a3a; }
.model-option.is-selected { color: var(--accent); }

/* Build-091 no-match message (egui Color32::LIGHT_RED = rgb(255,128,128)). */
.model-nomatch {
  margin: 0;
  padding: 8px 10px;
  border-top: 1px solid #323232;
  font-size: 0.8125rem;
  color: #ff8080;
}

/* The status line, mono like the app's status bar
   ("Model changed to: <name>"). */
.model-status {
  min-height: 1.2em;
  margin: 8px 0 0;
  font-size: 0.78rem;
  color: var(--text-3);
}

/* The profile card: what TPEE stores about the selected model (the
   ModelProfile struct fields), shown after a selection. */
.model-info {
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.model-info[hidden] { display: none; }
.model-info-name {
  margin: 0 0 2px;
  font-size: 1rem;
  color: var(--text-1);
}
.model-info-meta {
  margin: 0 0 8px;
  font-size: 0.78rem;
  color: var(--text-3);
}
.model-info-h {
  margin: 8px 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3);
}
.model-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.model-chip {
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.75rem;
  color: var(--text-2);
}
.model-tips {
  margin: 0;
  padding-left: 18px;
  font-size: 0.8125rem;
  color: var(--text-2);
}
.model-tips li { margin: 2px 0; }

@media (max-width: 900px) {
  .model-preview { max-width: 100%; }
  .model-combo { width: 100%; min-height: 44px; } /* touch target */
  .model-combo-wrap { flex: 1 1 auto; min-width: 0; }
  .model-dropdown { width: 100%; }
}

/* ===== Session 15: API Character Limits window replica ==================
   Mirrors the app's bottom API limits panel from src/main.rs Build 183
   (lines ~9449-9700), shown as a modal window like the User's Manual demo
   (Jacques's instruction). The shell (modal, window, chrome, close,
   status) REUSES the Session-11 .manual-* classes; only API-limits
   layout below is new. .apil-modal joined the dark-chrome token group at
   the top of this file. */

.apil-window {
  width: min(1100px, 100%);  /* 3 x 350px provider columns + spacing */
  height: min(720px, 100%);
}

/* Heading row: ui.heading left, the grey "Last Updated" label right
   (main.rs ~9495-9508). */
.apil-heading-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 10px 14px 8px;
  border-bottom: 1px solid var(--line);
}
.apil-heading {
  margin: 0;
  font-size: 1.05rem;
  color: var(--text-1);
}
.apil-updated {
  font-size: 0.8rem;
  color: rgb(180, 180, 180); /* the app's light-grey label, verbatim */
}

/* Vertical-only scroll area (the app's Build-160 ScrollArea::vertical —
   the grid itself wraps the provider columns, so no horizontal bar). */
.apil-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 14px;
}

/* Provider grid: the app computes num_columns from a 350px minimum column
   width with 10px spacing (main.rs ~9547-9549); auto-fill/minmax mirrors
   that flow. Each provider is ONE grid cell holding its header + cards. */
.apil-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 10px;
  align-items: start;
}
.apil-provider {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.apil-provider-name {
  margin: 0;
  font-size: 0.85rem;
  color: #ffff00; /* egui Color32::YELLOW, verbatim */
}
/* The app adds 10px of space above every provider header except the
   first (main.rs ~9611). */
.apil-provider-name--spaced { margin-top: 10px; }

/* Model card (ui.group): name + Released date, usage bar, tokens, price. */
.apil-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
}
.apil-card--selected {
  /* main.rs ~9652-9655: 3px gold border, faint gold fill, 4px rounding */
  border: 3px solid rgb(255, 215, 0);
  border-radius: 4px;
  background: rgba(255, 215, 0, 0.098); /* 25/255 alpha, verbatim */
  padding: 6px 8px; /* compensate the thicker border */
}
.apil-card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.apil-name {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--text-1);
}
.apil-name--selected { color: rgb(255, 215, 0); } /* gold "★ name ★" */
.apil-released {
  font-size: 0.75rem;
  white-space: nowrap;
  color: rgb(200, 200, 140); /* render_name_and_release, verbatim */
}
.apil-released--selected { color: rgb(220, 200, 120); } /* selected variant */

/* Usage bar: egui ProgressBar look. 0% with a fresh (empty) prompt —
   the fill colour is get_usage_color(0) = green rgb(50,200,50). */
.apil-bar-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.apil-bar {
  flex: 1 1 auto;
  height: 12px;
  border-radius: 6px;
  background: var(--bg-1);
  overflow: hidden;
}
.apil-bar-fill {
  height: 100%;
  width: 0%;
  background: rgb(50, 200, 50);
}
.apil-pct {
  min-width: 3ch;
  text-align: right;
  font-size: 0.75rem;
  color: var(--text-2);
}
.apil-tokens,
.apil-price {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .apil-window { width: 100%; height: 100%; } /* beat the later-source-order
    .apil-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall — re-assert inside our own media block) */
  .apil-grid { grid-template-columns: 1fr; }
}

/* ===== Session 16: Model / Commands window replica ======================
   Mirrors the app's per-family command reference panel from
   src/model_commands_reference.rs Build 183 (render_panel, lines 685-769),
   shown as a modal window like the User's Manual demo (Jacques's
   instruction — in the app it is a bottom panel). The shell (modal,
   window, chrome, close, status) REUSES the Session-11 .manual-* classes;
   only the commands-sheet layout below is new. .cmd-modal joined the
   dark-chrome token group at the top of this file. */

.cmd-window {
  width: min(880px, 100%);   /* comfortable reading width for the monospace
    command tables (egui wraps the labels, so the sheet never scrolls
    sideways) */
  height: min(720px, 100%);
}

/* Vertical-only scroll area (the app's ScrollArea wraps the whole panel;
   the heading/banner/sections flow inside it). */
.cmd-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 16px;
}

/* ui.heading("<Family> / Commands (reference)") */
.cmd-heading {
  margin: 0 0 4px;
  font-size: 1.05rem;
  color: var(--text-1);
}

/* The app's italic REF_DATE_LINE in rgb(200,200,160), verbatim. */
.cmd-refdate {
  margin: 0 0 6px;
  font-size: 0.85rem;
  font-style: italic;
  color: rgb(200, 200, 160);
}

/* The app's family banner in rgb(255,220,120), verbatim. */
.cmd-banner {
  margin: 0 0 10px;
  font-size: 0.9rem;
  color: rgb(255, 220, 120);
}

/* egui CollapsingHeader: a clickable header row with a disclosure triangle;
   default-open in the app (open attribute in the markup), the Claude-only
   custom-commands section starts closed (default_open(false)). */
.cmd-section {
  margin-bottom: 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
}
.cmd-summary {
  display: block;
  padding: 8px 10px;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text-1);
  cursor: pointer;
  list-style: none;             /* we draw the egui-style triangle ourselves */
}
.cmd-summary::-webkit-details-marker { display: none; }
.cmd-summary::before {
  content: "\25BE";             /* ▾ open (egui CollapsingHeader arrow) */
  margin-right: 6px;
  color: var(--text-2);
}
.cmd-section:not([open]) .cmd-summary::before { content: "\25B8"; } /* ▸ */
.cmd-summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Tutorial text: the app's size-13 label; newlines kept (pre-line). */
.cmd-tutorial {
  margin: 0;
  padding: 0 10px 10px;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-1);
  white-space: pre-line;
}

/* Family overview intro: plain label text in the app. */
.cmd-intro {
  margin: 0;
  padding: 0 10px 10px;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--text-1);
}

/* The command table: the app's monospace size-11 label. egui labels WRAP,
   so pre-wrap here (no horizontal scroll, same as the app). */
.cmd-builtins {
  margin: 0;
  padding: 0 10px 10px;
  font-family: var(--font-mono);
  font-size: 0.72rem;           /* ≈ the app's 11.0pt monospace */
  line-height: 1.4;
  color: var(--text-1);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

@media (max-width: 900px) {
  .cmd-window { width: 100%; height: 100%; } /* beat the later-source-order
    .cmd-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall — re-assert inside our own media block) */
}


/* ----- Session 17: Optimization Tips window replica (Functions section) ----
   Mirrors the app's right-side Optimization Tips panel (src/main.rs Build
   183, lines 12510-12720), shown as a modal window like the User's Manual
   demo (Jacques's instruction — in the app it is a right SidePanel). The
   shell (modal, window, chrome, close, status) REUSES the Session-11
   .manual-* classes; only the tips layout below is new. .tips-modal joined
   the dark-chrome token group at the top of this file. */

.tips-window {
  width: min(560px, 100%);   /* the app's panel is narrow (default 280px,
    max 400px) — the window keeps a comfortable narrow reading column */
  height: min(640px, 100%);
}

/* Vertical-only scroll area (the app's ScrollArea::vertical wraps the
   whole panel; heading/context/tips flow inside it). */
.tips-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 16px;
}

/* ui.heading("💡 Optimization Tips") + the ui.separator() under the app's
   header row (the heading's bottom border plays the separator). */
.tips-heading {
  margin: 0 0 8px;
  padding-bottom: 8px;
  font-size: 1.05rem;
  color: var(--text-1);
  border-bottom: 1px solid var(--line);
}

/* The "🖥️ <IDE> + 🤖 <model>" context line: the app's .small() label in
   egui Color32::LIGHT_BLUE = rgb(140,180,255) (#8cb4ff site precedent). */
.tips-context {
  margin: 0 0 8px;
  font-size: 0.85rem;
  color: rgb(140, 180, 255);
}

/* One ui.group per tip: strong category label in the app's per-category
   colour (main.rs:12661-12678), tip text below, 4px gap between groups
   (the app's ui.add_space(4.0)). */
.tips-group {
  margin-bottom: 4px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-1);
}
.tips-cat {
  display: block;
  margin: 0 0 2px;
  font-weight: 700;
  font-size: 0.85rem;
}
.tips-cat--structure { color: rgb(100, 180, 255); }  /* Blue */
.tips-cat--style     { color: rgb(180, 130, 255); }  /* Purple */
.tips-cat--length    { color: rgb(255, 200, 80); }   /* Gold */
.tips-cat--features  { color: rgb(100, 220, 130); }  /* Green */

/* The tip text: plain wrapped label in the app (egui labels WRAP). */
.tips-text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text-1);
}

@media (max-width: 900px) {
  .tips-window { width: 100%; height: 100%; } /* beat the later-source-order
    .tips-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall — re-assert inside our own media block) */
}

/* ----- Session 18: Projects Prefixes window replica (Functions section) --
   Mirrors src/main.rs Build 183: the File Name / Project Prefix toolbar row
   (lines 11948-11989) as an INLINE .pfx-preview frame, and the egui::Window
   it opens (lines 19118-19294) as .pfx-modal — the app feature really IS a
   window, so no structural override (unlike Sessions 15-17). The shell
   (modal, window, chrome, close, status) REUSES the Session-11 .manual-*
   classes; only the prefixes layout below is new. .pfx-modal and
   .pfx-preview joined the dark-chrome token group at the top of this
   file. */

/* The inline toolbar-row frame (same pattern as .ide-preview /
   .model-preview): the app's ui.horizontal row is wide (200px File Name
   box + 20px space + 150px prefix box + suffix + button), so the frame
   gets a wider max-width and the row wraps on narrow screens. */
.pfx-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.pfx-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

/* "File Name:" is a plain ui.label (default text colour); "Project Prefix
   for Filename:" is strong LIGHT_BLUE (egui rgb(140,180,255) = #8cb4ff
   site precedent). The 20px spacer mirrors ui.add_space(20.0). */
.pfx-fname-label { color: var(--text-1); }
.pfx-prefix-label { font-weight: 700; color: #8cb4ff; }
.pfx-gap { flex: 0 0 20px; }

/* Dark egui TextEdit styling (same as .model-filter): 200px File Name box
   and 150px prefix boxes are the app's desired_width values. */
.pfx-input {
  padding: 4px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
}
.pfx-input::placeholder { color: var(--text-3); }
.pfx-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.pfx-input--fname { width: 200px; }
.pfx-input--prefix,
.pfx-input--new { width: 150px; }

/* The small grey "_Pmt_NNNN.txt" suffix (egui .small() + Color32::GRAY). */
.pfx-suffix { font-size: 0.78rem; color: rgb(128, 128, 128); }

/* The Build-068 toggle button keeps the .manual-open-btn styling; the
   5px left margin mirrors ui.add_space(5.0) before it. */
.pfx-open-btn { margin-left: 5px; }

/* The window: the app sets default_width 380 / min 280x260, resizable —
   the replica keeps a comfortable narrow column. */
.pfx-window {
  width: min(400px, 100%);
  height: min(560px, 100%);
}

/* Vertical-only scroll area around the window body (the window's own
   ScrollArea wraps only the list in the app — the list additionally caps
   at 250px below, matching ScrollArea::vertical().max_height(250.0)). */
.pfx-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 16px;
}

/* "Current prefix:" strong + the value in LIGHT_GREEN (#90ee90 = egui
   LIGHT_GREEN, site precedent from the Model: label). */
.pfx-current { margin: 5px 0; font-size: 0.9rem; color: var(--text-1); }
.pfx-current-value { color: #90ee90; }

/* The app's ui.separator() calls (with their add_space gaps). */
.pfx-sep { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }

.pfx-add-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pfx-add-label { font-size: 0.9rem; color: var(--text-1); }
.pfx-quick-wrap { margin: 8px 0 0; }
.pfx-quick-wrap[hidden] { display: none; }

/* "No saved prefixes yet. Add one above." plain label; "Saved Prefixes
   (N):" strong header. */
.pfx-empty { margin: 0; font-size: 0.9rem; color: var(--text-1); }
.pfx-empty[hidden] { display: none; }
.pfx-list-wrap[hidden] { display: none; }
.pfx-list-head { margin: 0 0 3px; font-size: 0.9rem; color: var(--text-1); }
.pfx-list {
  max-height: 250px; /* the app's ScrollArea max_height(250.0) */
  overflow-y: auto;
  overflow-x: hidden;
}

/* One row per saved prefix: selectable_label (full-width, left-aligned)
   + small 🗑 button. The current prefix reads "▶ X (current)" in
   LIGHT_GREEN; others are WHITE — the app's exact colours
   (main.rs:19243-19247). */
.pfx-item { display: flex; align-items: center; gap: 6px; padding: 1px 0; }
.pfx-pick {
  flex: 1 1 auto;
  min-width: 0;
  padding: 2px 6px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: rgb(255, 255, 255);
  font-size: 0.9rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.pfx-pick:hover { background: #3a3a3a; }
.pfx-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pfx-pick.is-current {
  color: #90ee90;
  background: rgba(144, 238, 144, 0.10); /* egui selected-fill hint */
}
.pfx-del {
  flex: 0 0 auto;
  padding: 1px 6px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.75rem;
  font-family: inherit;
  cursor: pointer;
}
.pfx-del:hover { background: #3a3a3a; }

.pfx-close-wrap { margin: 3px 0 0; }

@media (max-width: 900px) {
  .pfx-window { width: 100%; height: 100%; } /* beat the later-source-order
    .pfx-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall — re-assert inside our own media block) */
  .pfx-preview { max-width: 100%; }
  .pfx-gap { flex-basis: 0; }
}

/* ----- Session 19: Persona editor replica (Editors section) -------------
   Mirrors src/main.rs Build 183 (lines 12870-13176): the Persona editor is
   an INLINE Frame::group in the app's central panel (2px rgb(100,100,100)
   stroke, 10px rounding) — NOT a window — so .persona-preview is an inline
   frame like .ide-preview / .model-preview / .pfx-preview and joined the
   dark-chrome token group at the top of this file. */

/* The inline editor frame (same pattern as the other inline replicas).
   The app's editor group is wide (it fills the central panel), so the
   frame gets the 920px max-width the Session-18 toolbar frame uses. */
.persona-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}

/* egui Frame::group: 2px rgb(100,100,100) stroke, Rounding::same(10.0). */
.per-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02); /* egui group fill hint */
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}

/* The title bar: allocate_ui_with_layout row painted rect_filled
   rgb(50,50,50), rounding 10, 30px high; "Persona" WHITE size 20. */
.per-titlebar {
  display: flex;
  align-items: center;
  height: 30px;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.per-title { color: rgb(255, 255, 255); font-size: 20px; line-height: 1; }
.per-title-quality { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.per-quality-icon { font-size: 18px; line-height: 1; }
.per-quality-dot { font-size: 16px; line-height: 1; }
.per-quality-dot--bottom { font-size: 12px; }

/* The "🎭 Select Persona:" row (ui.horizontal). The filter TextEdit is
   the app's desired_width 200; ✖ clear shows only while the filter is
   non-empty. */
.per-select-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.per-select-label { color: var(--text-1); }
.per-filter {
  width: 200px;
  padding: 4px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
}
.per-filter::placeholder { color: var(--text-3); }
.per-filter:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Dark egui buttons (same recipe as .pfx-del / .manual-open-btn). */
.per-filter-clear,
.per-dropdown-btn,
.per-dropdown-close,
.per-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
}
.per-filter-clear:hover,
.per-dropdown-btn:hover,
.per-dropdown-close:hover,
.per-copy:hover { background: #3a3a3a; }
.per-filter-clear:focus-visible,
.per-dropdown-btn:focus-visible,
.per-dropdown-close:focus-visible,
.per-copy:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.per-matches { font-size: 0.875rem; color: var(--text-1); }

/* The dropdown: egui Frame::popup (1px rgb(100,100,100) stroke) with a
   max-300px vertical ScrollArea. Category headers are strong
   rgb(124,227,177) size 14 followed by ui.separator(); rows are
   selectable_label with a two-space indent. */
.per-dropdown {
  margin-top: 4px;
  padding: 6px;
  background: #262626; /* egui popup fill */
  border: 1px solid rgb(100, 100, 100);
  border-radius: 4px;
}
.per-list {
  max-height: 300px; /* the app's ScrollArea max_height(300.0) */
  overflow-y: auto;
  overflow-x: hidden;
}
.per-cat {
  margin: 4px 0 0;
  padding-bottom: 2px;
  font-size: 14px;
  font-weight: 700;
  color: rgb(124, 227, 177);
  border-bottom: 1px solid var(--line); /* the app's ui.separator() */
}
.per-option {
  display: block;
  width: 100%;
  padding: 2px 6px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: rgb(255, 255, 255);
  font-size: 0.9rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.per-option:hover { background: #3a3a3a; }
.per-option:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.per-option[aria-selected="true"] {
  background: rgba(61, 212, 224, 0.16); /* egui selected-fill hint */
}
.per-no-match {
  margin: 4px 0;
  font-style: italic;
  color: rgb(255, 255, 0); /* egui Color32::YELLOW */
}
.per-sep { border: 0; border-top: 1px solid var(--line); margin: 6px 0; }

/* "Enter your persona below:" + the right-aligned copy button (RichText
   size 11 .strong(), min_size 160x18). */
.per-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.per-editor-label { color: var(--text-1); }
.per-copy {
  min-width: 160px;
  min-height: 18px;
  font-size: 11px;
  font-weight: 700;
}

/* The multiline TextEdit: desired_width editor_width-10, hint "Enter
   persona here..."; rows are driven by JS (2 when empty, else lines+2,
   like the app) so resize stays off. */
.per-text {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
  line-height: 1.5;
  resize: none;
}
.per-text::placeholder { color: var(--text-3); }
.per-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The bottom row: "<N> characters" weak italic in the quality colour on
   the left, "📋 Quality Guidance" CollapsingHeader (default closed) in
   the middle, "●" 12px + quality text 11px on the right. */
.per-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.per-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.per-guidance { flex: 1 1 auto; min-width: 200px; }
.per-guidance-summary {
  cursor: pointer;
  color: var(--text-1);
  font-size: 0.9rem;
}
.per-guidance-body {
  margin-top: 6px;
  padding: 8px; /* the app's Frame::none inner_margin 8.0 */
  border: 1px solid var(--line);
  border-radius: 4px;
}
.per-g { margin: 2px 0; font-size: 0.85rem; }
.per-g--green { color: rgb(100, 255, 100); }
.per-g--yellow { color: rgb(255, 255, 100); }
.per-g--tip { color: rgb(150, 150, 255); }
.per-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.per-quality-text { font-size: 11px; color: var(--text-1); }

/* Status line (the app's bottom status bar does not exist inside the
   replica frame — the app's verbatim status strings land here). */
.per-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .persona-preview { max-width: 100%; }
  .per-filter { flex: 1 1 160px; }
  .per-quality-right { margin-left: 0; }
}

/* ----- Session 20: Instructions editor replica (Editors section) ---------
   Mirrors src/main.rs Build 183 (lines 13178-13345): the Instructions
   editor is an INLINE Frame::group in the app's central panel (2px
   rgb(100,100,100) stroke, 10px rounding) — NOT a window — so
   .instr-preview is an inline frame exactly like .persona-preview and
   joined the dark-chrome token group at the top of this file. Unlike the
   Persona editor there is NO library / select row (the app has none for
   Instructions). */

/* The inline editor frame (same pattern + 920px max-width as the Persona
   replica — the app's editor group fills the central panel). */
.instr-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}

/* egui Frame::group: 2px rgb(100,100,100) stroke, Rounding::same(10.0). */
.ins-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02); /* egui group fill hint */
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}

/* The title bar: allocate_ui_with_layout row painted rect_filled
   rgb(50,50,50), rounding 10, 30px high; "Instructions" WHITE size 20. */
.ins-titlebar {
  display: flex;
  align-items: center;
  height: 30px;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.ins-title { color: rgb(255, 255, 255); font-size: 20px; line-height: 1; }
.ins-title-quality { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.ins-quality-icon { font-size: 18px; line-height: 1; }
.ins-quality-dot { font-size: 16px; line-height: 1; }
.ins-quality-dot--bottom { font-size: 12px; }

/* "Enter your instructions below:" + the right-aligned copy button
   (RichText size 11 .strong(), min_size 180x18 — main.rs:13230-13234). */
.ins-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.ins-editor-label { color: var(--text-1); }

/* Dark egui button (same recipe as .per-copy). */
.ins-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 11px;
  font-weight: 700;
  font-family: inherit;
  min-width: 180px;
  min-height: 18px;
  cursor: pointer;
}
.ins-copy:hover { background: #3a3a3a; }
.ins-copy:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* The multiline TextEdit: desired_width editor_width-10, hint "Enter
   instructions here..."; rows are driven by JS (2 when empty, else
   lines+2, like the app) so resize stays off. */
.ins-text {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
  line-height: 1.5;
  resize: none;
}
.ins-text::placeholder { color: var(--text-3); }
.ins-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The bottom row: "<N> characters" weak italic in the quality colour on
   the left, "📋 Quality Guidance" CollapsingHeader (default closed) in
   the middle, "●" 12px + quality text 11px on the right. */
.ins-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.ins-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.ins-guidance { flex: 1 1 auto; min-width: 200px; }
.ins-guidance-summary {
  cursor: pointer;
  color: var(--text-1);
  font-size: 0.9rem;
}
.ins-guidance-body {
  margin-top: 6px;
  padding: 8px; /* the app's Frame::none inner_margin 8.0 */
  border: 1px solid var(--line);
  border-radius: 4px;
}
.ins-g { margin: 2px 0; font-size: 0.85rem; }
.ins-g--green { color: rgb(100, 255, 100); }
.ins-g--yellow { color: rgb(255, 255, 100); }
.ins-g--tip { color: rgb(150, 150, 255); }
.ins-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.ins-quality-text { font-size: 11px; color: var(--text-1); }

/* Status line (the app's bottom status bar does not exist inside the
   replica frame — the app's verbatim status strings land here). */
.ins-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .instr-preview { max-width: 100%; }
  .ins-quality-right { margin-left: 0; }
}

/* ----- Session 21: Context editor replica (Editors section) --------------
   Mirrors src/main.rs Build 183 (lines 13347-13512): the Context editor is
   an INLINE Frame::group in the app's central panel — NOT a window — so
   .context-preview is an inline frame exactly like .instr-preview and
   joined the dark-chrome token group at the top of this file. */

.context-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}

/* egui Frame::group: 2px rgb(100,100,100) stroke, Rounding::same(10.0). */
.ctx-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}

/* The title bar: painted rect_filled rgb(50,50,50), rounding 10, 30px
   high; "Context" WHITE size 20 (main.rs:13356-13371). */
.ctx-titlebar {
  display: flex;
  align-items: center;
  height: 30px;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.ctx-title { color: rgb(255, 255, 255); font-size: 20px; line-height: 1; }
.ctx-title-quality { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.ctx-quality-icon { font-size: 18px; line-height: 1; }
.ctx-quality-dot { font-size: 16px; line-height: 1; }
.ctx-quality-dot--bottom { font-size: 12px; }

/* "Enter your context below:" + the right-aligned copy button (RichText
   size 11 .strong(), min_size 170x18 — main.rs:13399-13403). */
.ctx-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.ctx-editor-label { color: var(--text-1); }
.ctx-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 11px;
  font-weight: 700;
  font-family: inherit;
  min-width: 170px;
  min-height: 18px;
  cursor: pointer;
}
.ctx-copy:hover { background: #3a3a3a; }
.ctx-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The multiline TextEdit (hint "Enter context here..."); rows are driven
   by JS (2 when empty, else lines+2 — main.rs:13421). */
.ctx-text {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
  line-height: 1.5;
  resize: none;
}
.ctx-text::placeholder { color: var(--text-3); }
.ctx-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

.ctx-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.ctx-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.ctx-guidance { flex: 1 1 auto; min-width: 200px; }
.ctx-guidance-summary { cursor: pointer; color: var(--text-1); font-size: 0.9rem; }
.ctx-guidance-body {
  margin-top: 6px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.ctx-g { margin: 2px 0; font-size: 0.85rem; }
.ctx-g--green { color: rgb(100, 255, 100); }
.ctx-g--yellow { color: rgb(255, 255, 100); }
.ctx-g--tip { color: rgb(150, 150, 255); }
.ctx-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.ctx-quality-text { font-size: 11px; color: var(--text-1); }
.ctx-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .context-preview { max-width: 100%; }
  .ctx-quality-right { margin-left: 0; }
}

/* ----- Session 21: Technical Specs editor replica (Editors section) ------
   Mirrors src/main.rs Build 183 (lines 13516-14467): the editor frame is
   the same inline pattern as Context; the Build-129 hardware area, the
   Build-131 enlarged view (a real egui::Window in the app -> a modal
   reusing the Session-11 shell) and the Build-147 CYD helper are new. */

.techspec-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.tsp-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}
.tsp-titlebar {
  display: flex;
  align-items: center;
  height: 30px;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.tsp-title { color: rgb(255, 255, 255); font-size: 20px; line-height: 1; }
.tsp-title-quality { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.tsp-quality-icon { font-size: 18px; line-height: 1; }
.tsp-quality-dot { font-size: 16px; line-height: 1; }
.tsp-quality-dot--bottom { font-size: 12px; }
.tsp-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.tsp-editor-label { color: var(--text-1); }
.tsp-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 11px;
  font-weight: 700;
  font-family: inherit;
  min-width: 190px; /* the app's min_size 190x18 (main.rs:13572) */
  min-height: 18px;
  cursor: pointer;
}
.tsp-copy:hover { background: #3a3a3a; }
.tsp-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tsp-text {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
  line-height: 1.5;
  resize: none;
}
.tsp-text::placeholder { color: var(--text-3); }
.tsp-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The app's ui.separator() between the editor, the hardware area and the
   bottom row. */
.tsp-sep { border: 0; border-top: 1px solid var(--line); margin: 10px 0 5px; }

/* "🔧 Hardware / Development Board Selection" strong 13px + the visuals
   toggle + the right-aligned board count (main.rs:13626-13647). */
.tsp-hw-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 5px;
}
.tsp-hw-title { color: var(--text-1); font-size: 13px; font-weight: 700; }
.tsp-visuals-toggle {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}
.tsp-visuals-toggle:hover { background: #3a3a3a; }
.tsp-visuals-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tsp-hw-count { margin-left: auto; font-size: 11px; color: var(--text-3); }

/* The visuals area: the 200x150 photo / primitive drawing on the left,
   the board info block on the right (main.rs:13651-13855). */
.tsp-hw-visuals {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 15px;
  margin-top: 10px;
}
.tsp-hw-visual { flex: 0 0 auto; width: 200px; height: 150px; }
.tsp-hw-visual svg { display: block; width: 200px; height: 150px; }
.tsp-hw-photo {
  display: block;
  width: 200px;
  height: 150px;
  object-fit: contain;
  background: rgb(20, 26, 34);
  border: 2px solid rgb(100, 100, 100);
  border-radius: 4px;
  cursor: pointer;
}
.tsp-hw-photo:hover { border: 3px solid rgb(100, 200, 255); }
.tsp-hw-photo:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tsp-hw-info { flex: 1 1 240px; min-width: 220px; }
.tsp-hw-info p { margin: 2px 0; }
.tsp-hw-name { font-size: 14px; font-weight: 700; color: rgb(100, 200, 255); }
.tsp-hw-weak { color: var(--text-3); font-size: 11px; }
.tsp-hw-line { color: var(--text-1); font-size: 11px; }
.tsp-hw-display { color: rgb(150, 255, 150); font-size: 11px; }
.tsp-hw-features { color: var(--text-3); font-size: 10px; margin-top: 4px !important; }
.tsp-hw-none { font-size: 14px; font-weight: 700; color: rgb(255, 200, 100); }
.tsp-hw-howto { font-size: 11px; font-weight: 700; color: rgb(100, 255, 100); margin-top: 8px !important; }
.tsp-hw-step { font-size: 11px; color: var(--text-1); }
.tsp-hw-tip { color: rgb(255, 200, 100); font-size: 10px; margin-top: 8px !important; }

/* The filter row (main.rs:13862-13926). */
.tsp-hw-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 5px;
}
.tsp-hw-filter-label { color: var(--text-1); font-size: 0.9rem; }
.tsp-hw-filter {
  width: 200px;
  padding: 4px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
}
.tsp-hw-filter::placeholder { color: var(--text-3); }
.tsp-hw-filter:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.tsp-hw-matches { font-size: 11px; color: rgb(100, 255, 100); }
.tsp-hw-dropdown-btn {
  margin-left: 12px; /* the app's ui.add_space(20.0) before the button */
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: inherit;
  cursor: pointer;
}
.tsp-hw-dropdown-btn:hover { background: #3a3a3a; }
.tsp-hw-dropdown-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The dropdown popup: Frame::popup, 1px rgb(100,100,100) stroke, a
   max-400px vertical ScrollArea (main.rs:13929-13935). */
.tsp-hw-dropdown {
  margin-top: 4px;
  padding: 6px;
  background: var(--bg-1);
  border: 1px solid rgb(100, 100, 100);
  border-radius: 6px;
}
.tsp-hw-list { max-height: 400px; overflow-y: auto; overflow-x: hidden; }
.tsp-hw-cat {
  margin: 6px 0 4px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  font-weight: 700;
  color: rgb(100, 200, 255);
}
.tsp-hw-cat:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.tsp-hw-option {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 3px 6px;
  border: 0;
  border-radius: 3px;
  background: transparent;
  color: var(--text-1);
  font-size: 0.9rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.tsp-hw-option:hover { background: rgba(148, 184, 220, 0.12); }
.tsp-hw-option:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tsp-hw-option[aria-selected="true"] { background: rgba(63, 212, 224, 0.16); }
.tsp-hw-icon { font-size: 16px; line-height: 1; }
.tsp-hw-mini { flex: 0 0 auto; width: 48px; height: 32px; }
.tsp-hw-display-line { margin: 0 0 4px 70px; font-size: 11px; color: var(--text-3); }
.tsp-hw-no-match { margin: 20px 0 10px; font-weight: 700; color: rgb(255, 255, 0); }
.tsp-hw-no-match-tip { margin: 0 0 10px; font-size: 11px; color: var(--text-3); }
.tsp-hw-showing {
  margin: 4px 0;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  color: rgb(100, 255, 100);
}
.tsp-hw-dropdown-close {
  margin-top: 4px;
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}
.tsp-hw-dropdown-close:hover { background: #3a3a3a; }
.tsp-hw-dropdown-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The Build-147 CYD helper: default-closed CollapsingHeader, the
   "Selected:" weak 11px line and the monospace reference body capped at
   360px (main.rs:14251-14280). */
.tsp-cyd { margin-top: 8px; }
.tsp-cyd-summary { cursor: pointer; color: var(--text-1); font-size: 0.9rem; }
.tsp-cyd-selected { margin: 6px 0; font-size: 11px; color: var(--text-3); }
.tsp-cyd-body {
  max-height: 360px;
  overflow-y: auto;
  overflow-x: hidden;
  margin: 0;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
  font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  color: var(--text-1);
}

.tsp-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.tsp-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.tsp-guidance { flex: 1 1 auto; min-width: 200px; }
.tsp-guidance-summary { cursor: pointer; color: var(--text-1); font-size: 0.9rem; }
.tsp-guidance-body {
  margin-top: 6px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.tsp-g { margin: 2px 0; font-size: 0.85rem; }
.tsp-g--green { color: rgb(100, 255, 100); }
.tsp-g--yellow { color: rgb(255, 255, 100); }
.tsp-g--tip { color: rgb(150, 150, 255); }
.tsp-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.tsp-quality-text { font-size: 11px; color: var(--text-1); }
.tsp-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

/* The Build-131 enlarged view window: the app's default_size 600x500
   (main.rs:14307); the photo scales to fit 580x420 (main.rs:14313-14324). */
.tsp-window { width: min(600px, 100%); height: min(560px, 100%); }
.tsp-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 16px;
}
.tsp-enlarged-wrap { margin: 0 0 10px; text-align: center; }
.tsp-enlarged {
  max-width: 580px;
  max-height: 420px;
  width: auto;
  height: auto;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: rgb(20, 26, 34);
}
.tsp-enlarged-info p { margin: 2px 0; font-size: 0.9rem; color: var(--text-1); }
.tsp-close-wrap { margin: 10px 0 0; text-align: right; }

@media (max-width: 900px) {
  .tsp-window { width: 100%; height: 100%; } /* beat the later-source-order
    .tsp-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall) */
  .techspec-preview { max-width: 100%; }
  .tsp-quality-right { margin-left: 0; }
  .tsp-hw-count { margin-left: 0; flex-basis: 100%; }
  .tsp-hw-dropdown-btn { margin-left: 0; }
  .tsp-hw-display-line { margin-left: 54px; }
}

/* ----- Session 21: Format / Audience / Tone editor replicas (Editors) ----
   Mirror src/main.rs Build 183 (Format 14471-14638, Audience 14642-14803,
   Tone 14807-14968). These three sections use the 26px title bar with a
   16px STRONG white title and a TEXT-ONLY quality readout on the right
   ("Quality:" + Good / Needs Work / Poor, 11px, default colour — no
   icon, no "●"), and a FIXED-120px MONOSPACE TextEdit (add_sized). */

.format-preview,
.audience-preview,
.tone-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.fmt-frame,
.aud-frame,
.ton-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}
.fmt-titlebar,
.aud-titlebar,
.ton-titlebar {
  display: flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.fmt-title,
.aud-title,
.ton-title { color: rgb(255, 255, 255); font-size: 16px; font-weight: 700; line-height: 1; }
.fmt-title-quality,
.aud-title-quality,
.ton-title-quality {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-1);
}
.fmt-editor-label-row,
.aud-editor-label-row,
.ton-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.fmt-editor-label,
.aud-editor-label,
.ton-editor-label { color: var(--text-1); }
.fmt-copy,
.aud-copy,
.ton-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 11px;
  font-weight: 700;
  font-family: inherit;
  min-height: 18px;
  cursor: pointer;
}
.fmt-copy { min-width: 170px; } /* main.rs:14524 */
.aud-copy { min-width: 175px; } /* main.rs:14691 */
.ton-copy { min-width: 165px; } /* main.rs:14856 */
.fmt-copy:hover,
.aud-copy:hover,
.ton-copy:hover { background: #3a3a3a; }
.fmt-copy:focus-visible,
.aud-copy:focus-visible,
.ton-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fmt-text,
.aud-text,
.ton-text {
  display: block;
  width: 100%;
  height: 120px; /* the app's add_sized([w, 120.0]) */
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  font-family: ui-monospace, Consolas, "Courier New", monospace; /* TextStyle::Monospace */
  line-height: 1.5;
  resize: none;
}
.fmt-text::placeholder,
.aud-text::placeholder,
.ton-text::placeholder { color: var(--text-3); }
.fmt-text:focus,
.aud-text:focus,
.ton-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.fmt-bottom-row,
.aud-bottom-row,
.ton-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.fmt-chars,
.aud-chars,
.ton-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.fmt-guidance,
.aud-guidance,
.ton-guidance { flex: 1 1 auto; min-width: 200px; }
.fmt-guidance-summary,
.aud-guidance-summary,
.ton-guidance-summary { cursor: pointer; color: var(--text-1); font-size: 0.9rem; }
.fmt-guidance-body,
.aud-guidance-body,
.ton-guidance-body {
  margin-top: 6px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.fmt-g,
.aud-g,
.ton-g { margin: 2px 0; font-size: 0.85rem; }
.fmt-g--green,
.aud-g--green,
.ton-g--green { color: rgb(100, 255, 100); }
.fmt-g--yellow,
.aud-g--yellow,
.ton-g--yellow { color: rgb(255, 255, 100); }
.fmt-g--tip,
.aud-g--tip,
.ton-g--tip { color: rgb(150, 150, 255); }
.fmt-quality-right,
.aud-quality-right,
.ton-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.fmt-quality-dot,
.aud-quality-dot,
.ton-quality-dot { font-size: 12px; line-height: 1; }
.fmt-quality-text,
.aud-quality-text,
.ton-quality-text { font-size: 11px; color: var(--text-1); }
.fmt-status,
.aud-status,
.ton-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .format-preview,
  .audience-preview,
  .tone-preview { max-width: 100%; }
  .fmt-quality-right,
  .aud-quality-right,
  .ton-quality-right { margin-left: 0; }
}

/* ----- Session 22: Data / Example(s) / Graphics / MCP Servers / Agents ---
   Mirror src/main.rs Build 183 (14972-15721 + draw_editor_block 7488-7700).
   Data = 26px-bar variant (strong 16px title, "Quality:" text, no icon) +
   fixed-120px monospace TextEdit; the other four = 30px-bar variant (20px
   title, icon + "●") + dynamic-rows TextEdits; Graphics has NO copy button. */

.data-preview,
.examples-preview,
.graphics-preview,
.mcp-preview,
.agents-preview {
  position: relative;
  margin: 0 auto;
  max-width: 920px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.dat-frame,
.exa-frame,
.gfx-frame,
.mcp-frame,
.agt-frame {
  padding: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 2px solid rgb(100, 100, 100);
  border-radius: 10px;
}
.dat-titlebar,
.exa-titlebar,
.gfx-titlebar,
.mcp-titlebar,
.agt-titlebar {
  display: flex;
  align-items: center;
  padding: 0 10px;
  background: rgb(50, 50, 50);
  border-radius: 10px;
}
.dat-titlebar { height: 26px; }
.exa-titlebar,
.gfx-titlebar,
.mcp-titlebar,
.agt-titlebar { height: 30px; }
.dat-title,
.exa-title,
.gfx-title,
.mcp-title,
.agt-title { color: rgb(255, 255, 255); line-height: 1; }
.dat-title { font-size: 16px; font-weight: 700; }
.exa-title,
.gfx-title,
.mcp-title,
.agt-title { font-size: 20px; }
.dat-title-quality,
.exa-title-quality,
.gfx-title-quality,
.mcp-title-quality,
.agt-title-quality {
  margin-left: auto;
  display: flex;
  align-items: center;
  color: var(--text-1);
}
.dat-title-quality { gap: 8px; font-size: 11px; }
.exa-title-quality,
.gfx-title-quality,
.mcp-title-quality,
.agt-title-quality { gap: 5px; }
.exa-quality-icon,
.gfx-quality-icon,
.mcp-quality-icon,
.agt-quality-icon { font-size: 18px; line-height: 1; }
.exa-quality-dot,
.gfx-quality-dot,
.mcp-quality-dot,
.agt-quality-dot { font-size: 16px; line-height: 1; }
.dat-quality-dot--bottom,
.exa-quality-dot--bottom,
.gfx-quality-dot--bottom,
.mcp-quality-dot--bottom,
.agt-quality-dot--bottom { font-size: 12px; }
.dat-editor-label-row,
.exa-editor-label-row,
.gfx-editor-label-row,
.mcp-editor-label-row,
.agt-editor-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.dat-editor-label,
.exa-editor-label,
.gfx-editor-label,
.mcp-editor-label,
.agt-editor-label { color: var(--text-1); }
.dat-copy,
.exa-copy,
.mcp-copy,
.agt-copy {
  padding: 4px 10px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 11px;
  font-weight: 700;
  font-family: inherit;
  min-height: 18px;
  cursor: pointer;
}
.dat-copy { min-width: 160px; } /* main.rs:15021 */
.exa-copy { min-width: 185px; } /* main.rs:15202 */
.mcp-copy { min-width: 195px; } /* main.rs:15411 */
.agt-copy { min-width: 175px; } /* main.rs:15600 */
.dat-copy:hover,
.exa-copy:hover,
.mcp-copy:hover,
.agt-copy:hover { background: #3a3a3a; }
.dat-copy:focus-visible,
.exa-copy:focus-visible,
.mcp-copy:focus-visible,
.agt-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dat-text,
.exa-text,
.gfx-text,
.mcp-text,
.agt-text {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid #323232;
  border-radius: 4px;
  background: #2d2d2d;
  color: #f5f5f5;
  font-size: 0.9rem;
  line-height: 1.5;
  resize: none;
}
.dat-text {
  height: 120px; /* the app's add_sized([w, 120.0]) — main.rs:15045 */
  font-family: ui-monospace, Consolas, "Courier New", monospace; /* TextStyle::Monospace */
}
.exa-text,
.gfx-text,
.mcp-text,
.agt-text { font-family: inherit; }
.dat-text::placeholder,
.exa-text::placeholder,
.mcp-text::placeholder,
.agt-text::placeholder { color: var(--text-3); }
.dat-text:focus,
.exa-text:focus,
.gfx-text:focus,
.mcp-text:focus,
.agt-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.dat-bottom-row,
.exa-bottom-row,
.gfx-bottom-row,
.mcp-bottom-row,
.agt-bottom-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 4px;
}
.dat-chars,
.exa-chars,
.gfx-chars,
.mcp-chars,
.agt-chars { font-style: italic; opacity: 0.75; font-size: 0.875rem; }
.dat-guidance,
.exa-guidance,
.gfx-guidance,
.mcp-guidance,
.agt-guidance { flex: 1 1 auto; min-width: 200px; }
.dat-guidance-summary,
.exa-guidance-summary,
.gfx-guidance-summary,
.mcp-guidance-summary,
.agt-guidance-summary { cursor: pointer; color: var(--text-1); font-size: 0.9rem; }
.dat-guidance-body,
.exa-guidance-body,
.gfx-guidance-body,
.mcp-guidance-body,
.agt-guidance-body {
  margin-top: 6px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.dat-g,
.exa-g,
.gfx-g,
.mcp-g,
.agt-g { margin: 2px 0; font-size: 0.85rem; }
.dat-g--green,
.exa-g--green,
.gfx-g--green,
.mcp-g--green,
.agt-g--green { color: rgb(100, 255, 100); }
.dat-g--yellow,
.exa-g--yellow,
.gfx-g--yellow,
.mcp-g--yellow,
.agt-g--yellow { color: rgb(255, 255, 100); }
.dat-g--tip,
.exa-g--tip,
.gfx-g--tip,
.mcp-g--tip,
.agt-g--tip { color: rgb(150, 150, 255); }
.dat-quality-right,
.exa-quality-right,
.gfx-quality-right,
.mcp-quality-right,
.agt-quality-right { margin-left: auto; display: flex; align-items: center; gap: 5px; }
.dat-quality-text,
.exa-quality-text,
.gfx-quality-text,
.mcp-quality-text,
.agt-quality-text { font-size: 11px; color: var(--text-1); }
.dat-status,
.exa-status,
.mcp-status,
.agt-status {
  margin: 8px 0 0;
  min-height: 1.2em;
  font-size: 0.8rem;
  color: var(--text-2);
}

@media (max-width: 900px) {
  .data-preview,
  .examples-preview,
  .graphics-preview,
  .mcp-preview,
  .agents-preview { max-width: 100%; }
  .dat-quality-right,
  .exa-quality-right,
  .gfx-quality-right,
  .mcp-quality-right,
  .agt-quality-right { margin-left: 0; }
}

/* ===== Session 23: hero Copy/Preview row + "Content Preview" window =======
   Mirrors src/main.rs Build 183: the "📋 Copy to Clipboard" / "👁 Preview"
   row (lines 12183-12215 — 12px STRONG labels, min 130x20 / 100x20) and the
   egui::Window "Content Preview" (lines 15853-15937: default 800x600,
   min-height 400; lead 16px strong; read-only MONOSPACE text; dark bottom
   bar rgb(40,40,40) with the YELLOW 16px "◆ Copy to Clipboard" min 200x32
   and the right-aligned YELLOW "Press Escape to close this preview").
   .cpb-modal REUSES the Session-11 .manual-* shell; .cpb-preview (inline
   hero frame) and .cpb-modal joined the dark-token group at the top. */
.cpb-preview {
  max-width: 720px;
  margin: 0 auto 1.5rem;
  padding: 14px 16px 10px;
  text-align: center;
  background: var(--surface);      /* dark, via the token group */
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.cpb-row { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.cpb-btn {
  min-width: 130px;
  min-height: 32px;
  padding: 4px 14px;
  border: 1px solid #323232; /* OUTLINE, like the app's dark buttons */
  border-radius: 8px;
  background: #2d2d2d;       /* DARK_BUTTON rgb(45,45,45) */
  color: #f5f5f5;            /* STEP_WHITE rgb(245,245,245) */
  font-size: 0.75rem;        /* the app's 12pt label */
  font-weight: 700;          /* .strong() */
  cursor: pointer;
}
.cpb-btn:hover { background: #3a3a3a; }
#cpb-preview { min-width: 100px; } /* the app's min 100x20 for Preview */
.cpb-status {
  margin: 8px 0 0;
  min-height: 1.4em;
  font-size: 0.85rem;
  color: var(--accent);
}
.cpb-status:empty { margin: 0; min-height: 0; }

.cpb-window {
  width: min(800px, 100%);   /* the app's default_size [800, 600] */
  height: min(600px, 100%);
  min-height: 400px;         /* the app's .min_height(400.0) */
}
.cpb-lead {
  margin: 0;
  padding: 12px 12px 0;
  font-size: 1rem;           /* 16px, .strong() in the app */
  color: var(--text-1);
}
.cpb-text {
  flex: 1 1 auto;
  min-height: 0;
  margin: 10px 12px;
  padding: 10px 12px;
  overflow-y: auto;
  white-space: pre-wrap;
  font-family: var(--font-mono); /* egui::TextStyle::Monospace */
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-1);
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.cpb-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 12px 10px;
  padding: 5px 10px;           /* inner_margin symmetric(10.0, 5.0) */
  background: rgb(40, 40, 40); /* the app's dark button area */
  border-radius: var(--r-sm);
}
.cpb-bar-copy {
  min-width: 200px;
  min-height: 32px;
  padding: 2px 12px;
  border: 1px solid #323232;
  border-radius: 8px;
  background: #2d2d2d;
  color: #ffff00;              /* egui Color32::YELLOW text */
  font-size: 1rem;             /* 16px in the app */
  cursor: pointer;
}
.cpb-bar-copy:hover { background: #3a3a3a; }
.cpb-bar-hint {
  margin-left: auto;           /* the app's right_to_left(Align::Center) */
  color: #ffff00;              /* Color32::YELLOW */
  font-size: 0.85rem;
}

@media (max-width: 900px) {
  .cpb-window { width: 100%; height: 100%; } /* beat the later-source-order
    .cpb-window size rule, same full-bleed as .manual-window (Session-12
    specificity pitfall) */
  .cpb-bar { flex-direction: column; align-items: stretch; }
  .cpb-bar-hint { margin-left: 0; text-align: right; }
}


/* ===== Session 24: vertical message carousel (top of the home page) ======
   Jacques's brief: a VERTICAL carousel for messages — the messages go UP
   instead of left/right. One very-high-contrast message box with an UP
   arrow button on its LEFT and a DOWN arrow button on its RIGHT.
   Hardcoded #000 / #ffff00 / #fff (NOT theme tokens): the box must be
   maximum contrast on the light page (21:1 and 19.56:1, WCAG AAA).
   No-JS state = a normal stacked list (all messages readable); JS adds
   .vmsg--js -> fixed-height viewport + transform-only sliding track. */
.vmsg {
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: 880px;
  margin: 0 auto 20px;
}
.vmsg-arrow {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 3px solid #ffff00;
  border-radius: 50%;
  background: #000000;
  color: #ffff00;              /* 19.56:1 on #000 — WCAG AAA */
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.vmsg-arrow:hover { background: #ffff00; color: #000000; } /* invert */
.vmsg-arrow:focus-visible {
  outline: 3px solid #000000;  /* against the light page, outside the button */
  outline-offset: 3px;
}
.vmsg-box {
  flex: 1 1 auto;
  min-width: 0;
  background: #000000;
  border: 3px solid #ffff00;
  border-radius: 10px;
  padding: 0 14px;
}
.vmsg-track {
  list-style: none;
  margin: 0;
  padding: 0;
}
.vmsg-item {
  padding: 12px 4px;
  color: #ffffff;              /* 21:1 on #000 — WCAG AAA */
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1.35;
  text-align: center;
}

/* JS-enhanced mode: the box becomes a fixed-height viewport (height set
   inline by messages.js to the tallest message) and the track slides
   vertically with a transform-only transition (no layout thrash). */
.vmsg--js .vmsg-box { overflow: hidden; }
.vmsg--js .vmsg-track {
  height: 100%;
  transition: transform 0.6s ease;
}
.vmsg--js .vmsg-item {
  height: 100%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
}

@media (prefers-reduced-motion: reduce) {
  .vmsg--js .vmsg-track { transition: none; } /* messages.js also stops
    the 12 s clock under the same media query */
}

@media (max-width: 900px) {
  .vmsg { gap: 8px; }
  .vmsg-arrow { width: 44px; height: 44px; font-size: 1.05rem; }
  .vmsg-item { font-size: 0.95rem; }
}



/* ==========================================================================
   Session 28: "Learning" main-nav tab -> #learning-center anchor + attention
   flash on the Open Learning Center button.
   #learning-center is a .fn-demo div (not a section), so the global
   section[id] scroll-margin doesn't cover it — same 80px clearance as
   #pew-demo. .learn-flash is toggled by app.js section (ae) ONLY when the
   page arrives at /#learning-center: a seizure-safe box-shadow ripple ring
   (no luminance flash, no layout shift) plus a steady accent outline that
   stays on while the ripple runs. Reduced motion: ripple OFF, the static
   outline + soft ring stay so the target is still unmistakable.
   ========================================================================== */
#learning-center { scroll-margin-top: calc(var(--header-h) + 16px); }

/* Session 67: the "Teach" main-nav tab points at /#teach, the ClassRoom
   Presentation fn-demo card. It is a .fn-demo div too, so it needs the same
   80 px clearance as #learning-center; .teach-flash is the 1:1 twin of
   .learn-flash (app.js section (ag) part 2). */
#teach { scroll-margin-top: calc(var(--header-h) + 16px); }

.teach-flash {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  animation: teachFlashRing 1.4s ease-out infinite;
}
@keyframes teachFlashRing {
  0%   { box-shadow: 0 0 0 0 rgba(12, 106, 132, 0.55); }
  70%  { box-shadow: 0 0 0 14px rgba(12, 106, 132, 0); }
  100% { box-shadow: 0 0 0 14px rgba(12, 106, 132, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .teach-flash {
    animation: none;
    box-shadow: 0 0 0 6px rgba(12, 106, 132, 0.25);
  }
}

.learn-flash {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  animation: learnFlashRing 1.4s ease-out infinite;
}
@keyframes learnFlashRing {
  0%   { box-shadow: 0 0 0 0 rgba(12, 106, 132, 0.55); }
  70%  { box-shadow: 0 0 0 14px rgba(12, 106, 132, 0); }
  100% { box-shadow: 0 0 0 14px rgba(12, 106, 132, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .learn-flash {
    animation: none;
    box-shadow: 0 0 0 6px rgba(12, 106, 132, 0.25);
  }
}

/* ==========================================================================
   Session 35: Arabic (ar) RTL — page-level chrome mirrors; replica internals
   stay LTR (the app demos simulate the English-only Windows app 1:1, and
   flexbox would otherwise auto-mirror them). All rules are scoped under
   html[dir="rtl"], which ONLY the Arabic pages carry (the builder emits it),
   so the other 14 languages are byte-for-byte unaffected.
   The mirrors: the skip-link sits top-right; the lang-switcher separator
   flips to the leading side; the switcher dropdown aligns to the left edge
   (the switcher sits at the far LEFT of the flipped header row); ordered
   .steps indentation goes to the right; the plan "Most popular" badge moves
   to the right edge of the card; external-link arrows in the footer lead the
   text. Replica roots (.app-preview, .pew-preview, .cpb-preview, the twelve
   editor .*-preview frames, the .ide/.model/.per/.tsp-hw dropdowns and the
   .manual-modal/.manual-window shells incl. their apil/cmd/cpb/classroom/learn/
   pfx/tips/tsp variants) are pinned direction:ltr — their English menu bars and
   windows must not mirror on Arabic pages.
   ========================================================================== */
html[dir="rtl"] .skip-link { left: auto; right: 16px; }
html[dir="rtl"] .lang-switcher {
  margin-left: 0;
  padding-left: 0;
  border-left: none;
  margin-right: 8px;
  padding-right: 12px;
  border-right: 1px solid var(--line);
}
html[dir="rtl"] .lang-list { right: auto; left: 0; }
html[dir="rtl"] .steps { padding-left: 0; padding-right: 22px; }
html[dir="rtl"] .plan-badge { left: auto; right: 20px; }
html[dir="rtl"] .footer-col a[target="_blank"]::after { margin-left: 0; margin-right: 4px; }
html[dir="rtl"] .app-preview,
html[dir="rtl"] .pew-preview,
html[dir="rtl"] .cpb-preview,
html[dir="rtl"] .persona-preview,
html[dir="rtl"] .instr-preview,
html[dir="rtl"] .context-preview,
html[dir="rtl"] .techspec-preview,
html[dir="rtl"] .format-preview,
html[dir="rtl"] .audience-preview,
html[dir="rtl"] .tone-preview,
html[dir="rtl"] .data-preview,
html[dir="rtl"] .examples-preview,
html[dir="rtl"] .graphics-preview,
html[dir="rtl"] .mcp-preview,
html[dir="rtl"] .agents-preview,
html[dir="rtl"] .ide-preview,
html[dir="rtl"] .model-preview,
html[dir="rtl"] .pfx-preview,
html[dir="rtl"] .manual-modal,
html[dir="rtl"] .manual-window,
html[dir="rtl"] .classroom-modal,
html[dir="rtl"] .classroom-window,
html[dir="rtl"] .ide-dropdown,
html[dir="rtl"] .model-dropdown,
html[dir="rtl"] .per-dropdown,
html[dir="rtl"] .tsp-hw-dropdown { direction: ltr; }

/* ==========================================================================
   Session 44: References page (.ref-*) — the "Model / Commands (reference)"
   page. A responsive card grid, one card per model family, each with a
   "Show <Family> / Commands" button that opens the shared .cmd-modal window
   (the Session-16 shell reused on references.html). Light-theme friendly
   (the page is light; only the modal is dark chrome). */
.ref-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin: 24px 0;
}

.ref-card {
  border: 1px solid var(--border-1, rgba(0, 0, 0, 0.12));
  border-radius: 10px;
  padding: 14px 16px 16px;
  background: var(--bg-1, #ffffff);
}

.ref-name {
  margin: 0 0 6px;
  font-size: 1.02rem;
}

.ref-desc {
  margin: 0 0 12px;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--text-2, #444);
}

.ref-card .manual-open-btn {
  width: 100%;
  text-align: center;
}

.ref-note {
  font-size: 0.9rem;
  color: var(--text-2, #444);
  border-top: 1px solid var(--border-1, rgba(0, 0, 0, 0.12));
  padding-top: 14px;
}

@media (max-width: 640px) {
  .ref-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Session 45 — "The Gift of the Future" modal + Subscribe band.
   The gift modal is SITE copy (translatable, light-theme surface) — unlike
   the .manual-modal demo shells it deliberately does NOT join the dark
   chrome token group. It reuses the same fixed-overlay pattern with its own
   classes (.gift-*) so the i18n extractor sees it (manual-modal is in the
   SKIP_CLASSES set and would be frozen English).
   ========================================================================== */

/* ---- Gift modal --------------------------------------------------------- */
.gift-modal {
  position: fixed;
  inset: 0;
  z-index: 210; /* above demo modals (200) — it can be opened from /pricing */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vh 3vw;
}
.gift-modal[hidden] { display: none; }
.gift-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 8, 14, 0.66); /* hardcoded: overlay sits on the page */
}
.gift-window {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 92vh;
  overflow-y: auto;
  background: #faf8f1;          /* light site surface, not dark chrome */
  color: #182230;
  border: 1px solid #e3ddcc;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  padding: 28px 24px;
}
.gift-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid #e3ddcc;
  border-radius: var(--r-sm);
  background: transparent;
  color: #182230;
  font-size: 0.9rem;
  cursor: pointer;
}
.gift-close:hover { background: #efe9da; }
.gift-title { margin: 0 0 6px; font-size: 1.35rem; }
.gift-intro { margin: 0 0 18px; color: #4a5568; line-height: 1.55; }
.gift-fieldset {
  border: 1px solid #e3ddcc;
  border-radius: var(--r-sm);
  padding: 14px 16px 16px;
  margin: 0 0 14px;
}
.gift-fieldset legend { padding: 0 6px; font-weight: 650; font-size: 0.9rem; }
.gift-fieldset label {
  display: block;
  margin-bottom: 10px;
  font-size: 0.875rem;
  color: #33404f;
}
.gift-row { display: flex; gap: 12px; }
.gift-row label { flex: 1 1 0; min-width: 0; }
.gift-note { font-size: 0.8125rem; color: #4a5568; margin: 0 0 14px; }
.gift-window .plan-status { margin-top: 10px; min-height: 1.2em; }

/* ---- Buyer-details modal (Session 46) ----------------------------------- */
/* Same fixed-overlay pattern as the gift modal with its own .buyer-*
   classes so the i18n extractor sees the copy (manual-modal is in the
   SKIP_CLASSES set and would be frozen English). */
.buyer-modal {
  position: fixed;
  inset: 0;
  z-index: 210; /* above demo modals (200) — it can be opened from /pricing */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vh 3vw;
}
.buyer-modal[hidden] { display: none; }
.buyer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 8, 14, 0.66); /* hardcoded: overlay sits on the page */
}
.buyer-window {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 92vh;
  overflow-y: auto;
  background: #faf8f1;          /* light site surface, not dark chrome */
  color: #182230;
  border: 1px solid #e3ddcc;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  padding: 28px 24px;
}
.buyer-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid #e3ddcc;
  border-radius: var(--r-sm);
  background: transparent;
  color: #182230;
  font-size: 0.9rem;
  cursor: pointer;
}
.buyer-close:hover { background: #efe9da; }
.buyer-title { margin: 0 0 6px; font-size: 1.35rem; }
.buyer-intro { margin: 0 0 18px; color: #4a5568; line-height: 1.55; }
.buyer-fieldset {
  border: 1px solid #e3ddcc;
  border-radius: var(--r-sm);
  padding: 14px 16px 16px;
  margin: 0 0 14px;
}
.buyer-fieldset legend { padding: 0 6px; font-weight: 650; font-size: 0.9rem; }
.buyer-fieldset label {
  display: block;
  margin-bottom: 10px;
  font-size: 0.875rem;
  color: #33404f;
}
.buyer-row { display: flex; gap: 12px; }
.buyer-row label { flex: 1 1 0; min-width: 0; }
.buyer-optin {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 0.875rem;
  color: #33404f;
  cursor: pointer;
}
.buyer-optin input { margin-top: 2px; }
.buyer-optin-helper { font-size: 0.8125rem; color: #4a5568; margin: 0 0 12px; }
/* Session 47: the untick consequence line (Jacques's sentence). Calm amber,
   not red — a notice, not an alarm, at the payment moment; #8a4b08 on the
   modal's #fff surface = 5.9:1 (WCAG AA). */
.buyer-optin-warning { font-size: 0.8125rem; color: #8a4b08; margin: -6px 0 12px; }
.buyer-note { font-size: 0.8125rem; color: #4a5568; margin: 12px 0 14px; }
.buyer-window .plan-status { margin-top: 10px; min-height: 1.2em; }

/* ---- Subscribe band ------------------------------------------------------ */
.subscribe-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
.subscribe-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 24px 20px;
}
.subscribe-title { margin: 0 0 6px; font-size: 1.1rem; }
.subscribe-desc { margin: 0 0 14px; color: var(--text-2); font-size: 0.9rem; }
.subscribe-form label {
  display: block;
  margin-bottom: 10px;
  font-size: 0.875rem;
  color: var(--text-2);
}
.subscribe-form .field { width: 100%; }
.subscribe-status { margin-top: 10px; min-height: 1.2em; }

@media (max-width: 900px) {
  .subscribe-grid { grid-template-columns: 1fr; }
  .gift-row { flex-direction: column; gap: 0; }
  .buyer-row { flex-direction: column; gap: 0; }
}

/* ----- Session 60: expand hint (right of headings) + "Used By" logo wall -- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Heading + right-aligned expand hint. */
.section-head,
.gallery-tab-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.gallery-tab-head { margin-bottom: 0.5rem; }
.gallery-tab-head .gallery-tab-title { margin-bottom: 0; }

.expand-hint,
.try-hint {
  color: var(--text-3);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--text-3);
  border-radius: 999px;
  white-space: nowrap;
  opacity: 0.9;
}

/* "Used By" logo wall — rightward marquee, ~1 logo per second. */
.used-by-intro {
  color: var(--text-2);
  font-size: 1.125rem;
  max-width: 62ch;
  margin-bottom: 2rem;
}
.used-by-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.used-by-track {
  display: flex;
  width: max-content;
  animation: used-by-scroll 56s linear infinite;
}
.used-by-list {
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0;
  list-style: none;
}
.logo-item {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  /* Session 61: brand colour is set inline per logo (style="color:#HEX");
     --text-3 remains the fallback for any logo without an inline colour. */
  color: var(--text-3);
  opacity: 0.9;
  margin-right: 3rem;
}
.logo-icon { width: 1.75rem; height: 1.75rem; }
.logo-item--word .logo-wordmark {
  font-family: var(--font-ui);
  font-size: 1.05rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
@keyframes used-by-scroll {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}
/* WCAG 2.2.2 Pause/Stop/Hide: pause the marquee on hover and keyboard focus. */
.used-by-marquee:hover .used-by-track,
.used-by-marquee:focus-within .used-by-track {
  animation-play-state: paused;
}
@media (prefers-reduced-motion: reduce) {
  .used-by-track { animation: none; }
}


/* Build 291: Family + Business plans launch later — hidden from Pricing. */
.plan-card--hidden { display: none !important; }

/* ----- (ag) Estimate-for header (Session 62) ----- */
.est-geo { display: block; margin-top: 0.4rem; font-size: 0.92rem; color: var(--muted, #64748b); font-weight: 500; }
.est-geo[hidden] { display: none; }

/* ----- Feedback form (pricing#feedback) ----------------------------------- */
.feedback-form {
  max-width: 620px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.feedback-form .field { width: 100%; }
.feedback-form .field--area { min-height: 160px; }
.feedback-form .btn { align-self: flex-start; margin-top: 16px; }
.feedback-optional { color: var(--text-3); font-weight: 400; }
.feedback-consent {
  color: var(--text-3);
  font-size: 0.8125rem;
  margin: 12px 0 0;
}
.feedback-status {
  margin-top: 10px;
  min-height: 1.2em;
  color: var(--text-2);
}
.feedback-success {
  color: var(--text-1);
  font-weight: 600;
}

/* Session 31: Papers CTA band — clickable science-references entry points */
.papers-band {
  margin: 0 auto;
  padding: 34px 16px 10px;
  max-width: 1100px;
  text-align: center;
}
.papers-band-title {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 6px;
}
.papers-band-sub {
  color: var(--text-2);
  margin: 0 0 14px;
  font-size: .92rem;
}
.papers-band-links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
.papers-band-links .btn { margin: 0; }
@media (max-width: 640px) { .papers-band { padding: 26px 12px 6px; } }

.papers-band--top {
  max-width: 1200px;
  margin: 0 auto;
  padding: 18px 16px 6px;
}
.papers-band--top .papers-band-title { font-size: .95rem; margin: 0 0 8px; }
.papers-band--top .papers-band-links { margin: 0; }

/* S31b: single randomized Papers CTA sprinkled through page content */
.papers-cta-row { text-align: center; margin: 28px auto 10px; }
.papers-cta-row .btn { margin: 0; }
