/* CKA Practice — minimal, no framework. */

:root {
  --bg: #ffffff;
  --bg-elev: #f7f7f9;
  --bg-code: #f1f1f4;
  --fg: #1f2328;
  --fg-muted: #656d76;
  --border: #d0d7de;
  --accent: #0969da;
  --accent-fg: #ffffff;
  --success: #1a7f37;
  --danger: #d1242f;
  --warning: #9a6700;

  --tag-cka:        #d1242f;
  --tag-killer-a:   #bc4c00;
  --tag-killer-b:   #8250df;
  --tag-killercoda: #1f883d;   /* green — KillerCoda is the live-lab provider; distinct from Killer.sh's red/purple */
  --tag-general:    #6e7781;

  --shadow: 0 1px 3px rgba(31,35,40,.08);
  --radius: 6px;
}

[data-theme="dark"] {
  --bg: #0d1117;
  --bg-elev: #161b22;
  --bg-code: #1a1f26;
  --fg: #e6edf3;
  --fg-muted: #8b949e;
  --border: #30363d;
  --accent: #2f81f7;
  --shadow: 0 1px 3px rgba(0,0,0,.5);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  /* Root-level escape valve so any stray horizontal overflow (long token,
     wide table, oversized <pre>) is clipped at the body instead of pushing
     the page wider than the viewport. `clip` (not `hidden`) avoids creating
     a new scroll container, so position: sticky on TOCs still works. */
  overflow-x: clip;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  background: var(--bg);
  color: var(--fg);
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

button {
  font: inherit;
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 10px;
  cursor: pointer;
}
button:hover { background: var(--border); }
button.primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
button.primary:hover { filter: brightness(1.1); }
/* Anchors styled as buttons (e.g. the report modal's Open-GitHub-issue link
   — kept as a real anchor so mobile Safari / Android PWA navigate natively
   instead of relying on the popup-blocked window.open path). */
a.primary {
  display: inline-block;
  text-decoration: none;
  font: inherit;
  background: var(--accent);
  color: var(--accent-fg);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 4px 10px;
  cursor: pointer;
}
a.primary:hover { filter: brightness(1.1); text-decoration: none; }
button.danger { color: var(--danger); border-color: var(--danger); background: transparent; }
button.grade-got { color: var(--success); border-color: var(--success); }
button.grade-partial { color: var(--warning); border-color: var(--warning); }
button.grade-miss { color: var(--danger); border-color: var(--danger); }

input[type="search"], input[type="number"] {
  font: inherit;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 8px;
}

code, pre { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; font-size: 13px; }
code { background: var(--bg-code); padding: 2px 5px; border-radius: 4px; }
pre { background: var(--bg-code); padding: 12px 14px; border-radius: var(--radius); overflow-x: auto; position: relative; }
pre code { background: transparent; padding: 0; }
pre .copy-btn {
  position: absolute; top: 6px; right: 6px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 4px;
  padding: 2px 8px; font-size: 11px; cursor: pointer;
  opacity: 0; transition: opacity .15s;
}
pre:hover .copy-btn { opacity: 1; }
pre .copy-btn.copied { color: var(--success); }

/* Header */
#app-header {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-elev);
  position: sticky;
  top: 0;
  z-index: 50;
}
.brand { display: flex; align-items: center; gap: 8px; font-size: 16px; }
.brand-icon {
  /* Mini PWA-install-icon variant (icons/icon-mark.svg) — blue rounded square
     + white helm, no wordmark (would duplicate the adjacent "CKA Practice"
     text and be illegible at this size). */
  width: 24px;
  height: 24px;
  display: inline-block;
  vertical-align: middle;
}
.mode-tabs { display: flex; gap: 4px; }
.mode-tab { border: 1px solid transparent; background: transparent; }
.mode-tab.active { background: var(--bg); border-color: var(--border); font-weight: 600; }
.header-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* Always-visible release version chip in the header right. Plain pill,
   monospace digits, clicks through to Help → Changelog. */
.app-build-chip {
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-elev);
  color: var(--fg-muted);
  cursor: pointer;
  line-height: 1.5;
  white-space: nowrap;
}
.app-build-chip:hover { color: var(--fg); border-color: var(--accent); }
.app-build-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Dev build (HEAD not on a release tag) — subtle orange so users can
   spot at a glance whether they're on a tagged release or a build
   between releases. Not alarming, just different. */
.app-build-chip--dev {
  border-color: rgba(217, 119, 0, 0.45);
  color: rgba(217, 119, 0, 0.95);
}
.app-build-chip--dev:hover { color: rgba(217, 119, 0, 1); border-color: rgba(217, 119, 0, 0.8); }
[data-theme="dark"] .app-build-chip--dev {
  border-color: rgba(255, 184, 77, 0.5);
  color: rgba(255, 184, 77, 0.95);
}
[data-theme="dark"] .app-build-chip--dev:hover { color: #ffb84d; border-color: rgba(255, 184, 77, 0.9); }
@media (max-width: 480px) {
  .app-build-chip { font-size: 10px; padding: 1px 6px; }
}
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  padding: 0; border-radius: var(--radius);
  background: transparent; border: 1px solid transparent;
  color: var(--fg-muted); cursor: pointer;
  text-decoration: none;
  transition: background .12s, color .12s, border-color .12s;
}
.icon-btn:hover { background: var(--bg-elev); border-color: var(--border); color: var(--fg); text-decoration: none; }
.icon-btn svg { display: block; }
#quiz-timer { font-weight: 600; font-variant-numeric: tabular-nums; padding: 4px 10px; background: var(--bg); border-radius: var(--radius); border: 1px solid var(--border); }
#quiz-timer.warn { color: var(--warning); border-color: var(--warning); }
#quiz-timer.danger { color: var(--danger); border-color: var(--danger); animation: pulse 1s infinite; }
@keyframes pulse { 50% { opacity: .55; } }

/* Refresh button: spin the 🔄 emoji while the manual refresh pre-check is in
   flight. Cleared automatically on success/error. */
#refresh-toggle.refreshing { animation: refresh-spin 0.6s linear infinite; }
@keyframes refresh-spin { to { transform: rotate(360deg); } }

/* Top-anchored refresh-result toast. Single-slot — any previous toast is
   replaced by manualRefresh(). Auto-dismisses in 3s (4s on error). */
.refresh-toast {
  position: fixed;
  top: 70px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2000;
  padding: 8px 14px;
  border-radius: var(--radius);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  font-size: 13px;
  box-shadow: var(--shadow);
  opacity: 0;
  animation: refresh-toast-in 200ms ease forwards;
  max-width: calc(100vw - 32px);
  text-align: center;
}
@keyframes refresh-toast-in { to { opacity: 1; } }
.refresh-toast--ok  { border-color: var(--success); color: var(--success); }
.refresh-toast--err { border-color: var(--danger);  color: var(--danger); }

/* Filter bar — desktop layout */
#filter-bar {
  border-bottom: 1px solid var(--border);
  background: var(--bg-elev);
  position: sticky;
  top: 56px;
  z-index: 40;
}
#filter-bar-content {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 10px 20px;
}
/* Mobile-only condensed toolbar; hidden on desktop */
.mobile-toolbar { display: none; }
.mobile-stats { font-size: 12px; }
.dropdown { position: relative; }
.dropdown > summary {
  list-style: none;
  cursor: pointer;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown[open] > summary { background: var(--border); }
.filter-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  position: absolute;
  margin-top: 4px;
  z-index: 100;
  min-width: 200px;
  box-shadow: var(--shadow);
}
.filter-list.horizontal { flex-direction: row; flex-wrap: wrap; gap: 14px; position: static; box-shadow: none; padding: 0; border: none; background: transparent; }
.filter-list label { display: flex; align-items: center; gap: 6px; cursor: pointer; white-space: nowrap; }
.toggle-label { display: flex; align-items: center; gap: 6px; padding: 4px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); cursor: pointer; }
#filter-search { flex: 1; min-width: 200px; }
#filter-stats { color: var(--fg-muted); margin-left: auto; font-size: 13px; }

/* Layout */
.view { display: none; }
.view.active { display: block; }
.layout { display: grid; grid-template-columns: 280px 1fr; min-height: calc(100vh - 110px); }

/* Sidebar */
#sidebar {
  border-right: 1px solid var(--border);
  background: var(--bg-elev);
  padding: 14px 12px;
  overflow-y: auto;
  max-height: calc(100vh - 110px);
  position: sticky;
  top: 110px;
}
#sidebar-progress {
  padding: 10px 8px;
  margin-bottom: 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 13px;
}
#sidebar-progress .progress-row { display: flex; justify-content: space-between; align-items: center; padding: 2px 0; }
#sidebar-progress .progress-row strong { color: var(--accent); }

/* Per-domain progress bars */
.prog-row { padding: 5px 0; }
.prog-row .prog-label {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px;
  margin-bottom: 3px;
}
.prog-row .prog-name { color: var(--fg); font-weight: 500; }
.prog-row .prog-count {
  color: var(--fg-muted);
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 10px;
}
.prog-row .prog-bar {
  height: 5px;
  background: var(--bg-code);
  border-radius: 999px;
  overflow: hidden;
}
.prog-row .prog-bar-fill {
  height: 100%;
  background: var(--accent);
  transition: width .25s, background-color .25s;
  border-radius: 999px;
}
.prog-row.complete .prog-bar-fill { background: var(--success); }
.prog-row.complete .prog-name { color: var(--success); }

/* Quiz-home per-domain proficiency strip — same prog-bar visuals as
   sidebar but laid out wider and with a 💡 weak hint chip. */
.quiz-proficiency {
  margin: 14px 0 10px;
  padding: 12px 14px;
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.quiz-prof-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 8px;
}
.quiz-prof-row { padding: 4px 0; }
.quiz-prof-row + .quiz-prof-row { margin-top: 2px; }
.quiz-prof-row .quiz-prof-label {
  display: flex; align-items: center; gap: 10px;
  font-size: 12px;
  margin-bottom: 3px;
  flex-wrap: wrap;
}
.quiz-prof-row .quiz-prof-name { font-weight: 500; color: var(--fg); flex: 1 1 auto; }
.quiz-prof-row .quiz-prof-weight { font-size: 10px; opacity: 0.7; }
.quiz-prof-row .quiz-prof-count {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--fg-muted);
}
.quiz-prof-row .quiz-prof-weak-tag {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 140, 0, 0.15);
  color: #d97700;
  border: 1px solid rgba(255, 140, 0, 0.35);
}
[data-theme="dark"] .quiz-prof-row .quiz-prof-weak-tag {
  background: rgba(255, 170, 60, 0.15);
  color: #ffb84d;
  border-color: rgba(255, 170, 60, 0.4);
}
.quiz-prof-row .prog-bar {
  height: 5px;
  background: var(--bg);
  border-radius: 999px;
  overflow: hidden;
}
.quiz-prof-row .prog-bar-fill {
  height: 100%;
  background: var(--accent);
  transition: width .25s, background-color .25s;
  border-radius: 999px;
}
.quiz-prof-row.complete .prog-bar-fill { background: var(--success); }
.quiz-prof-row.complete .quiz-prof-name { color: var(--success); }
.quiz-prof-row.weak .quiz-prof-name { color: #d97700; }
[data-theme="dark"] .quiz-prof-row.weak .quiz-prof-name { color: #ffb84d; }

.prog-divider {
  height: 1px;
  background: var(--border);
  margin: 8px 0;
}
.prog-overall {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12px;
  padding: 1px 0;
}
.prog-overall strong { color: var(--accent); font-variant-numeric: tabular-nums; }
.prog-overall.muted { color: var(--fg-muted); }
.prog-overall.muted strong { color: var(--fg-muted); }

.tree-domain { margin-bottom: 8px; }
.tree-domain > summary {
  list-style: none;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
  font-weight: 600;
  display: flex; align-items: center; gap: 6px;
}
.tree-domain > summary::-webkit-details-marker { display: none; }
.tree-domain > summary::before { content: "▸"; flex-shrink: 0; color: var(--fg-muted); }
.tree-domain[open] > summary::before { content: "▾"; }
.tree-domain > summary:hover { background: var(--bg); }
.tree-domain > summary > .label,
.tree-section > summary > .label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tree-domain > summary > small,
.tree-section > summary > small {
  flex-shrink: 0;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}
.tree-section { margin-left: 14px; margin-bottom: 4px; }
.tree-section > summary {
  list-style: none;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--fg-muted);
  display: flex; align-items: center; gap: 6px;
}
.tree-section > summary::-webkit-details-marker { display: none; }
.tree-section > summary::before { content: "▸"; flex-shrink: 0; }
.tree-section[open] > summary::before { content: "▾"; }
.tree-section > summary:hover { background: var(--bg); }
.tree-exercise {
  display: flex; align-items: center; gap: 6px;
  padding: 2px 8px 2px 22px;
  font-size: 12px;
  color: var(--fg);
  border-radius: 4px;
  cursor: pointer;
  border: none;
  background: transparent;
  text-align: left;
  width: 100%;
  line-height: 1.5;
}
.tree-exercise .qnum {
  flex-shrink: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--fg-muted);
  min-width: 32px;
}
.tree-exercise .label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tree-exercise:hover { background: var(--bg); color: var(--accent); }
.tree-exercise:hover .qnum { color: var(--accent); }
.tree-exercise.done .label { text-decoration: line-through; }
.tree-exercise.done { color: var(--fg-muted); }
.tree-exercise.bookmarked::after { content: "⭐"; flex-shrink: 0; }

/* ---------- Browse sidebar custom hover tooltip ----------
   The sidebar tree keeps every label single-line + ellipsis for compactness
   (the 280 px column is intentionally narrow). On hover / focus this fixed-
   position singleton tooltip surfaces the full text without disrupting the
   tree's visual rhythm. Position is computed in JS (installSidebarTooltip). */
.sidebar-tooltip {
  position: fixed;
  z-index: 1500;
  max-width: 400px;
  padding: 8px 12px;
  background: var(--bg-elev);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  font-size: 12.5px;
  line-height: 1.45;
  white-space: normal;
  word-break: break-word;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 100ms ease;
}
.sidebar-tooltip--visible {
  opacity: 1;
  visibility: visible;
}

/* Main panel */
#main { padding: 20px 24px; overflow-y: auto; max-height: calc(100vh - 110px); }

/* Exercise card */
.exercise-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 20px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
}
.exercise-card.done { border-left: 4px solid var(--success); }
.exercise-header {
  display: flex; align-items: flex-start; flex-wrap: wrap; gap: 10px;
  margin-bottom: 10px;
}
.exercise-title { font-size: 16px; font-weight: 600; flex: 1; min-width: 200px; margin: 0; }
.exercise-tools { display: flex; gap: 6px; align-items: center; }
.exercise-tools button { padding: 3px 8px; font-size: 12px; }
.exercise-meta { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; font-size: 12px; color: var(--fg-muted); }

.tag-pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; color: white; font-weight: 600; }
.tag-cka-past-exam { background: var(--tag-cka); }
.tag-killersh-a { background: var(--tag-killer-a); }
.tag-killersh-b { background: var(--tag-killer-b); }
.tag-killercoda { background: var(--tag-killercoda); }
.tag-general    { background: var(--tag-general); }
.points-pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; background: var(--border); color: var(--fg); font-weight: 600; }
.id-pill { font-family: ui-monospace, monospace; color: var(--fg-muted); }

.exercise-docs { margin-bottom: 10px; font-size: 13px; }

.solve-on-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px;
  background: var(--bg-code); border: 1px solid var(--border);
  font-family: ui-monospace, monospace; font-size: 12px;
  color: var(--fg-muted);
}
.qnum-pill {
  display: inline-block;
  padding: 1px 9px; border-radius: 999px;
  background: var(--accent); color: var(--accent-fg);
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}
.exercise-docs { margin: 6px 0 12px; display: flex; flex-direction: column; gap: 2px; }
.exercise-docs-row { display: flex; align-items: baseline; gap: 6px; font-size: 13px; }
.exercise-docs-icon { color: var(--fg-muted); flex-shrink: 0; font-size: 12px; width: 14px; text-align: center; }
.task-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
  margin: 4px 0 6px;
}
.exercise-task { margin-bottom: 12px; }
.exercise-task :last-child { margin-bottom: 0; }
.exercise-task p { margin: 6px 0; }
.exercise-task ul, .exercise-task ol { padding-left: 22px; margin: 8px 0; }
.exercise-task li { margin: 3px 0; }
.exercise-task li > p { margin: 2px 0; }
.exercise-task blockquote {
  margin: 8px 0; padding: 8px 12px;
  border-left: 3px solid var(--border);
  color: var(--fg-muted);
}
.exercise-task blockquote.info-callout {
  border-left-color: var(--accent);
  background: rgba(9, 105, 218, 0.07);
  color: var(--fg);
  border-radius: 4px;
}
[data-theme="dark"] .exercise-task blockquote.info-callout {
  background: rgba(47, 129, 247, 0.12);
}
.exercise-task strong { font-weight: 700; }
.exercise-task .lab-context-label {
  display: block;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
  margin: 10px 0 4px;
}
.exercise-solution { margin-top: 8px; padding: 12px 14px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); }
.exercise-solution :first-child { margin-top: 0; }
.exercise-solution :last-child { margin-bottom: 0; }
.solution-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 14px; margin-top: 12px;
  border-radius: var(--radius);
  background: var(--bg-code); border: 1px solid var(--border);
  color: var(--fg);
  cursor: pointer; user-select: none;
  font: inherit; font-size: 12px; font-weight: 600;
  line-height: 1.4;
}
.solution-toggle:hover { background: var(--border); }
.solution-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.solution-toggle::before { content: "▸"; font-size: 10px; }
.exercise-card.solution-open .solution-toggle { background: var(--bg); border-color: var(--accent); color: var(--accent); }
.exercise-card.solution-open .solution-toggle::before { content: "▾"; }
.exercise-card:not(.solution-open) .exercise-solution { display: none; }

.muted { color: var(--fg-muted); }
.empty-state { padding: 40px; text-align: center; color: var(--fg-muted); }

/* Quiz */
.quiz-screen { max-width: 920px; margin: 24px auto; padding: 0 24px; }
.quiz-screen h2 { margin-top: 0; }
.quiz-screen fieldset {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px 14px; margin-bottom: 14px;
}
.quiz-screen legend { padding: 0 8px; font-weight: 600; }

/* Segmented chip groups — used by Quiz setup's Count / Time limit /
   Order / Solutions fieldsets. Each chip wraps a hidden radio + a
   visible <span>; the `:has(input:checked)` selector picks up the
   selected state without any JS. flex-wrap lets long groups
   gracefully break onto the next row on narrow viewports. */
.segmented-fieldset {
  /* Slightly tighter than the legacy fieldset since chips need no extra
     vertical breathing room. */
  padding: 8px 12px 12px !important;
}
.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.segmented-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  font-size: 13px;
  color: var(--fg);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.segmented-chip input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.segmented-chip:has(input:checked) {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.segmented-chip:has(input:checked) small { color: var(--accent-fg); opacity: 0.85; }
.segmented-chip:hover:not(:has(input:checked)) {
  background: var(--bg-elev);
}
.segmented-chip small {
  font-size: 11px;
  color: var(--fg-muted);
  margin-left: 2px;
}
.segmented-chip--with-input {
  padding-right: 6px;
}
.segmented-chip--with-input input[type="number"] {
  width: 4em;
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  font-size: 13px;
  margin-left: 4px;
}
.segmented-chip--with-input:has(input[type="radio"]:checked) input[type="number"] {
  background: var(--bg);
  color: var(--fg);
  border-color: var(--bg);
}

.quiz-actions { display: flex; gap: 12px; align-items: center; margin-top: 16px; }

/* ---------- Quiz mode landing page ---------- */
/* Primary CTA block — large "▶ Start a new quiz" button with subtitle. */
.quiz-home-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 20px 0 8px 0;
  margin-top: 12px;
  border-top: 1px solid var(--border);
}
.quiz-home-actions button {
  font-size: 16px;
  padding: 10px 22px;
}
.quiz-home-actions small { margin-left: 2px; }

/* Quick-start row — one-click presets sitting below the primary CTA. */
.quiz-home-quickstart {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 0 4px 0;
  margin-bottom: 8px;
}
.quiz-home-quickstart button { min-width: 0; }
.quiz-home-quickstart > span.muted { font-size: 12px; }
.quiz-home-quickstart button {
  padding: 6px 12px;
  font-size: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-elev);
  color: var(--fg);
  cursor: pointer;
}
.quiz-home-quickstart button:hover { background: var(--bg); border-color: var(--accent); }

/* Back-from-setup button — sits above the page title; same chrome as the
   Tools tab's .tools-back-to-list. */
.quiz-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 12px 0;
  padding: 6px 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  color: var(--fg);
}
.quiz-back-btn:hover { border-color: var(--accent); }
.quiz-progress { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.quiz-progress progress { flex: 1; height: 10px; }
#quiz-nav-toggle { white-space: nowrap; }
/* Utility row — 5 nav buttons (Prev / Flag / Reveal / Skip / Next).
   5-col equal-width grid on every viewport so desktop matches mobile's
   visual structure (user asked for desktop/mobile consistency). */
.quiz-controls {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  margin-top: 14px;
}
/* Grade row — three mutually-exclusive scoring buttons. Visually heavier
   than .quiz-controls (the row below it with Prev/Flag/Reveal/Skip/Next)
   since marking the question is the primary post-Check action. The
   `.is-current` modifier (set by syncQuizGradeButtons in app.js) fills the
   matching button so the user can see at a glance which bucket Check put
   them in — answers the "Partial 80/100, which button do I click?" UX
   question by showing them they're already marked. */
.quiz-grades {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 14px;
}
.quiz-grades button {
  padding: 10px 12px;
  font-size: 14px;
  font-weight: 600;
}
.quiz-grades .grade-got.is-current {
  background: var(--success);
  color: #fff;
  border-color: var(--success);
}
.quiz-grades .grade-partial.is-current {
  background: var(--warning);
  color: #fff;
  border-color: var(--warning);
}
.quiz-grades .grade-miss.is-current {
  background: var(--danger);
  color: #fff;
  border-color: var(--danger);
}
/* Session row — Save snapshot + End session. 2-col grid on desktop so
   they share a row; single column on phones (the narrow viewport
   override is in the mobile media query further below). */
.quiz-end-row {
  margin-top: 14px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* "Start new quiz" confirmation modal — reuses .overlay + .overlay-card,
   compact card with three stacked action buttons. */
#quiz-confirm-start-overlay { z-index: 1020; }
#quiz-confirm-start-overlay .quiz-confirm-start-card {
  max-width: 420px;
  width: 100%;
}
#quiz-confirm-start-overlay .quiz-confirm-start-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}
#quiz-confirm-start-overlay .quiz-confirm-start-actions button {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
}

/* Quiz navigator drawer (📋 Questions) — reuses .overlay + .overlay-card. */
#quiz-nav-overlay { z-index: 1010; }
#quiz-nav-overlay .quiz-nav-card {
  max-width: 520px;
  width: 100%;
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  overflow: hidden;
}
#quiz-nav-summary {
  font-size: 12px;
  color: var(--fg-muted);
  padding: 8px 12px;
  background: var(--bg-elev);
  border-radius: var(--radius);
  margin: 0 0 12px;
  letter-spacing: 0.04em;
}
.quiz-nav-grid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 6px;
  padding: 0 0 8px;
}
.qnav-cell {
  position: relative;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.qnav-cell:hover { border-color: var(--accent); }
.qnav-cell--current { border-color: var(--accent); border-width: 2px; }
.qnav-cell--got     { background: rgba(26, 127, 55, 0.20); border-color: var(--success); }
.qnav-cell--partial { background: rgba(154, 103, 0, 0.22); border-color: var(--warning); }
.qnav-cell--missed  { background: rgba(209, 36, 47, 0.18); border-color: var(--danger); }
.qnav-cell--skipped { background: var(--bg-elev); color: var(--fg-muted); }
.qnav-flag {
  position: absolute;
  top: -4px; right: -2px;
  font-size: 10px;
  pointer-events: none;
}
.quiz-nav-legend {
  display: flex; flex-wrap: wrap; gap: 6px 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--fg-muted);
  align-items: center;
}
.quiz-nav-legend .qnav-cell {
  width: 22px; aspect-ratio: 1/1;
  font-size: 11px;
  cursor: default;
}
.quiz-nav-legend .qnav-cell:hover { border-color: var(--border); }
@media (max-width: 768px) {
  #quiz-nav-overlay {
    align-items: flex-end;
    padding: 0;
  }
  #quiz-nav-overlay .quiz-nav-card {
    max-height: 92vh;
    border-radius: var(--radius) var(--radius) 0 0;
    width: 100%;
  }
}

#quiz-summary-list { padding-left: 28px; }
#quiz-summary-list li { margin-bottom: 6px; }
#quiz-summary-list .status-got { color: var(--success); font-weight: 600; }
#quiz-summary-list .status-missed { color: var(--danger); font-weight: 600; }
#quiz-summary-list .status-skipped { color: var(--warning); font-weight: 600; }
#quiz-summary-list .status-flagged { color: var(--accent); font-weight: 600; }

#quiz-summary-stats {
  display: flex; gap: 20px; padding: 14px 18px; margin-bottom: 14px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius);
}
#quiz-summary-stats .stat { display: flex; flex-direction: column; align-items: center; }
#quiz-summary-stats .stat-value { font-size: 24px; font-weight: 700; }
#quiz-summary-stats .stat-label { font-size: 12px; color: var(--fg-muted); }

/* Footer */
footer { padding: 12px 20px; border-top: 1px solid var(--border); background: var(--bg-elev); text-align: center; font-size: 12px; }

/* Mobile */
@media (max-width: 768px) {
  /* Header compaction */
  .brand strong { display: none; }
  #app-header { padding: 8px 12px; gap: 8px; }
  .mode-tab { padding: 4px 8px; font-size: 13px; }

  /* Filter bar: not sticky; show compact toolbar; full filter content collapsed */
  #filter-bar {
    position: static;
    padding: 8px 12px;
    z-index: auto;
  }
  .mobile-toolbar {
    display: flex; align-items: center; gap: 6px;
    flex-wrap: nowrap;
  }
  .mobile-toolbar #filter-search-mobile {
    flex: 1; min-width: 0;
  }
  .mobile-toolbar button {
    white-space: nowrap;
    padding: 5px 10px;
    font-size: 13px;
  }
  .mobile-toolbar .mobile-stats { display: none; }
  .mobile-toolbar button[aria-expanded="true"] {
    background: var(--accent);
    color: var(--accent-fg);
    border-color: var(--accent);
  }

  #filter-bar-content {
    display: none;
    flex-direction: column; align-items: stretch;
    gap: 8px;
    padding: 12px 0 0;
    margin-top: 10px;
    border-top: 1px solid var(--border);
  }
  #filter-bar.expanded #filter-bar-content { display: flex; }
  #filter-bar-content #filter-search { width: 100%; }
  #filter-stats { margin-left: 0; }

  /* Layout: 1 column, sidebar collapsed by default */
  .layout { grid-template-columns: 1fr; }
  #sidebar {
    display: none;
    position: static; max-height: none; top: 0;
    border-right: none; border-bottom: 1px solid var(--border);
  }
  #sidebar.expanded { display: block; }

  /* Main: less horizontal padding on mobile */
  #main { padding: 14px 12px; }
  .exercise-card { padding: 12px 14px; }

  /* Browse cards: keep all content within the card on narrow viewports.
     Without these, long inline <code>, URLs, or markdown tables push the
     card past the viewport and cause a body-level horizontal scroll. */
  .exercise-title { min-width: 0; }
  .exercise-card { overflow: hidden; }
  .exercise-task,
  .exercise-solution,
  .exercise-docs {
    overflow-wrap: anywhere;
    word-break: break-word;
  }
  /* <pre> blocks keep their own overflow-x:auto for terminal-faithful long
     commands; just don't let them push the card wider than the viewport. */
  .exercise-card pre,
  .exercise-card table {
    max-width: 100%;
  }
  /* Wide markdown tables get their own horizontal scroller. */
  .exercise-task table,
  .exercise-solution table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Belt-and-suspenders: clip any residual horizontal overflow at the main
     scroller and at the document root. overflow-x: clip (vs hidden) doesn't
     create a scroll context, so position:fixed elements like the bottom tab
     bar and update banner still anchor to the viewport. */
  #main { max-width: 100vw; overflow-x: clip; }
  html, body { overflow-x: clip; }
}

/* ============================================================ */
/* 📖 Docs view — kubernetes.io subset tree + detail             */
/* ============================================================ */

.docs-layout {
  display: grid;
  grid-template-columns: 360px 1fr;
  min-height: calc(100vh - 110px);
}

.docs-tree {
  border-right: 1px solid var(--border);
  background: var(--bg-elev);
  padding: 12px 14px;
  overflow-y: auto;
  max-height: calc(100vh - 56px);
  position: sticky;
  top: 56px;
}
.docs-tree-toolbar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 4px 0 12px;
  position: sticky;
  top: 0;
  background: var(--bg-elev);
  z-index: 2;
}
.docs-tree-toolbar input {
  width: 100%;
}
#docs-stats {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* Tree node (internal — has children) */
.docs-node {
  margin: 1px 0;
}
.docs-node > summary {
  list-style: none;
  cursor: pointer;
  padding: 3px 6px;
  border-radius: 4px;
  display: flex; align-items: center; gap: 6px;
  font-size: 13px;
}
.docs-node > summary::-webkit-details-marker { display: none; }
.docs-node > summary::before {
  content: "▸";
  flex-shrink: 0;
  color: var(--fg-muted);
  width: 10px;
  font-size: 10px;
}
.docs-node[open] > summary::before { content: "▾"; }
.docs-node > summary:hover { background: var(--bg); }
.docs-node > summary > .label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.docs-node > summary > .count {
  flex-shrink: 0;
  color: var(--fg-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.docs-node[data-depth="0"] > summary { font-weight: 600; }
.docs-node[data-depth="1"] > summary { color: var(--fg); }
.docs-node[data-depth="2"] > summary { color: var(--fg-muted); }

/* Indentation for nested nodes */
.docs-node .docs-node,
.docs-node .docs-leaf {
  margin-left: 14px;
}

/* Tree leaf (docs page) */
.docs-leaf {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 8px 3px 22px;
  border: none; background: none;
  width: calc(100% - 14px);
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
  font-size: 12px;
  color: var(--fg);
  font: inherit;
}
.docs-leaf:hover { background: var(--bg); color: var(--accent); }
.docs-leaf.active {
  background: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
}
.docs-leaf .label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.docs-leaf .ex-count {
  flex-shrink: 0;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--bg-code);
  color: var(--fg-muted);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
.docs-leaf.active .ex-count {
  background: rgba(255,255,255,0.25);
  color: var(--accent-fg);
}
.docs-leaf.search-hidden,
.docs-node.search-hidden { display: none; }

/* Detail pane */
.docs-detail {
  padding: 24px 28px;
  overflow-y: auto;
  max-height: calc(100vh - 56px);
}
.docs-detail h2 { margin: 0 0 8px; font-size: 22px; }
.docs-detail .breadcrumb {
  font-size: 13px;
  color: var(--fg-muted);
  margin-bottom: 14px;
}
.docs-detail .breadcrumb span + span::before {
  content: "›";
  margin: 0 6px;
  color: var(--border);
}
.docs-detail .open-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: var(--radius);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  font-size: 13px;
  text-decoration: none;
  color: var(--fg);
}
.docs-detail .open-link:hover {
  background: var(--border);
  text-decoration: none;
}
.docs-detail .open-link::after {
  content: "↗";
  font-size: 11px;
  color: var(--fg-muted);
}
.docs-detail .section-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--fg-muted);
  margin: 28px 0 10px;
}

/* Linked-exercise list */
.docs-ex-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.docs-ex-list button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  text-align: left;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  color: var(--fg);
}
.docs-ex-list button:hover {
  background: var(--bg-code);
  border-color: var(--accent);
}
.docs-ex-list .ex-title {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Mobile: collapse tree under the detail */
@media (max-width: 768px) {
  .docs-layout {
    grid-template-columns: 1fr;
  }
  .docs-tree {
    position: relative;
    max-height: 40vh;
    border-right: none;
    border-bottom: 1px solid var(--border);
    top: 0;
  }
  .docs-detail {
    max-height: none;
  }
}

/* ============================================================ */
/* Keyboard shortcuts overlay + focused-card indicator           */
/* ============================================================ */

.overlay {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.overlay[hidden] { display: none; }      /* defeat the .overlay display:flex when hidden=true */
.overlay-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 32px rgba(0,0,0,0.25);
  max-width: 560px; width: 100%;
  max-height: 80vh; overflow-y: auto;
  padding: 20px 24px;
}
.overlay-card header {
  /* Pin the header to the top of the scrolling card so the close button
     stays reachable even after the user has scrolled to the bottom of a
     long modal (Settings / Report / etc.). The negative top + horizontal
     margins extend the sticky band out to the card's edges so the bg
     hides scrolling content underneath the title, then padding restores
     the internal layout. */
  position: sticky;
  top: -20px;
  margin: -20px -24px 12px;
  padding: 16px 24px 12px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
}
.overlay-card h2 { margin: 0; font-size: 18px; }

.shortcut-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.shortcut-table th {
  text-align: left; padding: 14px 0 4px;
  border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
}
.shortcut-table td { padding: 5px 12px 5px 0; vertical-align: top; }
.shortcut-table td:first-child { white-space: nowrap; width: 1px; }

kbd {
  display: inline-block;
  padding: 1px 6px; min-width: 16px; text-align: center;
  background: var(--bg-elev); border: 1px solid var(--border);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 11px; line-height: 1.5;
  color: var(--fg);
  box-shadow: 0 1px 0 var(--border);
}

/* Focused card indicator (Browse mode, j/k navigation) */
.exercise-card.kbd-focused {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  scroll-margin-top: 80px;
}

/* ============================================================ */
/* Print stylesheet — clean printable Browse view                */
/* ============================================================ */

@media print {
  /* Force light, ink-friendly colors regardless of theme */
  :root, [data-theme="dark"] {
    --bg: #ffffff !important;
    --bg-elev: #ffffff !important;
    --bg-code: #f5f5f5 !important;
    --fg: #000000 !important;
    --fg-muted: #555555 !important;
    --border: #cccccc !important;
    --accent: #0050aa !important;
  }

  body, html {
    background: white !important;
    color: black !important;
  }

  /* Hide interactive chrome */
  #app-header,
  #filter-bar,
  #sidebar,
  footer,
  .icon-btn,
  .mode-tabs,
  .solution-toggle,
  .exercise-tools,
  .copy-btn,
  #help-overlay,
  #view-quiz,
  #view-docs {
    display: none !important;
  }

  /* Layout reset: main fills the page */
  .layout {
    display: block !important;
  }
  #main {
    padding: 0 !important;
    max-height: none !important;
    overflow: visible !important;
  }
  .view {
    display: block !important;
  }
  #view-browse {
    display: block !important;
  }

  /* Expand every solution */
  .exercise-card .exercise-solution {
    display: block !important;
  }

  /* Card formatting for paper */
  .exercise-card {
    background: white !important;
    border: 1px solid #cccccc !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 10px 14px !important;
    margin: 0 0 14px !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .exercise-card.done {
    border-left: 4px solid #1a7f37 !important;
  }
  .exercise-title { font-size: 14px !important; }
  .exercise-meta { font-size: 11px !important; gap: 6px !important; }

  /* Tag pills: convert filled chip to text-only on paper */
  .tag-pill, .points-pill, .qnum-pill {
    background: transparent !important;
    color: black !important;
    border: 1px solid #888 !important;
    padding: 0 4px !important;
  }
  .solve-on-chip {
    background: transparent !important;
    border: 1px solid #888 !important;
  }

  /* Code blocks */
  pre, code {
    background: #f5f5f5 !important;
    border: 1px solid #dddddd !important;
    color: black !important;
    box-shadow: none !important;
    page-break-inside: avoid;
    break-inside: avoid;
  }
  pre { padding: 8px 10px !important; }

  /* Heading levels print nicer */
  h2 { font-size: 16px !important; margin-top: 14px !important; }
  h3 { font-size: 13px !important; }

  /* Hide tree-domain h3 markers that mention `muted` since they look odd */
  .muted { color: #555 !important; }

  /* Links print as URL footnotes for offline use (uncomment if desired) */
  /* a[href]::after { content: " (" attr(href) ")"; font-size: 10px; color: #666; } */

  /* Show a footer note at top of first page */
  @page { margin: 18mm 14mm; }
}

/* ============================================================ */
/* Auto-grading: answer box + verdict + settings                 */
/* ============================================================ */

.answer-box {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.answer-label {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
  margin-bottom: 6px;
}
.answer-label-text { flex: 1; }
.answer-expand {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 2px 8px;
  font-size: 14px; line-height: 1;
  color: var(--fg-muted);
  cursor: pointer;
}
.answer-expand:hover,
.answer-expand:focus-visible {
  background: var(--bg-elev);
  color: var(--fg);
  border-color: var(--border);
  outline: none;
}
/* Hidden until the answer editor enters fullscreen — keeps the inline label
   row tidy on browse / quiz cards. Lets a typing user pull up Tools without
   exiting fullscreen. */
.answer-tools-btn {
  display: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 2px 8px;
  font-size: 14px; line-height: 1;
  color: var(--fg-muted);
  cursor: pointer;
}
.answer-tools-btn:hover,
.answer-tools-btn:focus-visible {
  background: var(--bg-elev);
  color: var(--fg);
  border-color: var(--border);
  outline: none;
}
.answer-box.answer-fullscreen .answer-tools-btn { display: inline-block; }
/* Surfaced when the lazy CodeMirror upgrade fails (e.g. CDN hiccup, esm.sh
   bundle dedup miss). Sits inside .answer-label next to ⛶, hover for the
   underlying error message. */
.cm-fail-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 8px;
  padding: 1px 6px;
  font-size: 11px;
  color: var(--warn, #c97);
  background: color-mix(in srgb, var(--warn, #c97) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn, #c97) 35%, transparent);
  border-radius: var(--radius);
  cursor: help;
}
/* Mirror of .answer-tools-btn for the per-card 📝 Task drawer trigger. */
.answer-task-btn {
  display: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 2px 8px;
  font-size: 14px; line-height: 1;
  color: var(--fg-muted);
  cursor: pointer;
}
.answer-task-btn:hover,
.answer-task-btn:focus-visible {
  background: var(--bg-elev);
  color: var(--fg);
  border-color: var(--border);
  outline: none;
}
.answer-box.answer-fullscreen .answer-task-btn { display: inline-block; }
/* Same hidden-until-fullscreen pattern for the 💡 Solution drawer trigger. */
.answer-solution-btn {
  display: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 2px 8px;
  font-size: 14px; line-height: 1;
  color: var(--fg-muted);
  cursor: pointer;
}
.answer-solution-btn:hover,
.answer-solution-btn:focus-visible {
  background: var(--bg-elev);
  color: var(--fg);
  border-color: var(--border);
  outline: none;
}
.answer-box.answer-fullscreen .answer-solution-btn { display: inline-block; }
.answer-textarea {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px; line-height: 1.5;
  padding: 8px 10px;
  background: var(--bg-code);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  resize: vertical; min-height: 80px;
}
.answer-textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px;
  border-color: var(--accent);
}
.answer-cm {
  min-height: 96px;
  max-height: 360px;
  /* No outer overflow — CM's .cm-scroller handles scrolling internally
     (height: 100% theme rule in app.js makes it fill this container). */
}
.answer-box.answer-fullscreen .answer-cm {
  max-height: none;
  flex: 1;
  min-height: 60vh;
}
.answer-box.answer-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 1000;
  margin: 0;
  border-radius: 0;
  background: var(--bg);
  padding: 20px 24px;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
.answer-box.answer-fullscreen .answer-textarea {
  flex: 1; min-height: 60vh;
}
body.answer-fullscreen-active { overflow: hidden; }

/* Quiz-only control strip rendered inside the answer-box. Hidden until the
   user maximises the editor; surfaces Prev/Next/Got/Missed/Flag/Reveal +
   the question navigator so the user keeps full quiz control while editing
   long YAML / kubectl answers without exiting fullscreen. */
.answer-fullscreen-quizbar { display: none; }
.answer-box.answer-fullscreen .answer-fullscreen-quizbar {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 0 4px 0;
  border-top: 1px solid var(--border);
  margin-top: 8px;
}
.answer-fullscreen-quizbar .qbar-grade-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
/* Utility row mirrors the regular Quiz controls' grid full-stretch
   pattern (and the grade row above) — 6 buttons (📋 Questions / Prev /
   Flag / Reveal / Skip / Next) each take 1/6 of the container.
   Was `flex-wrap` which left desktop buttons sized to content and
   visually disagreed with the full-stretch grade row above it. */
.answer-fullscreen-quizbar .qbar-util-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 6px;
  align-items: center;
}
.answer-fullscreen-quizbar button {
  padding: 7px 12px;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-elev);
  color: var(--fg);
  cursor: pointer;
}
.answer-fullscreen-quizbar .qbar-grade-row button {
  font-weight: 600;
  padding: 9px 8px;
}
.answer-fullscreen-quizbar button:hover { background: var(--bg); }
.answer-fullscreen-quizbar button.grade-got {
  border-color: var(--success); color: var(--success);
}
.answer-fullscreen-quizbar button.grade-partial {
  border-color: var(--warning); color: var(--warning);
}
.answer-fullscreen-quizbar button.grade-miss {
  border-color: var(--danger);  color: var(--danger);
}
/* `.is-current` fills the matching grade button when the current
   question's quiz status equals that grade — mirrors the regular
   Quiz controls' filled-pill highlight (see `.quiz-grades` rules
   above). syncQuizGradeButtons() applies/removes this class. */
.answer-fullscreen-quizbar button.grade-got.is-current {
  background: var(--success); color: #fff; border-color: var(--success);
}
.answer-fullscreen-quizbar button.grade-partial.is-current {
  background: var(--warning); color: #fff; border-color: var(--warning);
}
.answer-fullscreen-quizbar button.grade-miss.is-current {
  background: var(--danger); color: #fff; border-color: var(--danger);
}

/* Tools drawer — slides above the fullscreen answer overlay (z-index 1000)
   so the user can pull up kubectl explain / kubectl -h without exiting
   fullscreen. The card on small screens is a bottom sheet that fills 92vh. */
#tools-drawer-overlay { z-index: 1010; }
#tools-drawer-overlay .tools-drawer-card {
  max-width: 900px;
  width: 100%;
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  overflow: hidden;
}
#tools-drawer-host {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* #view-tools normally is a page-width view; inside the drawer it must
   flex-fill the host. */
#view-tools.in-drawer {
  display: flex;
  flex: 1;
  min-height: 0;
  flex-direction: column;
  margin: 0;
  padding: 0;
}
#view-tools.in-drawer .tools-panel {
  flex: 1;
  min-height: 0;
  /* Override the main-view 260+1fr grid — drawer is too narrow for it.
     Stack vertically regardless of viewport width: kind list on top,
     detail beneath. */
  display: flex;
  flex-direction: column;
  gap: 0;
}
/* Restore [hidden] semantics — the display:flex above is at higher
   specificity than the global `.tools-panel[hidden] { display: none }`
   rule, so without this both Explain + kubectl-h panels would render at
   once inside the drawer and tab switching would look broken. */
#view-tools.in-drawer .tools-panel[hidden] { display: none; }
#view-tools.in-drawer .tools-tree {
  /* Sticky positioning is anchored to the main page's scroll container;
     inside the drawer it locks to absolute viewport coordinates and
     scrolls out of the card. Reset to normal flow. */
  position: static;
  top: auto;
  max-height: 38vh;
  overflow-y: auto;
  border-bottom: 1px solid var(--border);
  padding: 4px 0 10px;
  padding-right: 0;
  margin-bottom: 8px;
}
#view-tools.in-drawer .tools-detail {
  max-width: none;
  overflow-y: auto;
  padding: 8px 0 4px;
}
#view-tools.in-drawer .tools-subtabs {
  /* Tab strip + version picker + meta is too wide for a phone — let it
     wrap so nothing overflows the drawer card. */
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 0 8px;
}
/* Tools/Explain search + result-list overrides for the drawer. The desktop
   `.tools-tree` selectors leak rules (sticky positioning, padding-right) that
   trash the visual rhythm inside the narrow drawer card; restore tight,
   ellipsis-safe layout here. */
#view-tools.in-drawer #tools-explain-search,
#view-tools.in-drawer #tools-kubectl-search {
  width: 100%;
  min-width: 0;
  margin-bottom: 8px;
}

/* In-detail filter input — sits at the top of Explain and kubectl -h detail
   panes, lets the user grep inside long field lists / help-text blocks. */
.tools-detail-filter {
  width: 100%;
  min-width: 0;
  padding: 6px 10px;
  margin: 8px 0 10px 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  font: inherit;
  box-sizing: border-box;
}
#view-tools.in-drawer #tools-kind-list {
  /* Anything inside is allowed to shrink rather than overflow the card. */
  min-width: 0;
}
#view-tools.in-drawer #tools-kind-list button {
  max-width: 100%;
  min-width: 0;
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 6px 8px;
  font-size: 13px;
  line-height: 1.35;
}
#view-tools.in-drawer #tools-kind-list .kind-shortnames {
  font-size: 11px;
  opacity: 0.7;
}
@media (max-width: 768px) {
  #tools-drawer-overlay {
    align-items: flex-end;
    padding: 0;
  }
  #tools-drawer-overlay    .tools-drawer-card,
  #task-drawer-overlay     .tools-drawer-card,
  #solution-drawer-overlay .tools-drawer-card {
    max-height: 92vh;
    border-radius: var(--radius) var(--radius) 0 0;
    width: 100%;
  }
  #task-drawer-overlay     { align-items: flex-end; padding: 0; }
  #solution-drawer-overlay { align-items: flex-end; padding: 0; }
}
/* Task drawer body — reuses .tools-drawer-card sizing; only the host
   content needs comfortable reading layout. */
#task-drawer-overlay { z-index: 1010; }
#task-drawer-overlay #task-drawer-host {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px 16px 16px;
  line-height: 1.55;
}
#task-drawer-overlay .task-drawer-docs {
  margin: 0 0 12px;
  padding: 8px 10px;
  background: var(--bg-elev);
  border-radius: var(--radius);
}
#task-drawer-overlay .task-drawer-task { font-size: 14px; }

/* Solution drawer — same shape as the task drawer; opens above fullscreen
   so the reference solution is reachable from the maximised editor. */
#solution-drawer-overlay { z-index: 1010; }
#solution-drawer-overlay #solution-drawer-host {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px 16px 16px;
  line-height: 1.55;
}
#solution-drawer-overlay .solution-drawer-locked {
  padding: 16px;
  text-align: center;
  color: var(--fg-muted);
  font-size: 13px;
}
#solution-drawer-overlay .solution-drawer-locked button {
  margin-top: 12px;
}
.answer-actions {
  display: flex; align-items: center; gap: 8px;
  margin-top: 8px; flex-wrap: wrap;
}
.answer-actions .answer-hint {
  font-size: 11px; margin-left: auto;
}
.check-btn[disabled] { opacity: 0.6; cursor: progress; }

.verdict-slot:empty { display: none; }
.verdict {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid;
  background: var(--bg);
}
.verdict-correct   { border-color: var(--success); background: rgba(26, 127, 55, 0.07); }
.verdict-partial   { border-color: var(--warning); background: rgba(154, 103, 0, 0.08); }
.verdict-incorrect { border-color: var(--danger);  background: rgba(209, 36, 47, 0.07); }
.verdict-error     { border-color: var(--danger);  background: rgba(209, 36, 47, 0.10); color: var(--fg); }
.verdict-error-detail {
  margin: 6px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 8px;
  max-height: 300px;
  overflow: auto;
}
.verdict-truncated-note {
  margin: 4px 0 8px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--warning);
  border-left: 3px solid var(--warning);
  padding: 4px 0 4px 8px;
}
[data-theme="dark"] .verdict-correct   { background: rgba(26, 127, 55, 0.15); }
[data-theme="dark"] .verdict-partial   { background: rgba(154, 103, 0, 0.18); }
[data-theme="dark"] .verdict-incorrect { background: rgba(209, 36, 47, 0.16); }

.verdict-head {
  display: flex; justify-content: space-between; align-items: center;
  font-weight: 700; font-size: 14px;
  margin-bottom: 4px;
}
.verdict-correct   .verdict-mark { color: var(--success); }
.verdict-partial   .verdict-mark { color: var(--warning); }
.verdict-incorrect .verdict-mark { color: var(--danger); }
.verdict-score {
  font-family: ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 13px; color: var(--fg-muted);
}
.verdict-summary {
  font-size: 13px;
  margin: 4px 0 6px;
}
.verdict-section-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.5px; color: var(--fg-muted);
  margin-top: 8px;
}
.verdict-list {
  margin: 4px 0 4px;
  padding-left: 20px;
  font-size: 13px;
}
.verdict-list li { margin: 2px 0; }

/* Report-a-reference-solution link inside the verdict block */
.verdict-report-link {
  display: block;
  margin-top: 10px;
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 6px 10px;
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
  text-align: left;
  width: 100%;
}
.verdict-report-link:hover,
.verdict-report-link:focus-visible {
  color: var(--fg);
  border-color: var(--accent);
  background: var(--bg-elev);
  outline: none;
}
.solution-report-link {
  display: inline-block;
  margin-top: 10px;
  background: transparent;
  border: 0;
  padding: 4px 0;
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
}
.solution-report-link:hover,
.solution-report-link:focus-visible {
  color: var(--accent);
  text-decoration: underline;
  outline: none;
}
/* Variant placed below the task body so it sits inline with the question. */
.task-report-link {
  margin: 4px 0 12px;
}

/* Mode-toggle for the shared report modal: solution-fix vs task/docs-fix.
   The mode is set via `#report-overlay[data-report-mode="task|solution"]`
   when openFixReportModal opens; CSS hides whichever blocks don't apply. */
#report-overlay[data-report-mode="task"] .solution-mode-only { display: none; }
#report-overlay:not([data-report-mode="task"]) .task-mode-only { display: none; }
/* `:not([hidden])` is load-bearing — without it the `display: flex` rule
   ties on specificity with [hidden] and wins by cascade order, defeating
   `block.hidden = true` from syncTaskSubBlocks. Symptom that prompted
   this: user picked unclear-task and still saw Suggested URL + Existing
   link fields. */
.report-suggested-url-block:not([hidden]),
.report-existing-link-block:not([hidden]) {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.report-suggested-url-block input[type="url"],
.report-suggested-url-block select,
.report-existing-link-block select {
  width: 100%;
  padding: 6px 8px;
  background: var(--bg-code);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 13px;
}
.report-task-body-md {
  max-height: 160px;
  overflow: auto;
  padding: 8px 10px;
  background: var(--bg-elev);
  border-radius: var(--radius);
  font-size: 13px;
  line-height: 1.5;
}
.report-task-docs-label {
  margin-top: 8px;
  font-size: 12px;
  color: var(--fg-muted);
}
.report-task-docs-list {
  margin: 4px 0 0;
  padding-left: 18px;
  font-size: 13px;
}
.report-task-docs-list li { margin: 2px 0; }

/* Report-overlay modal */
#report-overlay .overlay-card { max-width: 640px; }
/* Close button — square 36x36 tap target, visible at rest (the previous
   version had transparent bg + transparent border so it only appeared
   on hover; mobile has no hover and the button read as a plain glyph). */
.overlay-close {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  color: var(--fg-muted);
  cursor: pointer;
  padding: 0;
  line-height: 1;
}
.overlay-close:hover,
.overlay-close:focus-visible {
  background: var(--bg);
  border-color: var(--accent);
  color: var(--fg);
}
.overlay-close:active {
  background: color-mix(in srgb, var(--bg-elev) 70%, var(--fg));
}
.report-context {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
  margin-bottom: 10px;
  font-size: 12px;
}
.report-context-row {
  display: flex; gap: 8px; align-items: baseline;
  padding: 2px 0;
}
.report-context-label {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
  min-width: 56px;
}
.report-context-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--accent);
}
.report-context-title { flex: 1; }
.report-collapsible {
  margin: 8px 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 10px;
  background: var(--bg-code);
}
.report-collapsible summary {
  cursor: pointer;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
  padding: 2px 0;
}
.report-collapsible[open] summary { margin-bottom: 6px; }
.report-readonly {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--fg);
}
#report-verdict-body ul { padding-left: 20px; margin: 4px 0; }
#report-verdict-body div { margin: 2px 0; font-size: 12px; }
.report-field-label {
  display: block;
  margin: 10px 0 4px;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.6px; color: var(--fg-muted);
}
.report-required { color: var(--danger); }
.report-type-group {
  display: flex; flex-direction: column;
  gap: 4px;
  margin: 4px 0 6px;
}
.report-type-group label {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 8px;
  border-radius: var(--radius);
  font-size: 13px; line-height: 1.4;
  color: var(--fg-muted);
  cursor: pointer;
}
.report-type-group label:hover { background: var(--bg-elev); color: var(--fg); }

/* Inline help block right under the radio group — shows the currently-
   selected type's whatsWrong + suggested so the user knows what they're
   picking without context-switching into Help mode. Updated live on
   selection change by renderReportTypeHelp. */
.report-type-help {
  margin: 0 0 10px;
  padding: 10px 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--fg);
}
.report-type-help[hidden] { display: none; }
.report-type-help .report-type-help-row + .report-type-help-row { margin-top: 6px; }
.report-type-help .report-type-help-row strong { color: var(--fg); }
.report-type-help .report-type-help-body { margin: 0; color: var(--fg-muted); }
.report-type-group input[type="radio"] {
  margin-top: 2px;
  accent-color: var(--accent);
  flex-shrink: 0;
}
.report-type-group label code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  background: var(--bg-elev);
  padding: 0 4px;
  border-radius: 3px;
}
/* Checked highlight — :has() works in modern Safari/Chrome/Firefox. */
.report-type-group label:has(input[type="radio"]:checked) {
  color: var(--fg);
  font-weight: 600;
  background: var(--bg-elev);
}
#report-additional {
  width: 100%;
  font-family: inherit;
  font-size: 13px; line-height: 1.5;
  padding: 8px 10px;
  background: var(--bg-code);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  resize: vertical;
}
#report-additional:focus {
  outline: 2px solid var(--accent); outline-offset: -1px;
  border-color: var(--accent);
}
/* Additional-context state badge: '(optional)' muted, or '* required'
   coloured red when the selected type's whatsWrong is null (= `other`).
   Swap is driven by syncAdditionalContextState in docs/app.js. */
.report-additional-state {
  font-size: 11px;
  margin-left: 4px;
}
.report-additional-state.is-required {
  color: var(--danger);
  font-weight: 600;
}
.report-include-toggle {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--fg-muted);
  margin: 10px 0 6px;
}
.report-status {
  font-size: 12px;
  min-height: 1em;
  margin: 6px 0;
}
.report-actions {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: flex-end;
  margin-top: 10px;
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
.report-submit-block {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}
.report-title-row {
  display: flex; gap: 6px; align-items: stretch;
  margin: 4px 0 8px;
}
.report-title-row input {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  padding: 6px 8px;
  background: var(--bg-code);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.report-title-row button { white-space: nowrap; }
.report-mobile-hint {
  font-size: 12px;
  line-height: 1.45;
  padding: 8px 10px;
  background: var(--bg-elev);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  margin: 6px 0 4px;
}
.report-mobile-hint strong { color: var(--fg); }
.report-mobile-hint em { color: var(--fg); font-style: normal; font-weight: 600; }

/* Settings overlay */
#settings-overlay .overlay-card,
#privacy-overlay  .overlay-card {
  max-width: 520px;
}
.settings-section { margin: 14px 0 10px; }
.settings-label {
  display: block;
  font-size: 12px; font-weight: 600;
  color: var(--fg-muted);
  margin-bottom: 6px;
}
.provider-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
/* Provider card — three independent visual signals:
   1. Active (the one LLM Check actually uses) — gold left bar + tinted bg + ★ Active pill
   2. Configured (has saved credentials) — small green dot top-right
   3. Selected for editing (which slot the form below is bound to) — subtle outline only
   Previously these three were conveyed with overlapping borders / backgrounds / icons
   (blue bg for selected, green border for configured, "★ active" text for active) which
   was the "fragmented" UX the user flagged. */
.provider-card {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px 10px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  background: var(--bg);
}
.provider-card:hover { background: var(--bg-elev); }
.provider-card input { margin: 0; }
.provider-card > span:not(.provider-badge) { font-weight: 600; }
.provider-card small { color: var(--fg-muted); font-size: 11px; }

/* (1) Selected for editing — subtle outline ring only, no full-row tint */
.provider-card:has(input:checked) {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* (2) Configured — small green dot top-right */
.provider-card.configured::after {
  content: "";
  position: absolute;
  top: 8px; right: 8px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--success);
}

/* (3) Active — left-edge gold bar + tinted background + ★ Active pill at right */
.provider-card.active {
  background: color-mix(in srgb, var(--warning) 8%, var(--bg));
  border-left-color: var(--warning);
}
.provider-card .provider-badge {
  margin-left: auto;
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
  color: transparent;            /* default: invisible — only painted on active */
}
.provider-card.active .provider-badge {
  color: var(--warning);
  font-weight: 700;
}
.provider-card.active .provider-badge::before { content: "★ Active"; }

/* "⚡ Use" button — only renders for configured non-active providers,
   gives a one-click way to switch active without going through the
   form below. */
.provider-card .use-active-btn {
  font-size: 11px;
  padding: 3px 9px;
  background: transparent;
  border: 1px solid var(--accent);
  border-radius: 999px;
  color: var(--accent);
  cursor: pointer;
  display: none;                 /* default hidden — JS only shows on configured non-active */
}
.provider-card .use-active-btn:hover {
  background: var(--bg-elev);
}
.provider-card.configured:not(.active) .use-active-btn { display: inline-block; }
.provider-card.configured.active .provider-badge { margin-left: auto; }
/* When active row shows its ★ Active pill, the (hidden) Use button still
   eats no width thanks to display:none. */
#settings-providers-count,
#settings-grading-count {
  font-size: 11px;
  font-weight: 400;
  color: var(--fg-muted);
  margin-left: 6px;
}

/* Settings dialog subtabs — same visual pattern as .tools-subtabs. */
.settings-subtabs {
  display: flex;
  gap: 6px;
  align-items: center;
  margin: 0 0 14px;
  border-bottom: 1px solid var(--border);
}
.settings-subtabs button[data-settings-tab] {
  background: transparent;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 6px 14px;
  margin-bottom: -1px;
  color: var(--fg);
  cursor: pointer;
}
.settings-subtabs button[data-settings-tab].active {
  background: var(--bg);
  border-color: var(--border);
  font-weight: 600;
}
.settings-tab-panel[hidden] { display: none; }

@media (max-width: 480px) {
  .settings-subtabs button[data-settings-tab] { padding: 4px 8px; font-size: 13px; }
  #settings-grading-count { display: none; }
}

.settings-row {
  margin: 12px 0;
  display: flex; flex-direction: column; gap: 4px;
}
.settings-row input,
.settings-row select {
  width: 100%;
  padding: 6px 10px;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font: inherit;
}
.settings-row small { color: var(--fg-muted); font-size: 11px; }

.settings-actions {
  display: flex; gap: 10px; align-items: center;
  margin-top: 16px;
}
.settings-actions .muted { margin-left: auto; font-size: 12px; }

.settings-backup, .settings-gist {
  margin: 14px 0;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* Header ☁ sync popover */
.sync-menu-wrap { position: relative; display: inline-block; }
#sync-toggle { position: relative; }
.sync-dot {
  position: absolute;
  top: 4px; right: 4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--bg);
  pointer-events: none;
}
.sync-dot--in-flight {
  background: var(--accent);
  animation: sync-dot-pulse 1.4s ease-in-out infinite;
}
.sync-dot--ok    { background: var(--success); }
.sync-dot--error { background: var(--danger); }
/* Auto-sync timer is armed — slow accent pulse. Distinct from --in-flight
   (faster + scaled) so the user can read "pending" vs "actually pushing". */
.sync-dot--pending {
  background: var(--accent);
  animation: sync-dot-arm 2s ease-in-out infinite;
  opacity: 0.7;
}
@keyframes sync-dot-pulse {
  0%, 100% { opacity: 0.4; transform: scale(0.85); }
  50%      { opacity: 1;   transform: scale(1.1); }
}
@keyframes sync-dot-arm {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 0.9; }
}
/* Diagnostic top line in the ☁ popover — always-visible state line that
   tells you exactly why auto-push is firing or not. */
.sync-diag-line {
  font-size: 11.5px;
  color: var(--fg-muted);
  border-bottom: 1px dashed var(--border);
  padding-bottom: 4px;
  margin-bottom: 4px;
}
.sync-menu {
  position: absolute; right: 0; top: calc(100% + 6px);
  min-width: 280px; padding: 12px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  /* 1100 = above .answer-fullscreen (1000) and .tools-drawer (1010) so the
     quizbar ☁ button can surface the popover while a fullscreen editor or
     Tools drawer is active. */
  z-index: 1100;
}
.sync-menu[hidden] { display: none; }
.sync-menu-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; gap: 8px; }
.sync-menu-header strong { font-size: 13px; }
.sync-menu-header .muted { font-size: 11px; }
.sync-menu-actions { display: flex; gap: 6px; margin: 6px 0; }
.sync-menu-actions button { flex: 1; white-space: nowrap; }
.sync-menu-actions button:disabled { opacity: 0.5; cursor: not-allowed; }
#sync-menu-status { font-size: 12px; min-height: 1.2em; margin: 6px 0; }
.sync-menu-foot { font-size: 11px; text-align: right; margin-top: 4px; }
.sync-menu-foot a { color: var(--accent); text-decoration: none; }
.sync-menu-foot a:hover { text-decoration: underline; }

/* 🤖 LLM quick-switch popover — reuses .sync-menu chrome. */
.llm-menu-wrap { position: relative; display: inline-block; }
.llm-menu { min-width: 260px; }
.llm-menu-list { display: flex; flex-direction: column; gap: 2px; margin: 4px 0; }
.llm-menu-empty { font-size: 12px; padding: 4px 2px; }
.llm-menu-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 8px;
  align-items: baseline;
  width: 100%;
  padding: 6px 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.llm-menu-row:hover { background: var(--bg); border-color: var(--border); }
.llm-menu-row.active { background: var(--bg); border-color: var(--accent); }
.llm-menu-row-name { font-weight: 600; font-size: 13px; }
.llm-menu-row-model { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llm-menu-row-check { color: var(--success); font-weight: 700; min-width: 1em; text-align: right; }
#llm-menu-status { font-size: 12px; min-height: 1.2em; margin: 4px 0; }

/* Token-usage line under the verdict summary. */
.verdict-usage {
  font-size: 11px;
  margin-top: 4px;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

/* Live streaming grader card — visible during the in-flight grade. The
   header shows the same elapsed/chars label the Check button does; the
   body shows the last 400 chars of incoming raw response. The whole card
   is replaced by the parsed verdict the moment streaming + parsing finish. */
.verdict-streaming {
  margin-top: 6px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1.5px solid var(--accent);
  border-radius: 8px;
  box-shadow: 0 0 0 0 var(--accent);
  animation: verdict-streaming-pulse 1.6s ease-in-out infinite;
}
.verdict-streaming-head {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 6px;
  letter-spacing: 0.01em;
}
.verdict-streaming-body {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 14px;
  line-height: 1.4;
  max-height: 180px;
  overflow-y: auto;
  margin: 0;
  padding: 0;
  background: transparent;
  border: none;
  white-space: pre-wrap;
  word-break: break-all;
}
@keyframes verdict-streaming-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(9, 105, 218, 0.25); }
  50%      { box-shadow: 0 0 0 6px rgba(9, 105, 218, 0.06); }
}
@keyframes verdict-streaming-pulse-dark {
  0%, 100% { box-shadow: 0 0 0 0 rgba(47, 129, 247, 0.30); }
  50%      { box-shadow: 0 0 0 6px rgba(47, 129, 247, 0.08); }
}
[data-theme="dark"] .verdict-streaming { animation-name: verdict-streaming-pulse-dark; }
@media (prefers-reduced-motion: reduce) {
  .verdict-streaming { animation: none; }
}

.verdict-cancelled {
  font-size: 12px;
  padding: 8px 10px;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
}
.backup-help { font-size: 12px; margin: 4px 0 8px; line-height: 1.4; }
.backup-help a { color: var(--link); }
.backup-row {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 6px;
}
.backup-row button { white-space: nowrap; }
#backup-status, #gist-status { font-size: 12px; }
/* Auto-push toggle + Restore-backup button — wrapped in .backup-row so they
   inherit spacing, but each gets its own visual rhythm. */
.settings-inline-toggle {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
}
.settings-inline-toggle input[type="checkbox"] { margin-top: 3px; }
.settings-inline-toggle small { display: block; margin-top: 2px; }
.sync-restore-row { margin-top: 4px; }
#sync-restore-prepull[hidden] { display: none; }
#sync-restore-prepull {
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------- Issue queue (header 🐛 popover) ---------- */
.issues-queue-empty { margin: 8px 0 0 0; }
.issues-queue-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 12px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.issues-queue-item {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--bg-elev);
}
.issues-queue-item-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}
.issues-queue-tag {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--bg);
  flex: 0 0 auto;
}
.issues-queue-tag-task     { border-color: var(--accent); color: var(--accent); }
.issues-queue-tag-solution { border-color: #d73a4a;       color: #d73a4a; }
.issues-queue-title {
  font-weight: 600;
  word-break: break-word;
}
.issues-queue-meta {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}
.issues-queue-preview {
  margin-top: 4px;
  font-size: 12px;
  white-space: pre-wrap;
}
.issues-queue-item-actions {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.issues-queue-item-actions button,
.issues-queue-item-actions .issues-queue-open {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--fg);
  font: inherit;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.issues-queue-item-actions button:disabled,
.issues-queue-item-actions .issues-queue-open.disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
/* ---------- 🐞 Quick Flag button + scope picker menu ---------- */
.btn-flag-toggle {
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 3px 6px;
  font-size: 14px;
  opacity: 0.45;
  border-radius: 4px;
  filter: grayscale(0.85);
}
.btn-flag-toggle:hover { opacity: 0.9; filter: grayscale(0.3); }
.btn-flag-toggle.active { opacity: 1; filter: none; }
/* Scope-specific border colors so the user can see at a glance which side of
   the exercise they've flagged: solution = red, task = blue, both = gradient. */
.btn-flag-toggle.flag-solution {
  border-color: var(--danger);
  background: rgba(215, 58, 74, 0.08);
}
.btn-flag-toggle.flag-task {
  border-color: var(--accent);
  background: rgba(31, 111, 235, 0.08);
}
.btn-flag-toggle.flag-both {
  border-color: var(--danger);
  background: linear-gradient(135deg, rgba(215, 58, 74, 0.18) 0%, rgba(31, 111, 235, 0.18) 100%);
}

/* Fullscreen-only 🐞 in the answer-box label row — same hidden-until-fullscreen
   pattern as the Tools / Task / Solution drawer buttons. Avoids duplicating
   the card's flag button when both are visible at once. */
.answer-flag-btn { display: none; }
.answer-box.answer-fullscreen .answer-flag-btn { display: inline-block; }

/* Scope picker menu — floats above the 🐞 button. Position is set inline by
   openFlagMenu(); this rule only handles chrome. */
.flag-menu {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  padding: 4px;
  min-width: 180px;
  /* Above .answer-fullscreen (1000), .tools-drawer (1010), and the popovers (1100). */
  z-index: 1200;
  font-size: 13px;
}
.flag-menu-row {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 6px 10px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--fg);
  font: inherit;
}
.flag-menu-row:hover { background: var(--bg); }
.flag-menu-row.selected::after {
  content: ' ✓';
  color: var(--success, #2ea043);
  font-weight: 600;
}
.flag-menu-clear { color: var(--muted); }
.flag-menu-sep {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}
@media (max-width: 480px) {
  /* On phone-narrow viewports the 180 px min-width can crowd out the menu's
     placement budget. Let it shrink (clamp at viewport - 16 px so there's
     still margin on both sides) and drop the min-width floor entirely. */
  .flag-menu {
    max-width: calc(100vw - 16px);
    min-width: 0;
  }
}

/* ---------- Header 🐛 Issues popover (reuses .sync-menu chrome) ---------- */
.issues-menu-wrap { position: relative; display: inline-block; }
.issues-menu { min-width: 320px; max-width: 420px; max-height: 70vh; overflow-y: auto; }
.header-badge {
  display: inline-block;
  margin-left: 2px;
  min-width: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--bg);
  font-size: 10px;
  font-weight: 600;
  line-height: 14px;
  text-align: center;
  vertical-align: top;
}
.header-badge[hidden] { display: none; }
.issues-menu-body { font-size: 12px; }

/* ---------- Issue queue groups (To submit / Already opened) ---------- */
.issues-queue-group { margin-top: 8px; }
.issues-queue-group:first-of-type { margin-top: 0; }
.issues-queue-group-head {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
  user-select: none;
}
.issues-queue-group-head.collapsible {
  cursor: pointer;
}
.issues-queue-group-head.collapsible::before {
  content: '▼ ';
  display: inline-block;
  font-size: 9px;
}
.issues-queue-group-head.collapsible[data-collapsed="1"]::before {
  content: '▶ ';
}

/* Submitted entries are visually de-emphasised. */
.issues-queue-item--submitted {
  opacity: 0.7;
  background: var(--bg);
}
/* Left-border carries the scope cue (task = blue, solution = red) — applies
   to both flag-only and fully-filled drafts so the visual scope marker stays
   consistent. Previously `--flagonly` always painted red, which made the
   two entries that "Both" scope produces indistinguishable. */
.issues-queue-item[data-mode="task"]     { border-left: 3px solid var(--accent); }
.issues-queue-item[data-mode="solution"] { border-left: 3px solid #d73a4a; }
.issues-queue-tag-flag {
  border-color: var(--danger);
  color: var(--danger);
}

/* Mobile tweaks */
@media (max-width: 768px) {
  .provider-grid { grid-template-columns: 1fr; }
  .answer-actions { flex-direction: column; align-items: stretch; gap: 6px; }
  .answer-actions .answer-hint { margin-left: 0; }
  /* 16px prevents iOS Safari from auto-zooming on focus. */
  .answer-textarea,
  .answer-cm .cm-content { font-size: 16px; }
  /* Catch-all so every focusable form element clears the 16px threshold —
     stops iOS Safari from auto-zooming when the user taps the Tools /
     Browse / Settings / Report inputs while the answer editor is in
     fullscreen (or any other time). */
  input[type="text"],
  input[type="search"],
  input[type="number"],
  input[type="email"],
  input[type="password"],
  input[type="url"],
  textarea,
  select {
    font-size: 16px;
  }
}

/* ============================================================ */
/* Settings test connection                                       */
/* ============================================================ */

.key-row { display: flex; gap: 6px; align-items: stretch; }
.key-row input { flex: 1; min-width: 0; }
.key-row button {
  white-space: nowrap;
  padding: 6px 14px;
  font-weight: 600;
}

.test-status {
  margin-top: 8px;
  font-size: 12px;
  padding: 6px 10px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-elev);
}
.test-status.testing { color: var(--fg-muted); }
.test-status.ok {
  color: var(--success);
  border-color: var(--success);
  background: rgba(26, 127, 55, 0.07);
}
.test-status.warn {
  color: var(--warning);
  border-color: var(--warning);
  background: rgba(154, 103, 0, 0.10);
}
.test-status.err {
  color: var(--danger);
  border-color: var(--danger);
  background: rgba(209, 36, 47, 0.07);
}
[data-theme="dark"] .test-status.ok   { background: rgba(26, 127, 55, 0.15); }
[data-theme="dark"] .test-status.warn { background: rgba(154, 103, 0, 0.20); }
[data-theme="dark"] .test-status.err  { background: rgba(209, 36, 47, 0.18); }

/* ============================================================ */
/* Model suggestion chips (replaces the native datalist UI)      */
/* ============================================================ */

.model-chip-row {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 8px;
}
.model-chip {
  padding: 4px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--fg-muted);
  cursor: pointer;
  line-height: 1.3;
}
.model-chip:hover {
  background: var(--border);
  color: var(--fg);
}
.model-chip.active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.model-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Filter + counter row above the chip list. Hidden until populateModelChips
   gets at least one model (e.g. after a successful Test call). */
.model-suggestions-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.model-suggestions-controls input[type="search"] {
  flex: 1;
  min-width: 0;
  padding: 4px 8px;
  font-size: 12px;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
#settings-model-count {
  font-size: 11px;
  white-space: nowrap;
}
/* When expanded the chip row becomes a scrollable container so the brick
   wall of 100+ models doesn't push the rest of the dialog out of view. */
.model-chip-row.expanded {
  max-height: 200px;
  overflow-y: auto;
  padding-right: 4px;
}
.model-show-all {
  display: block;
  margin-top: 4px;
  background: transparent;
  border: 0;
  padding: 4px 0;
  font-size: 11px;
  color: var(--accent);
  cursor: pointer;
}
.model-show-all:hover { text-decoration: underline; }
.model-show-all[hidden] { display: none; }

/* ============================================================ */
/* Help view                                                       */
/* ============================================================ */

#view-help { padding: 16px 20px; }
#view-help.active { display: grid; grid-template-columns: 240px 1fr; gap: 28px; align-items: start; }
/* Document + language toggles injected at the top of #help-body by
   renderHelpView(). Two pills sit side-by-side in .help-controls:
   1. .help-doc-switch — 📖 Webapp Guide | 🎯 Study Index
   2. .help-lang-switch — EN | 中文
   On narrow viewports they wrap onto separate rows via the wrapper's
   flex-wrap. The wrapper drives the bottom margin so a single visible
   pill still has the right gap. */
.help-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0 0 16px;
}
.help-lang-switch,
.help-doc-switch {
  display: inline-flex;
  gap: 4px;
  margin: 0;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-elev);
}
.help-lang-btn,
.help-doc-btn {
  background: transparent;
  border: 0;
  padding: 4px 14px;
  border-radius: 999px;
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
  font-family: inherit;
}
.help-lang-btn.active,
.help-doc-btn.active {
  background: var(--accent);
  color: var(--accent-fg);
  font-weight: 600;
}
.help-lang-btn:hover:not(.active),
.help-doc-btn:hover:not(.active) { color: var(--fg); }
.help-lang-btn:focus-visible,
.help-doc-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.help-toc {
  position: sticky; top: 70px; align-self: start;
  max-height: calc(100vh - 90px); overflow-y: auto;
  font-size: 13px;
  padding-right: 8px;
}
.help-toc ul { list-style: none; padding: 0; margin: 0; }
/* Top-level (h2) entries: parent items — bolder, full-strength text. */
.help-toc > ul > li { margin: 6px 0; }
.help-toc > ul > li > a { font-weight: 600; }
/* Nested (h3) sub-list: SINGLE continuous border-left runs the full height
   of all child entries — that's the "tree-style outline" the user wanted,
   instead of each h3 drawing its own disconnected 1-px stub. */
.help-toc ul ul {
  margin: 2px 0 6px 12px;
  border-left: 2px solid var(--border);
  padding-left: 0;
}
.help-toc ul ul li { margin: 0; }
.help-toc ul ul li > a {
  padding: 2px 6px 2px 12px;
  font-size: 12px;
  color: var(--fg-muted);
}
.help-toc a { color: var(--fg-muted); text-decoration: none; display: block; padding: 3px 6px; border-radius: 4px; line-height: 1.3; }
.help-toc a:hover { color: var(--fg); background: var(--bg-elev); }
.help-toc a.active { color: var(--accent); background: var(--bg-elev); font-weight: 600; }

.help-body {
  max-width: 820px;
  line-height: 1.6;
  /* Allow the grid child to shrink below its widest descendant's intrinsic
     width on narrow viewports — without this, long URLs / wide tables /
     code blocks push the body past viewport width on mobile. */
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.help-body :is(h1, h2, h3, h4, h5, h6) { overflow-wrap: anywhere; }
.help-body h1 { font-size: 28px; margin: 0 0 12px; }
.help-body h2 { margin-top: 36px; padding-top: 14px; border-top: 1px solid var(--border); font-size: 20px; }
.help-body h3 { margin-top: 24px; font-size: 16px; }
.help-body p { margin: 10px 0; }
.help-body blockquote { border-left: 3px solid var(--accent); padding: 4px 12px; margin: 12px 0; color: var(--fg-muted); background: var(--bg-elev); border-radius: 0 6px 6px 0; }
.help-body code { background: var(--bg-code); padding: 1px 5px; border-radius: 4px; font-size: 0.9em; }
.help-body :not(pre) > code { overflow-wrap: anywhere; word-break: break-word; }
.help-body pre { background: var(--bg-code); padding: 12px; border-radius: 6px; overflow-x: auto; max-width: 100%; }
.help-body pre code { background: none; padding: 0; }
/* WEBAPP_GUIDE / EXAM_GUIDE inline screenshots. Source PNGs are 2×
   retina (3840×1870) so without a constraint they blow past the help
   column. The border + radius + soft shadow makes them read as
   screenshots rather than flat inline blocks. */
.help-body img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 14px auto;
  border-radius: 6px;
  border: 1px solid var(--border);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  background: var(--bg-elev);
}
/* `display: block` + `overflow-x: auto` is the responsive-table pattern:
   wide tables get their own horizontal scroll inside the box instead of
   pushing the help column wider than the viewport. */
.help-body table { display: block; border-collapse: collapse; margin: 14px 0; width: 100%; max-width: 100%; overflow-x: auto; font-size: 14px; }
.help-body th, .help-body td { border: 1px solid var(--border); padding: 8px 12px; text-align: left; vertical-align: top; }
.help-body th { background: var(--bg-elev); }
.help-body kbd { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--bg-elev); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--border); font-size: 0.85em; }
.help-body a { color: var(--accent); }
.help-body ul, .help-body ol { padding-left: 24px; }
.help-body li { margin: 4px 0; }

@media (max-width: 900px) {
  #view-help.active { grid-template-columns: 1fr; }
  .help-toc { position: static; max-height: none; border-bottom: 1px solid var(--border); padding: 0 0 12px; margin-bottom: 12px; }
}
/* ============================================================ */
/* Quiz resume panel + snapshots + tab dot                       */
/* ============================================================ */

/* Quiz tab "in-progress" dot */
.mode-tab .tab-dot {
  display: inline-block;
  margin-left: 6px;
  color: var(--accent);
  font-size: 10px;
  line-height: 1;
  vertical-align: middle;
  animation: pulse 2s ease-in-out infinite;
}
.mode-tab .tab-dot[hidden] { display: none; }

/* Resume panel container */
#quiz-resume-panel {
  margin: 12px 0 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Auto-saved session card */
.quiz-resume-active {
  border: 1px solid var(--accent);
  background: var(--bg-elev);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.quiz-resume-active .resume-headline {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.quiz-resume-active .resume-headline > span:first-child { font-weight: 600; }
.quiz-resume-active .resume-actions {
  display: flex;
  gap: 8px;
}

/* Snapshot list */
.quiz-resume-snapshots {
  border: 1px solid var(--border);
  background: var(--bg-elev);
  border-radius: var(--radius);
  padding: 10px 14px;
}
.quiz-resume-snapshots h3 {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 600;
}
.quiz-resume-snapshots ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.quiz-resume-snapshots li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
}
.quiz-resume-snapshots li:first-child { border-top: none; }
.quiz-resume-snapshots .snap-name {
  font-weight: 500;
  flex: 0 0 auto;
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.quiz-resume-snapshots .snap-meta {
  flex: 1;
  font-size: 12px;
}
.quiz-resume-snapshots li button { white-space: nowrap; }

/* Save-snapshot button spacing within quiz-end-row */
.quiz-end-row {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 12px;
}

@media (max-width: 768px) {
  .quiz-resume-snapshots li {
    flex-wrap: wrap;
  }
  .quiz-resume-snapshots .snap-name { max-width: 100%; }
}

/* ============================================================ */
/* PWA standalone — iOS notch / Dynamic Island safe area         */
/* ============================================================ */

@supports (padding: env(safe-area-inset-top)) {
  #app-header {
    padding-top: calc(10px + env(safe-area-inset-top));
    padding-left: calc(20px + env(safe-area-inset-left));
    padding-right: calc(20px + env(safe-area-inset-right));
  }
}

/* ============================================================ */
/* Footer                                                         */
/* ============================================================ */

.app-footer {
  text-align: center;
  padding: 16px 20px;
  margin-top: 24px;
  border-top: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: 12px;
}
.app-footer a { color: var(--fg-muted); }
.app-footer a:hover { color: var(--accent); }

/* Update-available banner — sticky pill at the bottom of the viewport. */
.update-banner {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  background: var(--bg-elev);
  border: 1px solid var(--accent);
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  font-size: 13px;
  z-index: 200;
  max-width: calc(100vw - 24px);
}
.update-banner[hidden] { display: none; }
.update-banner button {
  background: var(--accent);
  color: var(--accent-fg);
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 3px 14px;
  font-size: 12px;
  cursor: pointer;
}
.update-banner button.muted {
  background: transparent;
  color: var(--fg-muted);
  border-color: transparent;
  padding: 0 4px;
}
.update-banner-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
/* Keep each version token (e.g. `v0.1.0+dev.17`) on one line — without
   this the browser breaks at `+` and `.` symbols, fragmenting the
   delta into "v0.1.0" / "+dev" / "17" on narrow viewports. */
#update-banner-versions strong {
  white-space: nowrap;
}
@media (max-width: 480px) {
  /* On phone widths the pill layout can't fit one row anymore — stack
     the message + actions, switch to a rounded rectangle. Each version
     token still stays nowrap (rule above), so a long delta may push
     the right-hand version to a new line of its own, but never breaks
     mid-token. */
  .update-banner {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    border-radius: 12px;
    font-size: 12px;
    padding: 8px 12px;
    gap: 6px;
  }
  .update-banner-actions { justify-content: center; }
}
@media print { .update-banner { display: none !important; } }

/* Floating Back-to-top button. Wired up by installBackToTop() in
   docs/app.js, which toggles `hidden` based on scrollY + current mode.
   Bottom offset lifts it above the mobile mode-tabs row + home
   indicator. z-index sits above install-hint (90) but below
   update-banner (200) so a deploy-time update notice can still get the
   user's attention. */
.scroll-top-btn {
  position: fixed;
  right: 16px;
  bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: var(--bg-elev);
  color: var(--accent);
  border: 1px solid var(--accent);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  z-index: 199;
  opacity: 0.85;
  padding: 0;
}
.scroll-top-btn:hover, .scroll-top-btn:active { opacity: 1; }
.scroll-top-btn[hidden] { display: none; }
@media print { .scroll-top-btn { display: none !important; } }

/* Install-to-home-screen hint banner — same visual family as the
   .update-banner but stacked further off the bottom edge so they
   don't collide if both appear in the same session. Hidden in
   PWA standalone mode (no point urging an install you already did). */
.install-hint {
  position: fixed;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px 7px 14px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
  font-size: 12.5px;
  z-index: 90;
  max-width: calc(100vw - 24px);
  pointer-events: auto;
}
.install-hint .install-hint-text { pointer-events: none; }
.install-hint[hidden] { display: none; }
.install-hint button {
  background: transparent;
  border: none;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 999px;
}
.install-hint button:hover { background: var(--bg-code); color: var(--fg); }
@media (display-mode: standalone) { .install-hint { display: none !important; } }
@media print { .install-hint { display: none !important; } }
@media print { .app-footer { display: none; } }

/* ============================================================ */
/* Mobile responsiveness pass                                     */
/* ============================================================ */

/* ≤768px — drop the keyboard-shortcuts toggle and the GitHub icon
   (the latter lives in the footer now, so no functional loss).
   Both are pure-desktop affordances. */
@media (max-width: 768px) {
  #help-toggle,
  .header-right a.icon-btn[href*="github.com"] { display: none; }
}

/* ≤480px — narrow-phone tweaks (iPhone 17 Pro is 402pt; floor at 380pt). */
@media (max-width: 480px) {
  /* Top mode tabs are no longer visible on mobile (the bottom bar replaces
     them, see .mobile-mode-tabs further down). Header just gets compacted. */
  .header-right { gap: 4px; }
  #app-header { gap: 8px; padding-left: 12px; padding-right: 12px; }
  #quiz-timer { font-size: 12px; padding: 3px 7px; }

  /* Quiz utility row inherits the 5-col grid from the default
     `.quiz-controls` rule (no longer mobile-only after the
     desktop/mobile consistency pass). Mobile just tightens gap +
     paddings + caps button labels with ellipsis. */
  .quiz-controls { gap: 6px; }
  .quiz-grades button {
    padding: 9px 6px;
    font-size: 13px;
  }
  .quiz-controls button {
    padding: 8px 4px;
    font-size: 12px;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Session row goes single-column on narrow phones — desktop default
     is 2-col grid; here we collapse to 1 fr so each of Save snapshot /
     End session takes a full row, matching the iPhone screenshots. */
  .quiz-end-row {
    grid-template-columns: 1fr;
    gap: 6px;
  }

  /* Quiz setup screen — less horizontal padding */
  .quiz-screen { padding: 0 12px; margin: 16px auto; }

  /* ☁ Sync popover: anchor to the viewport, not to the (right-aligned) wrap,
     so the popover never spills past the left edge on narrow screens. */
  .sync-menu {
    position: fixed;
    top: calc(56px + env(safe-area-inset-top, 0px));
    left: 12px;
    right: 12px;
    width: auto;
    min-width: 0;
    max-width: none;
  }

  /* Resume panel: stack the headline + actions vertically */
  .quiz-resume-active .resume-headline {
    flex-direction: column;
    gap: 4px;
    align-items: flex-start;
  }
  .quiz-resume-active .resume-actions { width: 100%; }
  .quiz-resume-active .resume-actions button { flex: 1; }

  /* Footer hidden on mobile — body normal-flow + body-level rubber-band
     scroll would otherwise expose it under the fixed .mobile-mode-tabs
     bar at random scroll positions (license / source links remain
     reachable from Help mode / GitHub repo link in the header chips). */
  .app-footer { display: none; }
}

/* ============================================================ */
/* Tools view — kubectl explain + kubectl -h browsers            */
/* ============================================================ */

#view-tools { padding: 16px 20px; }
#view-tools.active { display: block; }

.tools-subtabs {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.tools-subtabs button {
  background: transparent;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 6px 14px;
  margin-bottom: -1px;
}
.tools-subtabs button.active {
  background: var(--bg);
  border-color: var(--border);
  font-weight: 600;
}
/* Version dropdown lives in the subtab strip, pushed to the right with
   the meta line trailing it. */
.tools-version-picker {
  margin-left: auto;
  font-size: 12px;
  color: var(--fg-muted);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tools-version-picker select {
  font: inherit;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2px 6px;
  cursor: pointer;
}
#tools-meta {
  margin-left: 8px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.tools-panel {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 24px;
  align-items: start;
}
/* Restore [hidden] semantics on the panels — the display:grid above otherwise
   defeats the user-agent default and makes both panels render at once. */
.tools-panel[hidden] { display: none; }

/* Single-column variant for the api-resources table — a flat lookup table
   doesn't need the sidebar layout. */
.tools-panel.tools-panel--table {
  display: block;
}
.tools-panel.tools-panel--table[hidden] { display: none; }

.tools-api-resources-bar {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 12px;
  position: sticky;
  top: 60px;
  background: var(--bg);
  padding: 6px 0;
  z-index: 1;
}
.tools-api-resources-bar input[type="search"] {
  flex: 1;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font: inherit;
  background: var(--bg-elev);
  color: var(--fg);
}
.tools-api-resources-wrap { overflow-x: auto; }
.tools-api-resources-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.tools-api-resources-table th,
.tools-api-resources-table td {
  padding: 6px 10px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.tools-api-resources-table th {
  background: var(--bg-elev);
  position: sticky;
  top: 110px;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.tools-api-resources-table tbody tr { cursor: pointer; }
.tools-api-resources-table tbody tr:hover { background: var(--bg-elev); }
.tools-api-resources-table .api-resources-cell--ns-true  { color: var(--success); }
.tools-api-resources-table .api-resources-cell--ns-false { color: var(--fg-muted); }
.tools-api-resources-table .api-resources-cell--shortnames { font-weight: 600; }
.tools-api-resources-table .api-resources-cell--verbs {
  font-size: 11px;
  color: var(--fg-muted);
  word-break: break-word;
}

/* 📑 api-resources mobile layout — stacked cards instead of a horizontally-
   scrolling six-column table. The standard responsive-table pattern: hide the
   thead, turn each <tr> into a card, prefix each <td> with its column name
   via attr(data-label). 600px chosen so iPad-mini portrait (744px) keeps the
   table layout while iPhones (≤402px logical) and small tablets get the
   cards. */
@media (max-width: 600px) {
  .tools-api-resources-bar {
    position: static;
    flex-wrap: wrap;
    gap: 6px;
    padding: 4px 0 8px;
  }
  .tools-api-resources-wrap { overflow-x: visible; }
  .tools-api-resources-table thead { display: none; }
  .tools-api-resources-table,
  .tools-api-resources-table tbody,
  .tools-api-resources-table tr,
  .tools-api-resources-table td {
    display: block;
    width: auto;
  }
  .tools-api-resources-table tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 12px 12px;
    margin-bottom: 10px;
    background: var(--bg-elev);
    cursor: pointer;
  }
  .tools-api-resources-table td {
    border: none;
    padding: 2px 0;
    position: relative;
    padding-left: 96px;
    min-height: 1.4em;
    word-break: break-word;
  }
  .tools-api-resources-table td::before {
    content: attr(data-label);
    position: absolute;
    left: 0;
    top: 2px;
    width: 88px;
    font-weight: 600;
    color: var(--fg-muted);
    font-size: 10.5px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }
  /* VERBS — longest field, gets a full-width row beneath the others. */
  .tools-api-resources-table .api-resources-cell--verbs {
    padding-top: 6px;
    margin-top: 4px;
    border-top: 1px dashed var(--border);
    padding-left: 0;
    font-size: 11px;
  }
  .tools-api-resources-table .api-resources-cell--verbs::before {
    position: static;
    display: block;
    margin-bottom: 2px;
    width: auto;
  }
  /* iOS Safari ignores :hover — explicit tap-affordance cue. */
  .tools-api-resources-table tr::after {
    content: '👉 tap to open in 📘 Explain';
    display: block;
    margin-top: 6px;
    font-size: 10px;
    color: var(--fg-muted);
    text-align: right;
  }
}

.tools-tree {
  position: sticky;
  top: 70px;
  max-height: calc(100vh - 90px);
  overflow-y: auto;
  padding-right: 6px;
}
.tools-tree input[type="search"] {
  width: 100%;
  margin-bottom: 12px;
}
#tools-kind-list button,
#tools-cmd-list button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 4px 8px;
  background: transparent;
  border: none;
  color: var(--fg-muted);
  border-radius: 4px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  /* Dotted paths like Pod.spec.affinity.nodeAffinity can exceed sidebar width;
     truncate gracefully (title attribute still shows the full path on hover). */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#tools-kind-list button:hover,
#tools-cmd-list button:hover {
  background: var(--bg-elev);
  color: var(--fg);
}
#tools-kind-list button.active,
#tools-cmd-list button.active {
  background: var(--bg-elev);
  color: var(--accent);
  font-weight: 600;
}
/* kubectl short-name aliases shown next to each top-level kind in Explain
   (e.g. "Pod (po)", "CertificateSigningRequest (csr)"). */
.kind-shortnames {
  color: var(--fg-muted);
  font-size: 0.85em;
  font-weight: normal;
  margin-left: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* kubectl sidebar — visual hierarchy: parents as group headings, children
   nested under a vertical guide line. --cmd-depth is set inline by JS. */
#tools-cmd-list .cmd-row {
  padding-left: calc(8px + var(--cmd-depth, 0) * 14px);
}
#tools-cmd-list .cmd-top {
  color: var(--fg);
  font-weight: 600;
  margin-top: 8px;
  border-top: 1px solid var(--border);
  padding-top: 6px;
}
#tools-cmd-list .cmd-top:first-child {
  border-top: none;
  margin-top: 0;
  padding-top: 4px;
}
#tools-cmd-list .cmd-child {
  font-size: 12.5px;
  color: var(--fg-muted);
  border-left: 2px solid var(--border);
  border-radius: 0;
  margin-left: 14px;
  padding-left: 12px;
}
#tools-cmd-list .cmd-child.active { border-left-color: var(--accent); }

.tools-detail {
  max-width: 920px;
  line-height: 1.55;
  /* Grid child needs to allow shrinking below the intrinsic width of its
     widest descendant (the kubectl-help <pre> can hit 120+ chars per line)
     so the internal overflow-x: auto fires inside the <pre> instead of
     stretching the panel + page wider than the viewport on mobile. */
  min-width: 0;
}

/* Explain panel detail */
.explain-header {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  background: var(--bg-elev);
  padding: 10px 14px;
  border-radius: var(--radius);
  margin-bottom: 14px;
}
.explain-header strong { color: var(--fg-muted); }
.explain-breadcrumb {
  font-size: 13px;
  color: var(--fg-muted);
  margin-bottom: 10px;
}
.explain-breadcrumb a {
  color: var(--accent);
  cursor: pointer;
  text-decoration: none;
}
.explain-breadcrumb a:hover { text-decoration: underline; }
.explain-desc {
  margin: 8px 0 14px;
  font-size: 13px;
  /* Leaf-detail + object-detail full descriptions render with original
     paragraph breaks preserved. */
  white-space: pre-wrap;
}
.explain-desc strong { color: var(--fg-muted); }
.explain-section {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  margin: 14px 0 4px;
}
.explain-section strong { color: var(--fg-muted); }
.field-row {
  padding: 6px 0;
  border-bottom: 1px dashed var(--border);
}
.field-head {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.field-name { color: var(--accent); font-weight: 600; }
.field-type { color: var(--fg-muted); white-space: pre; }
.field-drill {
  background: none;
  border: none;
  padding: 0 4px;
  color: var(--accent);
  cursor: pointer;
  font: inherit;
}
.field-desc {
  font-size: 12px;
  color: var(--fg-muted);
  margin-top: 2px;
  padding-left: 16px;
  /* Field list stays scannable even when descriptions are 500-1500 chars —
     clamp at 4 lines, expand on hover (desktop) / click into leaf detail
     (mobile + keyboard). */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* `pre-wrap` so the OpenAPI source's paragraph breaks (\n\n) count toward
     the line-clamp instead of being collapsed into prose. */
  white-space: pre-wrap;
}
.field-row:hover .field-desc {
  -webkit-line-clamp: unset;
  display: block;
}

/* kubectl -h panel detail */
.kubectl-heading {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--bg-elev);
  padding: 10px 14px;
  border-radius: var(--radius);
  margin-bottom: 12px;
}
.kubectl-path {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 600;
}
.kubectl-summary { font-size: 12px; flex: 1; min-width: 0; }
.kubectl-copy { margin-left: auto; }
.kubectl-help {
  margin: 0;
  padding: 14px 16px;
  background: var(--bg-code);
  border-radius: var(--radius);
  overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.45;
  /* Belt-and-suspenders alongside `.tools-detail { min-width: 0 }` — locks
     the help block to the container width so the overflow-x scrollbar fires
     inside the box instead of widening the parent. */
  max-width: 100%;
}
.kubectl-help code { background: none; padding: 0; }
/* Line wrappers introduced for the in-detail filter (line-level show/hide).
   white-space: pre preserves the leading indentation that kubectl -h relies
   on for nesting; the mobile override below wraps long lines. */
.kubectl-help-line { white-space: pre; }

/* Wrap kubectl -h help text on phones + inside the Tools drawer. Desktop
   keeps `white-space: pre` for the terminal look; on a narrow card horizontal
   scrolling is the wrong UX and lines get clipped at the card's right edge.
   pre-wrap preserves the leading indentation + blank lines; word-break
   breaks long `kubectl run hazelcast --image=…` lines so nothing escapes. */
@media (max-width: 600px) {
  .kubectl-help-line {
    white-space: pre-wrap;
    word-break: break-word;
  }
}
#view-tools.in-drawer .kubectl-help-line {
  white-space: pre-wrap;
  word-break: break-word;
}

@media (max-width: 900px) {
  .tools-panel { grid-template-columns: 1fr; }
  .tools-tree, .tools-detail { min-width: 0; }
  .tools-tree {
    position: static;
    max-height: 40vh;
    overflow-y: auto;
    border-bottom: 1px solid var(--border);
    padding: 0 0 12px;
    margin-bottom: 12px;
  }
}

/* Mobile master-detail for Tools Explain + kubectl -h. The list and the
   detail pane share too little vertical space on a phone — let them take
   turns instead. When `.tools-detail-active` is on the panel, only the
   detail renders; otherwise only the list. Same rule applies inside
   the Tools drawer regardless of viewport width (drawer card is narrow).
   api-resources never sets the class — its stacked-card layout below
   `(max-width: 600px)` is independent. */
@media (max-width: 600px) {
  .tools-panel.tools-detail-active .tools-tree { display: none; }
  .tools-panel:not(.tools-detail-active) .tools-detail { display: none; }
  .tools-panel:not(.tools-detail-active) .tools-tree {
    max-height: none;
    border-bottom: none;
    margin-bottom: 0;
  }
}
#view-tools.in-drawer .tools-panel.tools-detail-active .tools-tree { display: none; }
#view-tools.in-drawer .tools-panel:not(.tools-detail-active) .tools-detail { display: none; }
#view-tools.in-drawer .tools-panel:not(.tools-detail-active) .tools-tree {
  max-height: none;
  border-bottom: none;
  margin-bottom: 0;
}

/* ← Back button prepended to detail panes in master-detail mode. Hidden
   on desktop / wide viewports so the side-by-side experience is unchanged. */
.tools-back-to-list { display: none; }
@media (max-width: 600px) {
  .tools-back-to-list {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px 0;
    padding: 6px 12px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    color: var(--fg);
  }
  .tools-back-to-list:hover { background: var(--bg); }
}
#view-tools.in-drawer .tools-back-to-list {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px 0;
  padding: 6px 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  color: var(--fg);
}
#view-tools.in-drawer .tools-back-to-list:hover { background: var(--bg); }

@media (max-width: 480px) {
  #view-tools { padding: 12px 12px; }
  .tools-subtabs button { padding: 4px 8px; font-size: 13px; }
  .tools-version-picker { font-size: 11px; gap: 4px; }
  .tools-version-picker select { padding: 1px 4px; }
  #tools-meta { display: none; }
  .kubectl-help { font-size: 11.5px; padding: 10px 12px; }
  .explain-header { font-size: 12px; padding: 8px 10px; }
  /* 📑 api-resources filter bar — tighter for phone widths. */
  .tools-api-resources-bar input[type="search"] { font-size: 13px; padding: 5px 8px; }
  #tools-api-resources-count { font-size: 11px; }
}

/* ============================================================ */
/* Nodes view — read-only kubeadm filesystem snapshot            */
/* ============================================================ */

#view-nodes { padding: 16px 20px; }
#view-nodes.active { display: block; }

.nodes-subtabs {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.nodes-subtabs button[data-nodes-role] {
  background: transparent;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 6px 14px;
  margin-bottom: -1px;
}
.nodes-subtabs button[data-nodes-role].active {
  background: var(--bg);
  border-color: var(--border);
  font-weight: 600;
}
#nodes-meta {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  margin-left: 8px;
}

.nodes-banner {
  font-size: 12px;
  padding: 8px 12px;
  background: var(--bg-elev);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: 14px;
}

.nodes-panel {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 24px;
  align-items: start;
}

.nodes-tree-pane {
  position: sticky;
  top: 70px;
  max-height: calc(100vh - 90px);
  overflow-y: auto;
  padding-right: 6px;
}
.nodes-tree-pane input[type="search"] {
  width: 100%;
  margin-bottom: 12px;
}
#nodes-tree details {
  margin: 0;
}
#nodes-tree details > summary {
  list-style: none;
  cursor: pointer;
  padding: 3px 6px;
  font-size: 13px;
  color: var(--fg);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  border-radius: 4px;
}
#nodes-tree details > summary:hover {
  background: var(--bg-elev);
}
#nodes-tree details > summary::-webkit-details-marker { display: none; }
#nodes-tree details > summary::before {
  content: "▸ ";
  color: var(--fg-muted);
}
#nodes-tree details[open] > summary::before {
  content: "▾ ";
}
#nodes-tree .file-row {
  display: block;
  width: 100%;
  text-align: left;
  padding: 2px 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--fg-muted);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#nodes-tree .file-row:hover {
  background: var(--bg-elev);
  color: var(--fg);
}
#nodes-tree .file-row.active {
  background: var(--bg-elev);
  color: var(--accent);
  font-weight: 600;
}

.nodes-detail {
  max-width: 980px;
  line-height: 1.55;
}
.nodes-detail .nodes-file-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--bg-elev);
  padding: 10px 14px;
  border-radius: var(--radius);
  margin-bottom: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
}
.nodes-detail .nodes-file-path { font-weight: 600; }
.nodes-detail .nodes-file-copy { margin-left: auto; }
.nodes-detail .nodes-file-body {
  margin: 0;
  padding: 14px 16px;
  background: var(--bg-code);
  border-radius: var(--radius);
  overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.5;
}
/* Per-line wrapper introduced for in-file filter (line-level show/hide).
   pre-wrap preserves leading whitespace + the original indentation; long
   lines wrap inside the wrapper rather than forcing a horizontal scroll. */
.nodes-file-line { white-space: pre-wrap; word-break: break-word; }

/* ← Back button — only visible in mobile master-detail mode. Same pattern as
   Tools' .tools-back-to-list. */
.nodes-back-to-tree { display: none; }

@media (max-width: 900px) {
  .nodes-panel { grid-template-columns: 1fr; }
  .nodes-tree-pane {
    position: static;
    max-height: 40vh;
    border-bottom: 1px solid var(--border);
    padding-bottom: 12px;
    margin-bottom: 12px;
  }
}

/* Mobile master-detail: clicking a file collapses the tree, expanding detail
   to fill the viewport. The ← Back button restores the tree-only view.
   Desktop / tablet (>600px) still shows tree + detail side by side. */
@media (max-width: 600px) {
  #view-nodes.nodes-detail-active .nodes-tree-pane { display: none; }
  #view-nodes:not(.nodes-detail-active) .nodes-detail { display: none; }
  .nodes-back-to-tree {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px 0;
    padding: 6px 12px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    color: var(--fg);
  }
}

@media (max-width: 480px) {
  #view-nodes { padding: 12px; }
  .nodes-subtabs button[data-nodes-role] { padding: 4px 8px; font-size: 13px; }
  #nodes-meta { display: none; }
  .nodes-detail .nodes-file-body { font-size: 11.5px; padding: 10px 12px; }
}

/* ============================================================ */
/* Bottom tab bar (mobile only)                                   */
/* ============================================================ */

/* Hidden by default — only shown on narrow viewports. */
.mobile-mode-tabs { display: none; }

@media (max-width: 768px) {
  /* Top tabs hidden on mobile — bottom bar takes over. */
  #app-header .mode-tabs { display: none; }

  /* The bar itself: fixed to the bottom, full width, safe-area aware. */
  .mobile-mode-tabs {
    display: flex;
    flex-direction: row;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    background: var(--bg-elev);
    border-top: 1px solid var(--border);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
    gap: 2px;
  }
  .mobile-mode-tabs .mode-tab {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    color: var(--fg-muted);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius);
    position: relative;
  }
  .mobile-mode-tabs .mode-tab .tab-icon {
    font-size: 20px;
    line-height: 1;
  }
  .mobile-mode-tabs .mode-tab .tab-label {
    font-size: 10px;
    line-height: 1.2;
    white-space: nowrap;
  }
  .mobile-mode-tabs .mode-tab.active {
    background: var(--bg);
    color: var(--accent);
    border-color: var(--border);
    font-weight: 600;
  }
  .mobile-mode-tabs .mode-tab.active .tab-icon { transform: scale(1.05); }

  /* In-progress quiz indicator — small pulsing dot at top-right of the
     Quiz icon, overriding the inline-flow positioning used by the top tabs. */
  .mobile-mode-tabs .mode-tab .tab-dot {
    position: absolute;
    top: 2px;
    right: calc(50% - 18px);
    margin: 0;
    font-size: 8px;
    line-height: 1;
    display: inline-block;
  }

  /* Make room for the fixed bar so footer / content aren't covered. */
  body { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }

  /* Push the update banner above the bar so they don't overlap. */
  .update-banner {
    bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  }
}
