/* AUTO-GENERATED by scripts/sync-quarto-assets.sh — DO NOT EDIT.
 * Source: crates/core/assets/shared/styles.css
 * Scoped under .bt-exercise for Quarto extension isolation.
 * Run sync-quarto-assets.sh to regenerate. */

/* blendtutor design tokens + semantic layout shell
 *
 * This file defines the --bt- design-token system and semantic region rules
 * shared by both webR and Pyodide target shells. It is embedded at compile
 * time via include_str! in crates/core/src/site/mod.rs and referenced by
 * both index.html shells via <link rel="stylesheet" href="styles.css">.
 *
 * What it does:
 *  - Declares all --bt- custom properties in :root (typography, color, spacing,
 *    radii) — the single source of truth for cross-target visual vocabulary.
 *  - Overrides all --bt-color-* tokens inside @media (prefers-color-scheme: dark)
 *    for WCAG AA dark-mode contrast (4.5:1 text, 3:1 UI / large text).
 *  - Styles the page shell: <header.site-header>, <main.workspace>,
 *    <footer.site-footer>, <body>, <h1> — the foundation AC-2 and AC-3 build on.
 *
 * What it does NOT do:
 *  - No component-level styles for the workspace internals (textarea, controls,
 *    output, feedback panel) — AC-2 and AC-3 own those regions.
 *  - No eval-results styling.
 *
 * Token contract for AC-2 (workspace styling):
 *   --bt-font-family-code, --bt-color-surface-code, --bt-color-status-*,
 *   --bt-radius-*, --bt-space-*
 *
 * Token contract for AC-3 (BYOK feedback panel styling):
 *   --bt-color-text-*, --bt-radius-*, --bt-font-family-ui, --bt-space-*
 */

/* ── Design tokens ─────────────────────────────────────────────── */

:root {
  /* Typography */
  --bt-font-family-ui: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --bt-font-family-code: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  --bt-font-size-base: 1rem;
  --bt-line-height: 1.5;
  /* Colors — light theme */
  --bt-color-surface: #ffffff;
  --bt-color-surface-code: #f5f5f5;
  --bt-color-text-primary: #1a1a1a;
  --bt-color-text-secondary: #555555;
  --bt-color-status-pass: #0a7d28;
  --bt-color-status-fail: #c0202a;
  --bt-color-status-running: #b06a00;
  --bt-color-brand: #1a1a1a;
  --bt-color-brand-hover: #000000;
  --bt-color-border: #d4d4d4;
  --bt-color-status-idle: #e8e8e8;
  /* Spacing */
  --bt-space-page-width: 50rem;
  --bt-space-xs: 0.25rem;
  --bt-space-sm: 0.5rem;
  --bt-space-md: 0.75rem;
  --bt-space-lg: 1rem;
  /* Shadows */
  --bt-shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
  /* Radii */
  --bt-radius-sm: 0.25rem;
  --bt-radius-md: 0.5rem;
  --bt-radius-pill: 9999px;
  /* AC-3: BYOK verdict tint backgrounds — distinct from status-pass/fail accents */
  --bt-color-success-bg: #e8f5e9;
  --bt-color-danger-bg: #fff3e0;
  /* Syntax highlighting token colors — CM6 default light-theme palette. Used
  * by the custom HighlightStyle's `.tok-*` classes (lesson-runner-core.js).
  * Distinct from the status/surface vocabulary; a fixed syntax palette. Dark-
  * mode overrides in the @media block below use a VS Code dark-theme palette. */
  --bt-color-syntax-keyword: #055;
  --bt-color-syntax-string: #a11;
  --bt-color-syntax-number: #708;
  --bt-color-syntax-comment: #6a6a6a;
  --bt-color-syntax-variable: #000;
  --bt-color-syntax-function: #30a;
  --bt-color-syntax-operator: #000;
  /* Cursor — dark on light background (same as CM6 default black). The
  * dark-mode override sets this to #ffffff for maximum contrast. */
  --bt-color-cursor: #1a1a1a;
}

/* ── Semantic region rules ─────────────────────────────────────── */

.bt-exercise {
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  line-height: var(--bt-line-height);
  color: var(--bt-color-text-primary);
  background: var(--bt-color-surface);
}

.bt-exercise header.site-header {
  display: flex;
  align-items: baseline;
  gap: var(--bt-space-md);
  padding: var(--bt-space-lg) 0;
  border-bottom: 1px solid var(--bt-color-border);
  margin-bottom: var(--bt-space-lg);
}

.bt-exercise header.site-header h1 {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--bt-color-brand);
  margin: 0;
}

.bt-exercise header.site-header #boot-status {
  font-size: 0.875rem;
  color: var(--bt-color-text-secondary);
  margin: 0;
}

.bt-exercise main.workspace {
  flex: 1;
  padding-bottom: var(--bt-space-lg);
}

.bt-exercise footer.site-footer {
  padding: var(--bt-space-lg) 0;
  border-top: 1px solid var(--bt-color-border);
  font-size: 0.75rem;
  color: var(--bt-color-text-secondary);
  text-align: center;
}

/* === static fallback (progressive enhancement) === */

/* Server-rendered static exercise content (title + prompt + code template +
 * hints/gotchas) emitted by the blendtutor filter INSIDE each div.bt-exercise
 * before the payload script (fix-demo-visible-exercises Part 1). Visible when
 * JS never runs: file:// CORS-blocks the ES-module bootstrap, JS disabled,
 * or a slow CDN. The runtime (exercise-runtime.js) REMOVES this block when it
 * mounts the interactive editor, so over HTTP these rules apply only for the
 * brief boot window — the static content degrades gracefully to readable
 * prose otherwise. Styled with the existing --bt-* tokens (no new colors). */

.bt-exercise .bt-exercise-static {
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-md);
  margin-bottom: var(--bt-space-md);
  background: var(--bt-color-surface-code);
}

.bt-exercise .bt-exercise-static .bt-static-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--bt-color-text-primary);
  margin: 0 0 var(--bt-space-sm);
}

.bt-exercise .bt-exercise-static .bt-static-prompt {
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
  margin-bottom: var(--bt-space-md);
}

/* ADR-0021: the prompt the runtime keeps after removing the static fallback.
 * Same rhythm as the fallback prompt, primary color: these are the live
 * instructions, not fallback prose. */

.bt-exercise .bt-prompt {
  color: var(--bt-color-text-primary);
  line-height: var(--bt-line-height);
  margin-bottom: var(--bt-space-md);
}

.bt-exercise .bt-exercise-static pre.bt-static-code {
  font-family: var(--bt-font-family-code);
  font-size: var(--bt-font-size-base);
  line-height: var(--bt-line-height);
  color: var(--bt-color-text-primary);
  background: var(--bt-color-surface);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-sm);
  overflow: auto;
  margin: 0 0 var(--bt-space-md);
  white-space: pre;
}

.bt-exercise .bt-exercise-static details {
  margin-bottom: var(--bt-space-sm);
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise .bt-exercise-static summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bt-color-text-secondary);
}

/* === workspace === */

/* Lesson workspace region (<main class="workspace">). Component-level rules
 * for picker, editor, controls, status badge, and output console. Scoped to
 * workspace-specific selectors — no bare element selectors that bleed into
 * header/footer.
 *
 * What it does NOT do:
 *  - No #feedback panel styling (AC-3 owns that region).
 *  - No header/footer overrides.
 *  - No JS changes — pure CSS only.
 *  - Dark mode is handled by the dark-mode @media block :root overrides
 *    at the bottom of this file — workspace rules inherit via var(--bt-*) tokens.
 */

.bt-exercise .lesson-picker {
  display: flex;
  align-items: center;
  gap: var(--bt-space-sm);
}

.bt-exercise .lesson-picker label {
  color: var(--bt-color-text-secondary);
}

.bt-exercise .lesson-picker select {
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  background: var(--bt-color-surface);
  color: var(--bt-color-text-primary);
  font-family: var(--bt-font-family-ui);
}

.bt-exercise #lesson-title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--bt-color-text-primary);
  margin-bottom: var(--bt-space-sm);
}

.bt-exercise #lesson-prompt {
  line-height: var(--bt-line-height);
  color: var(--bt-color-text-secondary);
  margin-bottom: var(--bt-space-md);
}

/* Hints — expandable <details> panel rendered by lesson-runner-core.js when a
 * lesson carries hints. Created dynamically (no static element in the HTML
 * shell); removed when switching to a lesson without hints. Dark mode is
 * handled by the existing :root token overrides in the @media block. */

.bt-exercise #lesson-hints {
  margin-bottom: var(--bt-space-md);
  padding: var(--bt-space-sm) var(--bt-space-md);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface-code);
}

.bt-exercise #lesson-hints summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bt-color-text-secondary);
}

.bt-exercise #lesson-hints p {
  margin: var(--bt-space-sm) 0 0;
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise #lesson-hints ul {
  margin: var(--bt-space-sm) 0 0;
  padding-left: var(--bt-space-lg);
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

/* Gotchas — expandable <details> panel rendered by lesson-runner-core.js when a
 * lesson carries gotchas. Created dynamically (no static element in the HTML
 * shell); removed when switching to a lesson without gotchas. Dark mode is
 * handled by the existing :root token overrides in the @media block. */

.bt-exercise #lesson-gotchas {
  margin-bottom: var(--bt-space-md);
  padding: var(--bt-space-sm) var(--bt-space-md);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface-code);
}

.bt-exercise #lesson-gotchas summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bt-color-text-secondary);
}

.bt-exercise #lesson-gotchas p {
  margin: var(--bt-space-sm) 0 0;
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise #lesson-gotchas ul {
  margin: var(--bt-space-sm) 0 0;
  padding-left: var(--bt-space-lg);
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise #submission {
  font-family: var(--bt-font-family-code);
  background: var(--bt-color-surface-code);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-sm);
  box-shadow: var(--bt-shadow-sm);
  min-height: 6rem;
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  color: var(--bt-color-text-primary);
  font-size: var(--bt-font-size-base);
  line-height: var(--bt-line-height);
}

.bt-exercise #submission:focus {
  outline: none;
  border-color: var(--bt-color-brand);
}

/* === CodeMirror 6 editor === */

/* The CM6 editor mounts inside #submission (a <div>, not a textarea). The
 * .cm-editor is the root CM6 view; .cm-content is the editable surface; .cm-
 * scroller is the scroll container. Styled to match the old textarea: code
 * font, surface-code background, border, min-height, and horizontal scroll for
 * long lines. Token colors use a custom HighlightStyle (lesson-runner-core.js)
 * that emits deterministic `.tok-*` classes — NOT CM6's default opaque unicode
 * classes (e.g. `ͼa`) — so the AC-2 deterministic check can grep for them.
 * Colors are the CM6 default light-theme palette; dark-mode overrides live in
 * the @media block at the end of this file (AC-3 will refine the theme).
 */

.bt-exercise .cm-editor {
  min-height: 6rem;
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface-code);
}

.bt-exercise .cm-content {
  font-family: var(--bt-font-family-code);
  padding: var(--bt-space-sm);
}

.bt-exercise .cm-scroller {
  overflow: auto;
}

/* Line number gutter — AC-3 UX polish. The gutter renders line numbers in a
 * monospace font matching the code surface (prevents gutter/code misalignment —
 * sneaky-pass #6: .cm-content monospace but .cm-gutters inherits system-ui).
 * Background uses surface-code so the gutter is visually distinct from the
 * editable content area. */

.bt-exercise .cm-gutters {
  background: var(--bt-color-surface-code);
  border-right: 1px solid var(--bt-color-border);
  font-family: var(--bt-font-family-code, monospace);
}

.bt-exercise .cm-gutterElement {
  font-family: var(--bt-font-family-code, monospace);
}

/* Active line highlight — the line holding the cursor gets a subtle background
 * tint so the learner can locate the insertion point. The tint must be DISTINCT
 * from .cm-content's background (sneaky-pass #4: transparent or matching bg =
 * zero visual difference). */

.bt-exercise .cm-activeLine {
  background: rgba(0, 0, 0, 0.04);
}

/* Bracket match highlight — when the cursor sits adjacent to a bracket, the
 * matching bracket is highlighted. bracketMatching() adds the
 * .cm-matchingBracket class to the DOM; this rule makes it VISIBLE (sneaky-pass
 * #2: class added but no CSS = no visual). The background + outline are
 * non-transparent so the match is unambiguous. */

.bt-exercise .cm-matchingBracket {
  background: rgba(0, 0, 0, 0.12);
  outline: 1px solid rgba(0, 0, 0, 0.2);
}

/* Focus outline removal — CM6 manages its own focus ring inside .cm-editor;
 * suppress the browser default outline on the contenteditable to avoid a
 * double-ring. */

.bt-exercise .cm-focused {
  outline: none;
}

/* Syntax token colors — deterministic `.tok-*` classes emitted by the custom
 * HighlightStyle in lesson-runner-core.js. CM6's defaultHighlightStyle uses
 * opaque generated classes (ͼa, ͼb, …) that cannot be grepped; these stable
 * names make token spans testable (AC-2 deterministic_check). Palette matches
 * the CM6 default light theme. */

.bt-exercise .tok-keyword {
  color: var(--bt-color-syntax-keyword);
}

.bt-exercise .tok-string {
  color: var(--bt-color-syntax-string);
}

.bt-exercise .tok-number {
  color: var(--bt-color-syntax-number);
}

.bt-exercise .tok-comment {
  color: var(--bt-color-syntax-comment); font-style: italic;
}

.bt-exercise .tok-variableName {
  color: var(--bt-color-syntax-variable);
}

.bt-exercise .tok-function {
  color: var(--bt-color-syntax-function);
}

.bt-exercise .tok-operator {
  color: var(--bt-color-syntax-operator);
}

.bt-exercise .controls {
  display: flex;
  align-items: center;
  gap: var(--bt-space-md);
  margin-top: var(--bt-space-sm);
  margin-bottom: var(--bt-space-sm);
}

.bt-exercise #run {
  background: var(--bt-color-brand);
  color: var(--bt-color-surface);
  border: none;
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise #run:hover {
  background: var(--bt-color-brand-hover);
}

.bt-exercise #submit {
  background: transparent;
  border: 1px solid var(--bt-color-border);
  color: var(--bt-color-text-primary);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise #submit:hover {
  background: color-mix(in srgb, var(--bt-color-border) 20%, transparent);
}

.bt-exercise #lesson-status {
  display: inline-block;
  padding: var(--bt-space-xs) var(--bt-space-sm);
  border-radius: var(--bt-radius-pill);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.75rem;
  box-shadow: var(--bt-shadow-sm);
  line-height: 1.75;
}

.bt-exercise #lesson-status[data-status="idle"] {
  background: var(--bt-color-status-idle);
  color: var(--bt-color-text-secondary);
}

.bt-exercise #lesson-status[data-status="running"] {
  background: var(--bt-color-status-running);
  color: var(--bt-color-surface);
}

.bt-exercise #lesson-status[data-status="pass"] {
  background: var(--bt-color-status-pass);
  color: var(--bt-color-surface);
}

.bt-exercise #lesson-status[data-status="fail"] {
  background: var(--bt-color-status-fail);
  color: var(--bt-color-surface);
}

.bt-exercise #output {
  background: var(--bt-color-surface-code);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-sm);
  box-shadow: var(--bt-shadow-sm);
  white-space: pre-wrap;
  min-height: 4rem;
  font-family: var(--bt-font-family-code);
  font-size: var(--bt-font-size-base);
  line-height: var(--bt-line-height);
  color: var(--bt-color-text-primary);
}

/* === exercise UX polish (AC-8) === */

/* Per-exercise UX elements: hints <details> toggle, solution/check buttons,
 * data-status badge, and disabled-button cursor. These are the class-based
 * equivalents of the singleton #lesson-* selectors above, used by
 * exercise-runtime.js's per-exercise wireExercise().
 *
 * What it does:
 *  - .bt-hints: expandable <details> panel for hints (clause 1).
 *  - .bt-feedback-btn / .bt-check-btn / .bt-solution-btn: control buttons.
 *    (issue 182: .bt-feedback-btn replaced .bt-run-btn — Get feedback takes
 *    Run's toolbar slot with Run's styling.)
 *  - button[disabled]: cursor not-allowed (clause 5).
 *  - .bt-status[data-status]: closed-set status badge (clause 6).
 *
 * What it does NOT do:
 *  - No JS changes — pure CSS only.
 *  - No hex color literals — all colors via var(--bt-*) tokens.
 *  - Dark mode is handled by the dark-mode @media block :root overrides.
 */

.bt-exercise .bt-hints {
  margin-bottom: var(--bt-space-md);
  padding: var(--bt-space-sm) var(--bt-space-md);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface-code);
}

.bt-exercise .bt-hints summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bt-color-text-secondary);
}

.bt-exercise .bt-hints p {
  margin: var(--bt-space-sm) 0 0;
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise .bt-hints ul {
  margin: var(--bt-space-sm) 0 0;
  padding-left: var(--bt-space-lg);
  color: var(--bt-color-text-secondary);
  line-height: var(--bt-line-height);
}

.bt-exercise .bt-controls {
  display: flex;
  align-items: center;
  gap: var(--bt-space-md);
  margin-top: var(--bt-space-sm);
  margin-bottom: var(--bt-space-sm);
}

.bt-exercise .bt-feedback-btn {
  background: var(--bt-color-brand);
  color: var(--bt-color-surface);
  border: none;
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise .bt-feedback-btn:hover {
  background: var(--bt-color-brand-hover);
}

/* The former .bt-run-btn (issue 182) is REMOVED from the runtime — Check
 * runs the deterministic tests and Get feedback (.bt-feedback-btn) takes
 * Run's toolbar slot with Run's styling (above). */

.bt-exercise .bt-check-btn {
  background: transparent;
  border: 1px solid var(--bt-color-border);
  color: var(--bt-color-text-primary);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise .bt-check-btn:hover {
  background: color-mix(in srgb, var(--bt-color-border) 20%, transparent);
}

.bt-exercise .bt-solution-btn {
  background: transparent;
  border: 1px solid var(--bt-color-border);
  color: var(--bt-color-text-secondary);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise .bt-solution-btn:hover {
  background: color-mix(in srgb, var(--bt-color-border) 20%, transparent);
}

/* Disabled buttons — cursor not-allowed (clause 5). Applies to any button
 * inside .bt-exercise that carries the [disabled] attribute. */

.bt-exercise button[disabled] {
  cursor: not-allowed;
  opacity: 0.6;
}

.bt-exercise .bt-status {
  display: inline-block;
  padding: var(--bt-space-xs) var(--bt-space-sm);
  border-radius: var(--bt-radius-pill);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.75rem;
  box-shadow: var(--bt-shadow-sm);
  line-height: 1.75;
}

.bt-exercise .bt-status[data-status="idle"] {
  background: var(--bt-color-status-idle);
  color: var(--bt-color-text-secondary);
}

.bt-exercise .bt-status[data-status="running"] {
  background: var(--bt-color-status-running);
  color: var(--bt-color-surface);
}

.bt-exercise .bt-status[data-status="pass"] {
  background: var(--bt-color-status-pass);
  color: var(--bt-color-surface);
}

.bt-exercise .bt-status[data-status="fail"] {
  background: var(--bt-color-status-fail);
  color: var(--bt-color-surface);
}

/* ADR-0021: status and output render only once something has run; the
 * feedback area collapses until it has content. Attribute selectors beat the
 * component display rules above, which would otherwise override [hidden]. */

.bt-exercise .bt-status[hidden],
.bt-exercise .bt-output[hidden],
.bt-exercise .bt-feedback:empty {
  display: none;
}

.bt-exercise .bt-output {
  background: var(--bt-color-surface-code);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-sm);
  box-shadow: var(--bt-shadow-sm);
  white-space: pre-wrap;
  min-height: 4rem;
  font-family: var(--bt-font-family-code);
  font-size: var(--bt-font-size-base);
  line-height: var(--bt-line-height);
  color: var(--bt-color-text-primary);
}

/* === feedback / BYOK === */

/* BYOK feedback panel — styled via data-byok / data-correct attribute selectors.
 * All rules scoped to #feedback-descendant selectors or specific
 * [data-byok] / #byok-disclosure selectors — never bare element selectors.
 *
 * What it does:
 *  - Cards each #feedback child with surface + border + shadow + radius + padding.
 *  - Verdict states (correct/incorrect) visually distinct via success-bg/danger-bg.
 *  - Disclosure (#byok-disclosure) styled as muted privacy note.
 *  - Form elements consistent with AC-2 workspace styling.
 *  - Transient states (pending, loading, error) styled with appropriate emphasis.
 *
 * What it does NOT do:
 *  - No JS changes — pure CSS only. feedback.js byte-unchanged.
 *  - No className/style./classList manipulation (those are feedback.js's job).
 *  - No hex color literals in BYOK rules — all colors via var(--bt-*) tokens.
 *  - Dark mode is handled by the dark-mode @media block :root overrides
 *    at the bottom of this file — BYOK rules inherit via var(--bt-*) tokens.
 */

/* Card container — each phase uses surface + border + shadow for elevation */

.bt-exercise #feedback [data-byok="key-prompt"],
.bt-exercise #feedback [data-byok="model-picker"],
.bt-exercise #feedback [data-byok="verdict"],
.bt-exercise #feedback [data-byok="pending"],
.bt-exercise #feedback [data-byok="error"],
.bt-exercise #feedback [data-byok="models-loading"] {
  background: var(--bt-color-surface);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  box-shadow: var(--bt-shadow-sm);
  padding: var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
}

/* Form elements — consistent with AC-2 workspace input/select/button styling */

.bt-exercise #feedback [data-byok="provider"],
.bt-exercise #feedback [data-byok="model"],
.bt-exercise #feedback input[type="password"] {
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  background: var(--bt-color-surface);
  color: var(--bt-color-text-primary);
  font-family: var(--bt-font-family-ui);
}

.bt-exercise #feedback input[type="password"] {
  width: 100%;
  box-sizing: border-box;
}

.bt-exercise #feedback button[type="submit"] {
  background: var(--bt-color-brand);
  color: var(--bt-color-surface);
  border: none;
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  cursor: pointer;
  font-weight: 600;
}

.bt-exercise #feedback button[type="submit"]:hover {
  background: var(--bt-color-brand-hover);
}

/* Verdict: correct — green-tinted surface, green left accent */

.bt-exercise #feedback [data-byok="verdict"][data-correct="true"] {
  background: var(--bt-color-success-bg);
  color: var(--bt-color-text-primary);
  border-left: 4px solid var(--bt-color-status-pass);
}

.bt-exercise #feedback [data-byok="verdict"][data-correct="true"] strong {
  color: var(--bt-color-status-pass);
}

/* Verdict: incorrect — amber-tinted surface, fail left accent */

.bt-exercise #feedback [data-byok="verdict"][data-correct="false"] {
  background: var(--bt-color-danger-bg);
  color: var(--bt-color-text-primary);
  border-left: 4px solid var(--bt-color-status-fail);
}

.bt-exercise #feedback [data-byok="verdict"][data-correct="false"] strong {
  color: var(--bt-color-status-fail);
}

/* Disclosure — privacy note, visually distinct from body text */

.bt-exercise #byok-disclosure {
  color: var(--bt-color-text-secondary);
  font-size: 0.875em;
  font-style: italic;
  margin-bottom: var(--bt-space-sm);
}

/* Pending / loading — transient states: secondary text with pulsing animation */

.bt-exercise #feedback [data-byok="pending"],
.bt-exercise #feedback [data-byok="models-loading"] {
  color: var(--bt-color-text-secondary);
  animation: bt-pulse 1.5s ease-in-out infinite;
}

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

/* Error — text-only emphasis: fail color, no background tint (distinct from verdict) */

.bt-exercise #feedback [data-byok="error"] {
  color: var(--bt-color-status-fail);
}

/* === Quarto path (per-exercise .bt-feedback) + key page (issue 182) ===
 * The Quarto fork renders per-exercise feedback into a .bt-feedback container
 * (exercise-feedback.js mountFeedback) — the #feedback rules above serve the
 * crates site shell and are NOT matched by the new code. This section styles
 * the per-exercise container, the INLINE key form (issue 186), and the
 * KEY PAGE form.
 *
 * Scoping notes (scripts/sync-quarto-assets.sh):
 *  - Rules in this source file are prefixed with .bt-exercise by the sync
 *    transform, EXCEPT selectors wrapped in :global(...) which pass through
 *    UNscoped. The key page (.blendtutor-key) sits OUTSIDE any .bt-exercise
 *    wrapper, so its form rules MUST use :global(...) — a scoped rule would
 *    never match the key page ("bizarre page" bug, issue 182).
 *  - The INLINE key form (issue 186) renders INSIDE .bt-feedback inside
 *    .bt-exercise — scoped. The flatten override below cancels the :global
 *    card styling so there is no card-in-card.
 */

/* Per-exercise feedback container — cards the verdict/inline-form/error area */

.bt-exercise .bt-feedback {
  margin-top: var(--bt-space-md);
  padding: var(--bt-space-sm);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface);
  font-family: var(--bt-font-family-ui);
}

/* Inline key form inside the feedback container (issue 186): the key-page
 * form rules are :global passthrough (card styling for the standalone key
 * page). When the form mounts INLINE inside the .bt-feedback card, flatten
 * the card-in-card — the container already supplies border/background/padding.
 * This scoped rule beats the :global passthrough by specificity. */

.bt-exercise .bt-feedback [data-byok="key-page-form"] {
  max-width: none;
  border: none;
  background: transparent;
  box-shadow: none;
  padding: 0;
}

/* Verdict / pending / error / limit-reached inside the per-exercise container */

.bt-exercise [data-byok="feedback"] [data-byok="verdict"][data-correct="true"] {
  background: var(--bt-color-success-bg);
  color: var(--bt-color-text-primary);
  border-left: 4px solid var(--bt-color-status-pass);
}

.bt-exercise [data-byok="feedback"] [data-byok="verdict"][data-correct="true"] strong {
  color: var(--bt-color-status-pass);
}

.bt-exercise [data-byok="feedback"] [data-byok="verdict"][data-correct="false"] {
  background: var(--bt-color-danger-bg);
  color: var(--bt-color-text-primary);
  border-left: 4px solid var(--bt-color-status-fail);
}

.bt-exercise [data-byok="feedback"] [data-byok="verdict"][data-correct="false"] strong {
  color: var(--bt-color-status-fail);
}

.bt-exercise [data-byok="feedback"] [data-byok="pending"] {
  color: var(--bt-color-text-secondary);
  animation: bt-pulse 1.5s ease-in-out infinite;
}

.bt-exercise [data-byok="feedback"] [data-byok="error"] {
  color: var(--bt-color-status-fail);
}

.bt-exercise [data-byok="feedback"] [data-byok="limit-reached"] {
  color: var(--bt-color-text-secondary);
  font-size: 0.875em;
}

/* === KEY PAGE (issue 182) — GLOBAL rules via :global(...) ===
 * The key-management form (key-page.js mountKeyPage) renders into
 * <div class="blendtutor-key"> on the api-key page — OUTSIDE any
 * .bt-exercise wrapper. The sync transform passes :global(...) selectors
 * through unscoped so these rules reach the key page. */

[data-byok="key-page-form"] {
  display: flex;
  flex-direction: column;
  gap: var(--bt-space-md);
  max-width: 28rem;
  padding: var(--bt-space-lg);
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-md);
  background: var(--bt-color-surface);
  box-shadow: var(--bt-shadow-sm);
  font-family: var(--bt-font-family-ui);
}

[data-byok="key-input"] {
  border: 1px solid var(--bt-color-border);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  background: var(--bt-color-surface);
  color: var(--bt-color-text-primary);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  width: 100%;
  box-sizing: border-box;
}

[data-byok="key-input"]:focus {
  outline: none;
  border-color: var(--bt-color-brand);
}

[data-byok="save"] {
  align-self: flex-start;
  background: var(--bt-color-brand);
  color: var(--bt-color-surface);
  border: none;
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

[data-byok="save"]:hover {
  background: var(--bt-color-brand-hover);
}

[data-byok="clear"] {
  align-self: flex-start;
  background: transparent;
  border: 1px solid var(--bt-color-border);
  color: var(--bt-color-text-primary);
  border-radius: var(--bt-radius-sm);
  padding: var(--bt-space-xs) var(--bt-space-sm);
  font-family: var(--bt-font-family-ui);
  font-size: var(--bt-font-size-base);
  cursor: pointer;
  font-weight: 600;
}

[data-byok="clear"]:hover {
  background: color-mix(in srgb, var(--bt-color-border) 20%, transparent);
}

[data-byok="key-status"] {
  margin: 0;
  color: var(--bt-color-text-secondary);
  font-size: 0.875em;
  line-height: var(--bt-line-height);
}

/* ── Dark mode ────────────────────────────────────────────────────
 * Overrides all 21 --bt-color-* tokens inside @media (prefers-color-scheme: dark)
 * for WCAG AA contrast (4.5:1 text, 3:1 UI/large text). No non-color tokens.
 * The :root block is extracted by the test via brace-counting on the @media
 * selector, then brace-counting again on :root within the media block body.
 * The media block must appear AFTER light :root's closing `}` (positional
 * invariant enforced by build_dark_mode_token_overrides clause 1).
 *
 * WARNING: This block MUST remain at the END of this file, after all semantic
 * rules. The idle-pill status override inside this block has the SAME
 * specificity (1,1,0) as the default rule; @media does NOT add specificity
 * per the CSS cascading spec. If this block appears before the default rule,
 * the override is dead code — the later default rule wins by source order.
 * Tests check token values from parsed CSS custom properties, not computed
 * CSS styles, so they do NOT catch source-order bugs. Keep this block last.
 */

@media (prefers-color-scheme: dark) {
  :root {
    --bt-color-surface: #1e1e1e;
    --bt-color-surface-code: #2d2d2d;
    --bt-color-text-primary: #e0e0e0;
    --bt-color-text-secondary: #a0a0a0;
    --bt-color-status-pass: #66bb6a;
    --bt-color-status-fail: #ff5252;
    --bt-color-status-running: #ff9800;
    --bt-color-brand: #e0e0e0;
    --bt-color-brand-hover: #ffffff;
    --bt-color-border: #808080;
    --bt-color-status-idle: #888888;
    --bt-color-success-bg: #1b3d1b;
    --bt-color-danger-bg: #3d1b1b;
    /* Syntax highlighting — VS Code dark-theme palette */
    --bt-color-syntax-keyword: #569cd6;
    --bt-color-syntax-string: #ce9178;
    --bt-color-syntax-number: #b5cea8;
    --bt-color-syntax-comment: #6a9955;
    --bt-color-syntax-variable: #d4d4d4;
    --bt-color-syntax-function: #dcdcaa;
    --bt-color-syntax-operator: #d4d4d4;
    /* Cursor — pure white for maximum contrast against the dark surface-code
    * background. The previous value (text-primary gray) was visible but
    * faint at 1.2px width; pure white at 2px is clearly visible. */
    --bt-color-cursor: #ffffff;
  }

  /* Idle pill text: surface provides sufficient contrast on dark status-idle */

  .bt-exercise #lesson-status[data-status="idle"] {
    color: var(--bt-color-surface);
  }

  /* CM6 UX-polish dark overrides — AC-3. The light-mode rules use rgba(0,0,0,*)
   * tints which are invisible on a dark surface; these flip to rgba(255,255,255,*)
   * so the gutter border, active line, and bracket match remain visible in
   * dark mode. */

  .bt-exercise .cm-gutters {
    background: var(--bt-color-surface-code);
    border-right-color: var(--bt-color-border);
  }

  .bt-exercise .cm-activeLine {
    background: rgba(255, 255, 255, 0.04);
  }

  .bt-exercise .cm-matchingBracket {
    background: rgba(255, 255, 255, 0.12);
    outline-color: rgba(255, 255, 255, 0.2);
  }
}
