/* ------------------------------------------------------------------
   SQL Visualizer — layout & theme

   Layout principle: ONE vertical reading path.
       code that is running  →  data it transforms  →  explanation  →  controls
   Cause sits above effect, so the eye reads top-down without hunting.
   The active clause is the most salient thing on screen: a gold pointer bar
   slides to it (motion is what peripheral vision notices), the clause stays at
   full contrast while the rest of the query fades, and the same gold reappears
   on the data being examined.

   Look: "building blocks" — cream paper, thin indigo ink lines, boxes drawn
   with a wireframe extrusion (two skewed pseudo-elements), heavy uppercase
   display type. Semantic colours never change meaning:
     green = kept / TRUE / match     red  = dropped / FALSE
     grey  = NULL / unknown          gold = currently examined
     blue  = newly computed          g0–g7 = GROUP BY buckets
   ------------------------------------------------------------------ */

:root {
  /* "building blocks": cream paper, indigo ink lines, gold for whatever is being examined right now */
  --ink: #2D2A6E;
  --brand: var(--ink);
  --brand-2: #1F1D52;
  --brand-3: #ECEAF6;
  --brand-ink: var(--ink);
  --accent: #F2B84B;
  --accent-2: #F7D28A;
  --accent-3: #FBF1DA;
  --accent-ink: #7A5410;
  --gold-text: #E2A628;

  --bg: #F7F4EC;
  --panel: #FFFDF8;
  --panel-2: #F3F0E6;
  --line: #DDD9E6;
  --line-2: #9B97C2;
  --text: #1E1C4A;
  --text-dim: #5B5880;
  --text-faint: #8F8CAE;

  --green: #16A34A;
  --green-dim: rgba(22, 163, 74, 0.14);
  --amber: var(--accent);
  --amber-dim: rgba(242, 184, 75, 0.2);
  --cyan: #0369A1;
  --red: #E11D48;
  --red-dim: rgba(225, 29, 72, 0.10);
  --grey: #8A889E;
  --grey-dim: rgba(138, 136, 158, 0.16);
  --g0: #2D2A6E; --g1: #E2A628; --g2: #0EA5E9; --g3: #F97316; --g4: #10B981; --g5: #DB2777; --g6: #6366F1; --g7: #14B8A6;

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif;
  --display: "Avenir Next", "Segoe UI", "Helvetica Neue", Arial, "PingFang SC", sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", "DejaVu Sans Mono", monospace;
  --fs: 13px;
  --radius: 2px;
  --d: 10px;   /* depth of the block extrusion */
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body { margin: 0; background: var(--bg); color: var(--text); font-family: var(--sans); font-size: var(--fs); line-height: 1.45; overflow: hidden; }

code { font-family: var(--mono); color: var(--brand); background: var(--brand-3); padding: 0 4px; border-radius: 3px; font-size: 0.95em; }
b { color: var(--text); font-weight: 700; }
a { color: var(--cyan); }
[hidden] { display: none !important; }

/* ---------- top bar: light, typographic ---------- */
.topbar {
  height: 52px; display: flex; align-items: center; justify-content: space-between;
  padding: 0 20px; background: var(--panel); border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: baseline; gap: 14px; }
.title { font-weight: 700; font-size: 17px; color: var(--brand-ink); letter-spacing: -0.02em; text-decoration: none; display: inline-flex; align-items: center; gap: 9px; }
.title .logo { width: 24px; height: 24px; border-radius: 7px; display: block; }
.title-2 { color: var(--brand); }
.sub { color: var(--text-dim); font-size: 12.5px; }
.course { color: var(--text-dim); font-size: 12.5px; padding-left: 14px; border-left: 1px solid var(--line-2); }
.course:empty { display: none; }
.top-actions { display: flex; align-items: center; gap: 8px; }

/* ---------- app grid: optional tables rail + the stage ---------- */
.app { display: grid; grid-template-columns: 250px 1fr; height: calc(100% - 52px); }
.app.rail-hidden { grid-template-columns: 1fr; }
.app.rail-hidden .rail { display: none; }
.rail { border-right: 1px solid var(--line); background: var(--panel); overflow: auto; min-height: 0; }
.rail-head { padding: 10px 14px 6px; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.rail-hint { font-weight: 400; letter-spacing: 0; text-transform: none; font-size: 11px; color: var(--text-faint); }
.rail-body { padding: 0 14px 14px; }
.stage { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px 12px; min-height: 0; min-width: 0; overflow: hidden; }

/* ---------- buttons / inputs ---------- */
.btn {
  font-family: var(--sans); font-size: 12.5px; cursor: pointer; border-radius: var(--radius);
  background: #fff; color: var(--text); border: 1px solid var(--line-2); padding: 6px 12px;
  transition: background .15s, color .15s, border-color .15s, box-shadow .15s;
}
.btn:hover { border-color: var(--brand); color: var(--brand); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--brand); color: #fff; border-color: var(--brand); box-shadow: 0 1px 2px rgba(124,58,237,0.25); }
.btn.primary:hover { background: var(--brand-2); color: #fff; }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn.ghost:hover { background: var(--panel-2); border-color: var(--line); color: var(--brand); }
.btn.ghost.on { color: var(--brand); background: var(--brand-3); }
.btn.icon { padding: 6px 10px; min-width: 32px; }
.btn:disabled { opacity: .45; cursor: default; }
.select { font-family: var(--sans); font-size: 12.5px; background: #fff; color: var(--text); border-radius: var(--radius); border: 1px solid var(--line-2); padding: 6px 8px; max-width: 240px; }

.toolbar { display: flex; gap: 8px; align-items: center; }

/* ---------- 1. code ---------- */
.code-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); flex: 0 0 auto; overflow: visible; position: relative; z-index: 5; }
.editor { border-radius: var(--radius) var(--radius) 0 0; }
.editor-foot { border-radius: 0 0 var(--radius) var(--radius); }
.code-head { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px 6px 14px; }
.code-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; }
.editor { position: relative; height: 120px; min-height: 84px; overflow: hidden; background: #fff; transition: height .2s ease; }
.editor .hl, .editor textarea {
  position: absolute; inset: 0; margin: 0; padding: 10px 16px 10px 36px;
  font-family: var(--mono); font-size: 14px; line-height: 1.5; tab-size: 2; white-space: pre-wrap; word-wrap: break-word;
  overflow: auto; border: 0;
}
.editor .hl { pointer-events: none; color: var(--text); }
.editor .hl code { background: none; padding: 0; color: inherit; font-size: inherit; border-radius: 0; }
.editor .hl .k { color: var(--brand); font-weight: 700; }
.editor .hl .f { color: var(--cyan); }
.editor .hl .s { color: #B45309; }
.editor .hl .n { color: #0F766E; }
.editor .hl .c { color: var(--text-faint); font-style: italic; }
.editor .hl .i { color: var(--accent-ink); }
.editor .hl .p { color: var(--text-dim); }
.editor .hl mark.clause { background: var(--accent-3); color: inherit; box-shadow: 0 0 0 1.5px var(--accent); border-radius: 3px; padding: 0 2px; margin: 0 -2px; }
.editor .hl mark.clause.pulse { animation: markPulse .9s ease-out; }
@keyframes markPulse { 0% { box-shadow: 0 0 0 1.5px var(--accent), 0 0 0 10px rgba(236,72,153,0.28); } 100% { box-shadow: 0 0 0 1.5px var(--accent), 0 0 0 0 rgba(236,72,153,0); } }
.editor.focus-mode .hl .dimmed { opacity: .45; }
.editor.focus-mode .hl .active-line { font-weight: 600; }
.editor .pointer {
  position: absolute; left: 14px; width: 5px; border-radius: 3px; background: var(--accent);
  transition: top .45s cubic-bezier(.22,.8,.26,1), height .3s ease; pointer-events: none;
}
.editor .pointer::after { content: ""; position: absolute; left: 9px; top: 50%; margin-top: -5px; border: 5px solid transparent; border-left-color: var(--accent); border-right-width: 0; }
.editor .pointer.pulse { animation: ptrPulse .9s ease-out; }
@keyframes ptrPulse { 0% { box-shadow: 0 0 0 0 rgba(236,72,153,0.55); } 100% { box-shadow: 0 0 0 12px rgba(236,72,153,0); } }
.editor textarea { background: transparent; color: transparent; caret-color: var(--brand); resize: none; outline: none; -webkit-text-fill-color: transparent; }
.editor textarea::selection { background: rgba(31,95,191,0.18); }
.editor textarea::placeholder { color: var(--text-faint); -webkit-text-fill-color: var(--text-faint); }
.editor-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 6px 10px 6px 14px; font-size: 11.5px; color: var(--text-dim); border-top: 1px solid var(--line); background: var(--panel-2); }
.idea { color: var(--text-dim); }
.keys { color: var(--text-faint); white-space: nowrap; }

/* ---------- banners (errors, notices) ---------- */
.banner { display: flex; gap: 14px; align-items: flex-start; padding: 9px 14px; background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--red); border-radius: var(--radius); flex: 0 0 auto; }
.banner.notes { border-left-color: var(--line-2); background: var(--panel-2); }
.banner-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; white-space: nowrap; padding-top: 2px; }
.banner-body { flex: 1; min-width: 0; }
#message .err-title { color: var(--red); font-weight: 700; }
#message .hint { color: var(--text-dim); margin-top: 4px; }
#message .hint::before { content: "Hint: "; color: var(--accent); font-weight: 600; }
#message.ok .err-title { color: var(--green); }
#message.warn .err-title { color: var(--accent); }
.note-item { padding: 3px 0; }
.note-title { color: var(--text); font-weight: 700; }
.note-text { color: var(--text-dim); }

/* ---------- tables rail ---------- */
.tbl-def { margin-bottom: 10px; }
.tbl-name { color: var(--brand); cursor: pointer; font-weight: 700; font-family: var(--mono); }
.tbl-name:hover { text-decoration: underline; }
.tbl-rows { color: var(--text-faint); font-size: 11px; margin-left: 6px; }
.tbl-doc { color: var(--text-faint); font-size: 11px; line-height: 1.35; }
.col-list { list-style: none; padding: 0 0 0 10px; margin: 3px 0 0; font-family: var(--mono); font-size: 12.5px; }
.col-list li { color: var(--text-dim); cursor: pointer; white-space: nowrap; }
.col-list li:hover { color: var(--text); }
.col-list .pk { color: var(--accent); }
.col-type { color: var(--text-faint); font-size: 11px; margin-left: 6px; font-family: var(--sans); }

/* ---------- execution order ---------- */
.timeline { display: flex; align-items: center; gap: 12px; padding: 0 2px; flex: 0 0 auto; min-width: 0; }
.tl-label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; white-space: nowrap; }
.tl-chips { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; min-width: 0; padding: 2px 0; scrollbar-width: none; }
.tl-chips::-webkit-scrollbar { display: none; }
.chip { white-space: nowrap; flex: 0 0 auto; }
.chip { font-size: 11.5px; padding: 3px 10px; border: 1px solid var(--line-2); color: var(--text-faint); border-radius: 999px; background: #fff; cursor: default; font-family: var(--sans); transition: background .2s, color .2s, border-color .2s; }
.chip .no { color: var(--text-faint); margin-right: 5px; font-variant-numeric: tabular-nums; }
.chip.present { color: var(--text); cursor: pointer; }
.chip.present:hover { border-color: var(--brand); }
.chip.present.done { color: var(--brand); border-color: var(--brand-3); background: var(--brand-3); }
.chip.present.done .no { color: var(--brand); }
.chip.active { color: #fff; background: var(--brand); border-color: var(--brand); font-weight: 700; }
.chip.active .no { color: var(--accent-2); }
.chip.absent { opacity: .4; text-decoration: line-through; }

/* ---------- 2. data board ---------- */
.board-wrap { position: relative; flex: 1 1 auto; min-height: 160px; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); display: flex; flex-direction: column; }
.board { position: relative; flex: 1 1 auto; overflow: auto; padding: 0; min-height: 0; font-family: var(--mono); }
.board-inner { position: relative; min-width: 100%; padding: 14px; }
.ghosts { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; overflow: visible; }
.ghosts .row { background: var(--panel-2); }
.board-empty { position: absolute; inset: 0; z-index: 2; display: flex; align-items: center; justify-content: center; color: var(--text-dim); text-align: center; pointer-events: none; background: var(--panel); border-radius: var(--radius); }
.crt-text p { margin: 4px 0; }
.crt-text p:first-child { color: var(--brand); font-weight: 700; }
.crt-text.error { max-width: 640px; text-align: left; }
.crt-text.error p:first-child { color: var(--red); }
.crt-text.error .hint { color: var(--text-dim); }
.crt-text.error .hint::before { content: "Hint: "; color: var(--accent); font-weight: 600; }
.crt-text.muted p:first-child { color: var(--text-dim); }
.crt-text.muted p { color: var(--text-faint); }

.panels { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.panels.layout-column { flex-direction: column; }
.break { flex-basis: 100%; height: 0; }
.panel { background: #fff; border: 1px solid var(--line-2); border-radius: 4px; min-width: 160px; }
.panel.result { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-3); }
.panel.focus-panel { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-3); }
.panel.dim-panel { opacity: .4; }
/* spotlight: the panel this step is about stays vivid, the rest step back */
.panel { transition: opacity .35s ease, filter .35s ease, box-shadow .35s ease, border-color .35s ease; }
.panel.unlit { opacity: .55; filter: saturate(.7); }
.panel.unlit .row.focus { font-weight: 400; }
.panel.lit { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-3), 0 6px 18px rgba(124,58,237,0.08); }
.panel.lit.result { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-3), 0 6px 18px rgba(124,58,237,0.08); }
.panel.lit .panel-title { background: var(--accent-3); color: var(--accent-ink); }
.panel.lit.result .panel-title { background: var(--brand-3); color: var(--brand); }
.panel.lit.pulse { animation: panelPulse 1s ease-out; }
@keyframes panelPulse { 0% { box-shadow: 0 0 0 2px var(--accent-3), 0 0 0 12px rgba(236,72,153,0.28); } 100% { box-shadow: 0 0 0 2px var(--accent-3), 0 0 0 0 rgba(236,72,153,0); } }
.panel.before { border-style: dashed; background: var(--panel-2); }
.panel.before .panel-title { background: var(--panel-2); color: var(--text-dim); border-bottom-style: dashed; }
.panel.before .row.hdr { background: var(--panel-2); }
.panel.before .row:not(.hdr) { opacity: .85; }
.row.fan { background: var(--accent-3); border-left-color: var(--accent); }
.cell.idx { color: var(--text-faint); font-size: 11px; }
.hdr .cell.idx { color: var(--text-faint); }
.panel-title { display: flex; justify-content: space-between; gap: 12px; padding: 5px 8px; height: 27px; box-sizing: border-box; border-bottom: 1px solid var(--line-2); font-size: 11px; letter-spacing: 0.04em; color: var(--brand); font-weight: 700; font-family: var(--sans); background: var(--brand-3); position: sticky; top: 0; z-index: 3; border-radius: 4px 4px 0 0; }
.pcount { color: var(--text-dim); font-weight: 400; }
.tbl { padding: 2px 0 4px; }

.row {
  display: flex; align-items: center; gap: 0; padding: 1px 6px; border-left: 3px solid transparent;
  border-bottom: 1px solid #eef0ee; white-space: nowrap; position: relative;
  transition: background-color .35s ease, color .35s ease, opacity .35s ease, border-color .35s ease;
  will-change: transform;
}
.row:last-child { border-bottom-color: transparent; }
.row.hdr { color: var(--text-dim); border-bottom: 1px solid var(--line-2); position: sticky; top: 27px; background: #fff; z-index: 2; }
.cell { padding: 1px 6px; overflow: hidden; text-overflow: ellipsis; flex: 0 0 auto; transition: color .35s, background-color .35s, opacity .35s; }
.cell.span { flex: 1 1 auto; overflow: visible; }
.cell.isnull { color: var(--grey); font-style: italic; }
.cell.ref { color: var(--accent-ink); background: var(--accent-3); text-decoration: underline dotted var(--accent); text-underline-offset: 3px; }
.hdr .cell.ref, .hdr .cell.keepcol { color: var(--accent-ink); background: var(--accent-3); }
.hdr .cell.dropcol { opacity: .4; text-decoration: line-through; }
.hdr .cell.newcol { color: var(--cyan); }
.hdr .cell.verdict { color: var(--accent-ink); border-left: 1px dashed var(--line-2); font-weight: 400; background: var(--accent-3); }
.cell.verdict { font-weight: 700; border-left: 1px dashed var(--line-2); }
.cell.verdict.keep { color: var(--green); }
.cell.verdict.drop { color: var(--red); }
.cell.verdict.null { color: var(--grey); }
.cell.verdict.pending { color: var(--text-faint); font-weight: 400; }
.cell.dropcell { opacity: .3; }
.cell.newcell { color: var(--cyan); }
.empty { color: var(--text-faint); padding: 6px 10px; font-style: italic; }
.note { color: var(--text-faint); padding: 3px 10px; font-size: 11px; font-family: var(--sans); }

.row.keep { background: var(--green-dim); border-left-color: var(--green); }
.row.drop { background: var(--red-dim); border-left-color: var(--red); opacity: .6; }
.row.null { background: var(--grey-dim); border-left-color: var(--grey); opacity: .85; }
.row.focus { background: var(--accent-3); border-left-color: var(--accent); color: var(--text); font-weight: 600; }
.row.match { background: var(--green-dim); border-left-color: var(--green); }
.row.dim { opacity: .35; }
.row.dim .cell { opacity: .6; }
.row.done { opacity: .55; }
.row.ghost { color: var(--grey); font-style: italic; border-left-color: var(--grey); background: var(--grey-dim); }
.row.focus-soft { filter: saturate(1.4); }
.row.ghdr { font-size: 11px; letter-spacing: 0.04em; margin-top: 6px; border-bottom: 1px solid var(--line-2); font-family: var(--sans); font-weight: 700; }
.row.ghdr .cell { color: inherit; }

.row.g0 { border-left-color: var(--g0); } .row.g0.ghdr { color: var(--g0); } .row.g0:not(.ghdr) { background: color-mix(in srgb, var(--g0) 10%, transparent); }
.row.g1 { border-left-color: var(--g1); } .row.g1.ghdr { color: var(--g1); } .row.g1:not(.ghdr) { background: color-mix(in srgb, var(--g1) 12%, transparent); }
.row.g2 { border-left-color: var(--g2); } .row.g2.ghdr { color: var(--g2); } .row.g2:not(.ghdr) { background: color-mix(in srgb, var(--g2) 10%, transparent); }
.row.g3 { border-left-color: var(--g3); } .row.g3.ghdr { color: var(--g3); } .row.g3:not(.ghdr) { background: color-mix(in srgb, var(--g3) 10%, transparent); }
.row.g4 { border-left-color: var(--g4); } .row.g4.ghdr { color: var(--g4); } .row.g4:not(.ghdr) { background: color-mix(in srgb, var(--g4) 12%, transparent); }
.row.g5 { border-left-color: var(--g5); } .row.g5.ghdr { color: var(--g5); } .row.g5:not(.ghdr) { background: color-mix(in srgb, var(--g5) 10%, transparent); }
.row.g6 { border-left-color: var(--g6); } .row.g6.ghdr { color: var(--g6); } .row.g6:not(.ghdr) { background: color-mix(in srgb, var(--g6) 10%, transparent); }
.row.g7 { border-left-color: var(--g7); } .row.g7.ghdr { color: var(--g7); } .row.g7:not(.ghdr) { background: color-mix(in srgb, var(--g7) 10%, transparent); }
.row.keep.g0, .row.keep.g1, .row.keep.g2, .row.keep.g3, .row.keep.g4, .row.keep.g5, .row.keep.g6, .row.keep.g7 { background: var(--green-dim); }

.badge { margin-left: 10px; font-size: 10px; letter-spacing: 0.04em; padding: 0 6px; border: 1px solid currentColor; border-radius: 10px; color: var(--accent); white-space: nowrap; font-family: var(--sans); font-weight: 600; }
.row.drop .badge { color: var(--red); }
.row.ghost .badge { color: var(--grey); }

/* ---------- 3. explanation ---------- */
.narration { min-height: 44px; padding: 10px 14px; background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: var(--radius); color: var(--text); font-size: 14.5px; line-height: 1.55; flex: 0 0 auto; }
.narration .cap::after { content: " ↓"; color: var(--accent); font-weight: 700; }
.narration:empty::before { content: "…"; color: var(--text-faint); }
.narration .warn { color: #B45309; }
.narration .stage-tag { display: inline-block; font-size: 10.5px; letter-spacing: 0.12em; color: var(--accent-ink); background: var(--accent-3); border: 1px solid var(--accent); padding: 0 7px; border-radius: 3px; margin-right: 8px; vertical-align: middle; font-weight: 700; }
.narration .evals { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--line); display: flex; flex-direction: column; gap: 2px; font-family: var(--mono); }
.ev { font-size: 13px; color: var(--text-dim); display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.ev.note { color: var(--text-faint); font-style: italic; font-family: var(--sans); }
.ev-expr { color: var(--text-dim); }
.ev-arrow { color: var(--text-faint); }
.ev-sub { color: var(--text); font-weight: 600; }
.ev-res { font-weight: 700; }
.ev-res.keep { color: var(--green); }
.ev-res.drop { color: var(--red); }
.ev-res.null { color: var(--grey); }
.ev-res.agg, .ev-res.plain { color: var(--cyan); }

/* ---------- 4. controls ---------- */
.controls { display: flex; align-items: center; gap: 8px; padding: 6px 4px 0; flex: 0 0 auto; }
.frame-no { color: var(--text-faint); font-size: 11.5px; min-width: 56px; text-align: center; font-variant-numeric: tabular-nums; }
.progress { flex: 1 1 auto; min-width: 120px; display: flex; gap: 3px; align-items: flex-start; height: 26px; padding-top: 4px; }
.progress.empty { visibility: hidden; }
.seg { flex: 1 1 0; min-width: 14px; cursor: pointer; display: flex; flex-direction: column; gap: 3px; }
.seg-bar { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; transition: background .2s; }
.seg-fill { height: 100%; width: 0; background: var(--brand); border-radius: 3px; transition: width .25s ease; }
.seg.current .seg-bar { background: var(--accent-3); box-shadow: 0 0 0 1px var(--accent-2); }
.seg.current .seg-fill { background: var(--accent); }
.seg:hover .seg-bar { background: var(--line-2); }
.seg-label { font-size: 9.5px; letter-spacing: 0.06em; color: var(--text-faint); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; line-height: 1; }
.seg.current .seg-label { color: var(--accent); font-weight: 700; }
.seg.done .seg-label { color: var(--brand); }
.btn.next { padding: 7px 22px; font-weight: 700; letter-spacing: 0.04em; font-size: 13px; box-shadow: 0 2px 6px rgba(124,58,237,0.3); }
.next-hint { font-size: 11.5px; color: var(--text-faint); min-width: 90px; white-space: nowrap; }
.btn.toggle.on { color: var(--brand); border-color: var(--brand); }
.btn.toggle.playing { background: var(--brand-3); color: var(--brand); border-color: var(--brand); }

/* ---------- result (collapsible) ---------- */
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); display: flex; flex-direction: column; min-height: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; padding: 7px 14px; gap: 8px; }
.card-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; }
.card-body { overflow: auto; }
.meta { color: var(--text-faint); font-size: 11px; }
.result-card { flex: 0 0 auto; max-height: 34%; min-height: 0; }
.result-card.collapsed { display: none; }
.result-btn { margin-left: auto; }
.result-btn .meta { margin-left: 6px; }
.result-body { padding: 0; font-family: var(--mono); }
table.res { border-collapse: collapse; width: max-content; }
table.res th, table.res td { padding: 3px 12px; text-align: left; border-bottom: 1px solid var(--line); white-space: nowrap; }
table.res th { color: var(--brand); font-weight: 700; font-size: 11px; letter-spacing: 0.04em; position: sticky; top: 0; background: var(--brand-3); font-family: var(--sans); }
table.res td.num { text-align: right; }
table.res td.isnull { color: var(--grey); font-style: italic; }
table.res tr:hover td { background: var(--panel-2); }
.res-empty { padding: 8px 12px; color: var(--text-faint); font-style: italic; font-family: var(--sans); }
.card-head.clickable { cursor: pointer; user-select: none; }
.card-head.clickable:hover .card-title { color: var(--brand); }
.result-card.collapsed .result-body { display: none; }
.caret { display: inline-block; margin-left: 4px; color: var(--text-faint); }

/* ---------- overlay ---------- */
.overlay { position: fixed; inset: 0; background: rgba(31,42,38,0.5); display: flex; align-items: center; justify-content: center; z-index: 2000; }
.dialog { background: #fff; border-top: 4px solid var(--accent); border-radius: var(--radius); padding: 22px 26px; max-width: 620px; box-shadow: 0 10px 40px rgba(0,0,0,0.25); }
.dialog h2 { margin: 0 0 10px; color: var(--brand); font-size: 17px; }
.dialog pre { background: var(--panel-2); padding: 8px 10px; border: 1px solid var(--line); font-family: var(--mono); }
.dialog .small { color: var(--text-dim); font-size: 12px; }

@media (prefers-reduced-motion: reduce) {
  .row, .cell, .btn, .editor .pointer { transition: none; }
  .editor .pointer.pulse, .editor .hl mark.clause.pulse { animation: none; }
}


/* ---------- links between rows (e.g. the two rows a join glued together) ---------- */
.links { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 4; overflow: visible; }
.link { fill: none; stroke-width: 2; stroke-linecap: round; stroke: var(--green); stroke-dasharray: 2000; stroke-dashoffset: 2000; animation: linkDraw .55s ease-out forwards; animation-delay: var(--link-delay, 0ms); }
.link-dot { fill: var(--green); opacity: 0; animation: linkDot .2s ease-out forwards; animation-delay: calc(var(--link-delay, 0ms) + .35s); }
.link.null, .link-dot.null { stroke: var(--grey); fill: var(--grey); }
@keyframes linkDraw { to { stroke-dashoffset: 0; } }
@keyframes linkDot { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .link, .link-dot { animation: none; stroke-dashoffset: 0; opacity: 1; } }

/* ---------- footer ---------- */
.foot { display: flex; gap: 8px; align-items: center; padding: 2px 4px 0; color: var(--text-faint); font-size: 11px; flex: 0 0 auto; }
.foot-sep { color: var(--line-2); }
.status:empty { display: none; }
.status::before { content: "● "; color: var(--green); }

/* ---------- narrow-screen note ---------- */
.narrow-note { display: none; padding: 8px 12px; background: var(--accent-3); border: 1px solid var(--accent-2); border-radius: var(--radius); color: var(--accent-ink); font-size: 12px; }

/* ---------- welcome (first visit) ---------- */
.welcome { display: flex; gap: 20px; align-items: center; justify-content: space-between; padding: 14px 18px; background: linear-gradient(135deg, #fff 0%, var(--brand-3) 100%); border: 1px solid var(--line); border-left: 4px solid var(--brand); border-radius: var(--radius); flex: 0 0 auto; }
.welcome-title { font-size: 16px; font-weight: 700; color: var(--brand); margin-bottom: 4px; }
.welcome p { margin: 3px 0; color: var(--text-dim); max-width: 78ch; }
.welcome-tip { color: var(--text); }
.welcome-actions { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.welcome-actions .btn { white-space: nowrap; }

/* ---------- examples menu ---------- */
.examples-wrap { position: relative; }
.examples-menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 50; width: 380px; max-height: min(70vh, 560px); overflow: auto; background: #fff; border: 1px solid var(--line-2); border-radius: var(--radius); box-shadow: 0 12px 32px rgba(31,42,38,0.18); padding: 6px; }
.ex-group { font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; padding: 10px 10px 4px; }
.ex-group:first-child { padding-top: 6px; }
.ex-item { display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left; background: none; border: 0; border-radius: 4px; padding: 6px 10px; cursor: pointer; font-family: var(--sans); color: var(--text); }
.ex-item:hover, .ex-item:focus-visible { background: var(--brand-3); outline: none; }
.ex-title { font-size: 13px; font-weight: 600; color: var(--brand); }
.ex-idea { font-size: 11.5px; color: var(--text-dim); line-height: 1.35; }
#examples-btn .caret { margin-left: 2px; }

/* ---------- predict-then-reveal ---------- */
.predict { padding: 10px 14px; background: var(--accent-3); border: 1px solid var(--accent-2); border-radius: var(--radius); flex: 0 0 auto; font-size: 14px; line-height: 1.5; display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; }
.pq { display: flex; gap: 10px; align-items: baseline; flex: 1 1 auto; min-width: 0; }
.pq-tag { display: inline-block; font-size: 10.5px; letter-spacing: 0.12em; color: #fff; background: var(--accent); border: 1px solid var(--accent); padding: 0 7px; border-radius: 3px; font-weight: 700; white-space: nowrap; align-self: center; }
.pq.right .pq-tag { color: var(--green); background: var(--green-dim); border-color: var(--green); }
.pq.wrong .pq-tag { color: var(--red); background: var(--red-dim); border-color: var(--red); }
.pq-opts { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.btn.opt { min-width: 44px; font-family: var(--mono); font-weight: 700; font-size: 13px; padding: 5px 12px; background: #fff; }
.btn.opt:hover { background: var(--accent-3); border-color: var(--accent); color: var(--accent-ink); }
.pq-foot { font-size: 11.5px; color: var(--text-faint); white-space: nowrap; }
.pq-foot:empty { display: none; }
.btn.toggle.on { color: var(--brand); border-color: var(--brand); background: var(--brand-3); }

/* ---------- loading ---------- */
.loading { position: fixed; inset: 0; z-index: 3000; background: var(--bg); display: flex; align-items: center; justify-content: center; transition: opacity .3s ease; }
.loading.out { opacity: 0; pointer-events: none; }
.loading-box { width: 260px; text-align: center; }
.loading-brand { font-weight: 700; font-size: 22px; letter-spacing: -0.02em; color: var(--brand-ink); margin-bottom: 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.loading-brand img { border-radius: 11px; }
.loading-bar { height: 4px; background: var(--line); border-radius: 2px; overflow: hidden; }
.loading-fill { height: 100%; width: 40%; background: var(--brand); border-radius: 2px; animation: loadSlide 1.1s ease-in-out infinite; }
@keyframes loadSlide { 0% { transform: translateX(-100%); } 100% { transform: translateX(260%); } }
.loading-text { margin-top: 10px; font-size: 12px; color: var(--text-dim); }

/* ---------- shortcuts dialog ---------- */
.shortcuts-dialog { max-width: 460px; min-width: 380px; }
.keys-list { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; margin: 12px 0; align-items: center; }
.keys-list dt { text-align: right; white-space: nowrap; }
.keys-list dd { margin: 0; color: var(--text-dim); }
kbd { font-family: var(--mono); font-size: 11.5px; background: var(--panel-2); border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 4px; padding: 1px 6px; color: var(--text); }
.dialog-actions { display: flex; justify-content: flex-end; margin-top: 8px; }

/* ---------- toast ---------- */
.toast { position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 8px); z-index: 4000; background: var(--brand); color: #fff; padding: 9px 16px; border-radius: 999px; font-size: 13px; box-shadow: 0 8px 24px rgba(124,58,237,0.3); opacity: 0; transition: opacity .2s, transform .2s; }
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  body { overflow: auto; }
  .app { grid-template-columns: 1fr; height: auto; }
  .rail { display: none; }
  .board-wrap { min-height: 360px; height: 60vh; }
  .result-card { max-height: none; }
  .sub, .course { display: none; }
  .controls { flex-wrap: wrap; }
  .progress { order: 10; flex-basis: 100%; }
}
@media (max-width: 760px) {
  .narrow-note { display: block; }
  .editor-foot { flex-wrap: wrap; }
  .idea { flex-basis: 100%; }
}


/* ==================================================================
   BLOCK THEME — overrides. Boxes are drawn as wireframe blocks:
   a top face (::before, skewX) and a right face (::after, skewY).
   ================================================================== */
body { background-color: var(--bg); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }

.block { position: relative; background: var(--panel); border: 1.5px solid var(--ink); border-radius: 0; box-shadow: none; margin-top: var(--d); margin-right: var(--d); }
.block::before { content: ""; position: absolute; left: 0; top: calc(-1 * var(--d) - 1.5px); width: 100%; height: var(--d); box-sizing: border-box; border: 1.5px solid var(--ink); border-bottom: 0; transform: skewX(-45deg); transform-origin: bottom left; pointer-events: none; background: var(--bg); }
.block::after { content: ""; position: absolute; top: 0; right: calc(-1 * var(--d) - 1.5px); width: var(--d); height: 100%; box-sizing: border-box; border: 1.5px solid var(--ink); border-left: 0; transform: skewY(-45deg); transform-origin: top left; pointer-events: none; background: var(--bg); }
.stage { gap: 8px; padding: 10px 26px 12px 18px; }

/* which boxes are blocks */
.code-card, .board-wrap, .narration, .predict, .welcome, .result-card { }
.code-card { position: relative; background: var(--panel); border: 1.5px solid var(--ink); border-radius: 0; margin-top: var(--d); margin-right: var(--d); }
.code-card::before, .board-wrap::before, .narration::before, .predict::before, .welcome::before, .result-card::before { content: ""; position: absolute; left: 0; top: calc(-1 * var(--d) - 1.5px); width: 100%; height: var(--d); box-sizing: border-box; border: 1.5px solid var(--ink); border-bottom: 0; transform: skewX(-45deg); transform-origin: bottom left; pointer-events: none; z-index: 0; }
.code-card::after, .board-wrap::after, .narration::after, .predict::after, .welcome::after, .result-card::after { content: ""; position: absolute; top: 0; right: calc(-1 * var(--d) - 1.5px); width: var(--d); height: 100%; box-sizing: border-box; border: 1.5px solid var(--ink); border-left: 0; transform: skewY(-45deg); transform-origin: top left; pointer-events: none; z-index: 0; }
.board-wrap, .narration, .predict, .welcome, .result-card { position: relative; border: 1.5px solid var(--ink); border-radius: 0; margin-top: var(--d); margin-right: var(--d); box-shadow: none; }
.board-wrap { background: var(--panel-2); }
.narration { background: var(--panel); border-left-width: 1.5px; font-size: 14.5px; }
.predict { background: var(--accent-3); }
.welcome { background: var(--panel); border-left-width: 1.5px; }
.editor { background: var(--panel); border-radius: 0; }
.editor-foot { border-radius: 0; background: var(--panel-2); border-top: 1.5px solid var(--ink); }
.result-card { max-height: 34%; }

/* header: paper, one ink rule */
.topbar { background: transparent; border-bottom: 1.5px solid var(--ink); height: 54px; }
.title { font-family: var(--display); font-weight: 800; font-size: 19px; letter-spacing: 0.04em; text-transform: uppercase; gap: 10px; }
.title .logo { width: 26px; height: 26px; border-radius: 0; }
.title-1 { color: var(--gold-text); }
.title-2 { color: var(--ink); }
.loading { background: var(--bg); }
.loading-brand { font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; font-size: 24px; }
.loading-brand img { border-radius: 0; }
.loading-bar { background: var(--line); border-radius: 0; height: 3px; }
.loading-fill { background: var(--ink); border-radius: 0; }

/* display type for labels */
.tl-label, .rail-head, .banner-title, .panel-title, .stage-tag, .pq-tag, .seg-label, .welcome-title, .card-title, .code-title, .ex-group { font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; }
.tl-label { color: var(--ink); font-size: 11px; }
.rail-head { color: var(--ink); }
.welcome-title { font-size: 26px; letter-spacing: 0.02em; color: var(--ink); line-height: 1.1; margin-bottom: 8px; }
.welcome-title .hl { color: var(--gold-text); }
.welcome p { font-size: 14px; }

/* buttons: ink outline + hard shadow, press to flatten */
.btn { border: 1.5px solid var(--ink); border-radius: var(--radius); background: var(--panel); color: var(--ink); box-shadow: 2px 2px 0 var(--ink); font-weight: 600; transition: transform .08s, box-shadow .08s, background .15s; }
.btn:hover { border-color: var(--ink); color: var(--ink); background: var(--accent-3); transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
.btn:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--ink); }
.btn.primary { background: var(--ink); color: #fff; border-color: var(--ink); box-shadow: 2px 2px 0 var(--accent); }
.btn.primary:hover { background: var(--brand-2); color: #fff; box-shadow: 3px 3px 0 var(--accent); }
.btn.next { box-shadow: 3px 3px 0 var(--accent); }
.btn.ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--text-dim); font-family: var(--display); text-transform: uppercase; letter-spacing: 0.06em; font-size: 11px; font-weight: 800; }
.btn.ghost:hover { background: var(--accent-3); border-color: transparent; color: var(--ink); transform: none; box-shadow: none; }
.btn.ghost.on { background: var(--ink); color: #fff; }
.btn.toggle.on { background: var(--accent-3); border-color: var(--ink); color: var(--ink); }
.btn.toggle.playing { background: var(--accent); color: var(--ink); }
.btn:disabled { opacity: .35; box-shadow: 2px 2px 0 var(--ink); transform: none; }
.btn.opt { background: var(--panel); }
.btn.opt:hover { background: var(--accent); border-color: var(--ink); color: var(--ink); }
.select { border: 1.5px solid var(--ink); border-radius: var(--radius); background: var(--panel); color: var(--ink); }

/* execution order: nodes on a wire */
.timeline { padding: 4px 2px 0; }
.tl-chips { position: relative; padding: 4px 0; }
.tl-chips::before { content: ""; position: absolute; left: 4px; right: 4px; top: 50%; border-top: 1.5px solid var(--ink); }
.chip { position: relative; z-index: 1; font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; font-size: 10.5px; border: 1.5px solid var(--ink); border-radius: var(--radius); background: var(--panel); color: var(--ink); padding: 3px 9px; }
.chip .no { color: var(--text-faint); }
.chip.present.done { background: var(--accent-3); color: var(--ink); border-color: var(--ink); }
.chip.present.done .no { color: var(--accent-ink); }
.chip.active { background: var(--ink); color: #fff; border-color: var(--ink); box-shadow: 2px 2px 0 var(--accent); }
.chip.active .no { color: var(--accent); }
.chip.absent { opacity: .45; text-decoration: none; border-style: dashed; color: var(--text-faint); }

/* panels inside the board: flat blocks with a hard shadow */
.panel { border: 1.5px solid var(--ink); border-radius: 0; box-shadow: 3px 3px 0 var(--ink); background: var(--panel); }
.panel-title { background: var(--panel); color: var(--ink); font-size: 10.5px; border-bottom: 1.5px solid var(--ink); border-radius: 0; height: 28px; }
.row.hdr { top: 28px; background: var(--panel); border-bottom: 1.5px solid var(--line-2); }
.panel.lit { border-color: var(--ink); box-shadow: 4px 4px 0 var(--accent); }
.panel.lit .panel-title { background: var(--accent); color: var(--ink); }
.panel.lit.result { border-color: var(--ink); box-shadow: 4px 4px 0 var(--green); }
.panel.lit.result .panel-title { background: var(--green-dim); color: var(--ink); }
.panel.unlit { border-color: var(--line-2); box-shadow: 3px 3px 0 var(--line-2); opacity: .6; filter: none; }
.panel.before { border-style: dashed; box-shadow: none; background: var(--panel-2); }
.panel.before .panel-title, .panel.before .row.hdr { background: var(--panel-2); }
.panel.result { border-color: var(--ink); }
.panel.focus-panel { border-color: var(--ink); box-shadow: 4px 4px 0 var(--accent); }
.panel.dim-panel { box-shadow: 3px 3px 0 var(--line-2); border-color: var(--line-2); }
@keyframes panelPulse { 0% { box-shadow: 4px 4px 0 var(--accent), 0 0 0 10px rgba(242,184,75,0.35); } 100% { box-shadow: 4px 4px 0 var(--accent), 0 0 0 0 rgba(242,184,75,0); } }
.pcount { font-family: var(--sans); text-transform: none; letter-spacing: 0; font-weight: 500; }

/* banners: flat, shadow carries the meaning */
.banner { border: 1.5px solid var(--ink); border-left-width: 1.5px; border-radius: 0; box-shadow: 3px 3px 0 var(--red); margin-right: 3px; }
.banner.notes { border-color: var(--line-2); box-shadow: 3px 3px 0 var(--line-2); background: var(--panel-2); }
.banner-title { color: var(--ink); }
.banner.notes .banner-title { color: var(--text-dim); }

/* narration + predict */
.narration .stage-tag { background: var(--accent); color: var(--ink); border-color: var(--ink); border-radius: var(--radius); }
.narration .cap::after { color: var(--gold-text); }
.pq-tag { background: var(--accent); color: var(--ink); border-color: var(--ink); border-radius: var(--radius); }
.pq.right .pq-tag { background: var(--green-dim); color: var(--green); border-color: var(--green); }
.pq.wrong .pq-tag { background: var(--red-dim); color: var(--red); border-color: var(--red); }

/* editor marks */
.editor .hl mark.clause { background: var(--accent-3); box-shadow: 0 0 0 1.5px var(--accent); border-radius: var(--radius); }
.editor .pointer { background: var(--accent); border-radius: 0; }
.editor .pointer::after { border-left-color: var(--accent); }
.editor .hl .k { color: var(--ink); }

/* progress */
.seg-bar { border-radius: 0; background: var(--line); height: 6px; border: 1px solid var(--line-2); }
.seg-fill { border-radius: 0; background: var(--ink); }
.seg.current .seg-bar { background: var(--accent-3); box-shadow: none; border-color: var(--ink); }
.seg.current .seg-fill { background: var(--accent); }
.seg.current .seg-label { color: var(--accent-ink); }
.seg.done .seg-label { color: var(--ink); }

/* menus, dialogs, misc */
.examples-menu { border: 1.5px solid var(--ink); border-radius: 0; box-shadow: 4px 4px 0 var(--ink); background: var(--panel); }
.ex-item { border-radius: 0; }
.ex-item:hover, .ex-item:focus-visible { background: var(--accent-3); }
.ex-title { color: var(--ink); }
.dialog { border: 1.5px solid var(--ink); border-top-width: 1.5px; border-radius: 0; box-shadow: 6px 6px 0 var(--accent); background: var(--panel); }
.dialog h2 { font-family: var(--display); text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink); }
.toast { background: var(--ink); border-radius: var(--radius); box-shadow: 3px 3px 0 var(--accent); }
.narrow-note { border: 1.5px solid var(--ink); border-radius: 0; background: var(--accent-3); color: var(--ink); }
table.res th { background: var(--panel-2); color: var(--ink); border-bottom: 1.5px solid var(--ink); font-family: var(--display); letter-spacing: 0.05em; }
code { color: var(--ink); background: var(--brand-3); border-radius: var(--radius); }
.foot { padding-top: 4px; }
.status::before { color: var(--green); }
.rail { border-right: 1.5px solid var(--ink); background: transparent; }
.tbl-name { color: var(--ink); }
.col-list .pk { color: var(--accent-ink); }
.link { stroke: var(--ink); }
.link-dot { fill: var(--ink); }
kbd { border-color: var(--ink); border-radius: var(--radius); background: var(--panel); }

/* combined rows: where the left table ends and the right one begins */
.cell.rside { background: rgba(45,42,110,0.05); }
.cell.seam { border-left: 2px solid var(--ink); margin-left: 2px; }
.hdr .cell.rside { color: var(--ink); }
.row.ghost .cell.rside { background: rgba(138,136,158,0.10); }

/* ==================================================================
   FIXED BOARD — the board never scrolls; panels are windows.
   ================================================================== */
.board { overflow: hidden; font-size: 12.5px; }
.board-inner { height: 100%; display: flex; flex-direction: column; padding: 12px 14px 14px; }
.panels { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 14px; }
.panels.layout-column { flex-direction: column; }
.prow { display: flex; gap: 22px; align-items: flex-start; min-height: 0; flex: 0 1 auto; overflow-x: auto; overflow-y: hidden; padding: 0 6px 6px 0; }
.prow::-webkit-scrollbar { height: 6px; }
.panel { display: flex; flex-direction: column; max-height: 100%; min-height: 0; flex: 0 0 auto; }
.panel-title { position: static; flex: 0 0 auto; }
.tbl { flex: 0 1 auto; min-height: 0; overflow: auto; padding: 0 0 2px; scrollbar-width: thin; }
.row.hdr { top: 0; }
.break { display: none; }
/* denser rows: 12 rows fit in ~190px */
.row { padding: 0 6px; line-height: 1.3; }
.cell { padding: 0 6px; }
.row.ghdr { margin-top: 4px; }
.badge { font-size: 9.5px; }
/* the editor stays short while watching; the active clause scrolls into view by itself */
.app.rail-hidden .editor { max-height: 150px; }
/* strip: absent clauses are thin grey stubs */
.seg.absent { flex: 0 0 auto; width: 34px; min-width: 0; cursor: default; opacity: .55; }
.seg.absent .seg-bar { background: transparent; border: 1px dashed var(--line-2); }
.seg.absent .seg-label { color: var(--text-faint); text-decoration: line-through; }
.progress { min-width: 260px; }
.controls { padding-top: 4px; }
.frame-no { min-width: 48px; }

/* ==================================================================
   CODE <-> BOARD TAGS: the same colour on a word in the code and on the thing
   it produced. t1 = a table, t2 = the left key, t3 = the right key, num = output column n.
   ================================================================== */
:root { --t1: var(--ink); --t2: var(--accent); --t3: #0EA5E9; --t3-ink: #075985; --t3-3: #E3F4FC; }
.editor .hl mark.tag { background: none; color: inherit; padding: 0 1px 1px; margin: 0; border-radius: 0; border-bottom: 3px solid var(--ink); box-shadow: none; }
.editor .hl mark.tag.t1 { border-color: var(--t1); }
.editor .hl mark.tag.t2 { border-color: var(--t2); background: var(--accent-3); }
.editor .hl mark.tag.t3 { border-color: var(--t3); background: var(--t3-3); }
.editor .hl mark.tag.num { border-bottom-style: dotted; border-color: var(--ink); }
.editor .hl mark.tag.num::after { content: attr(data-n); display: inline-block; font-family: var(--display); font-size: 9px; font-weight: 800; line-height: 1; vertical-align: super; background: var(--ink); color: #fff; padding: 1px 3px; margin-left: 2px; border-radius: 2px; }
/* dimmed lines stay readable and their tags stay vivid (dim by colour, not opacity) */
.editor.focus-mode .hl .dimmed { opacity: 1; color: var(--text-faint); }
.editor.focus-mode .hl .dimmed span { color: var(--text-faint); }
.editor.focus-mode .hl .dimmed mark.tag { color: var(--text-dim); }
.editor.focus-mode .hl .dimmed mark.tag span { color: var(--text-dim); }
/* on the board */
.hdr .cell.t1 { box-shadow: inset 0 -3px 0 var(--t1); }
.hdr .cell.t2 { box-shadow: inset 0 -3px 0 var(--t2); background: var(--accent-3); color: var(--accent-ink); }
.hdr .cell.t3 { box-shadow: inset 0 -3px 0 var(--t3); background: var(--t3-3); color: var(--t3-ink); }
.cell.ref.t3 { background: var(--t3-3); color: var(--t3-ink); text-decoration-color: var(--t3); }
.cnum { display: inline-block; font-family: var(--display); font-size: 9px; font-weight: 800; line-height: 1; vertical-align: super; background: var(--ink); color: #fff; padding: 1px 3px; margin-left: 3px; border-radius: 2px; }
.ptag { display: inline-block; width: 9px; height: 9px; margin-right: 6px; vertical-align: -1px; border: 1.5px solid var(--ink); background: var(--panel); }
.ptag.t1 { background: var(--t1); }
.ptag.t2 { background: var(--t2); }
.ptag.t3 { background: var(--t3); }

/* ==================================================================
   STABLE GEOMETRY
   ================================================================== */
.row:not(.ghdr) { min-height: 17px; }
.badge { margin-left: 0; line-height: 1.2; padding: 0 5px; }
.cell.badgecol { padding: 0 4px; overflow: visible; }
.spacer { flex: 0 0 auto; }
/* a row of panels wider than the board shrinks its type instead of being cut off */
.prow.compact { font-size: 11px; }
.prow.tight { font-size: 9.5px; }
.prow.compact .row:not(.ghdr), .prow.tight .row:not(.ghdr) { min-height: 15px; }

/* ==================================================================
   FIXED EXPLANATION BLOCK — the board below never moves
   ================================================================== */
.explain { flex: 0 0 auto; height: 118px; display: flex; flex-direction: column; gap: 8px; min-height: 0; margin-top: var(--d); }
.explain .predict, .explain .narration { margin-top: 0; }
.explain .predict { flex: 0 0 auto; padding: 7px 14px; }
.explain .narration { flex: 1 1 auto; min-height: 0; overflow: auto; scrollbar-width: thin; }
.narration:empty::before { content: ""; }
.explain:has(.predict[hidden]) .narration { font-size: 14.5px; }
.explain:has(.predict:not([hidden])) .narration { font-size: 13.5px; padding: 7px 14px; line-height: 1.45; }
/* bucket header rows: same height as data rows, so reserved heights are exact */
.row.ghdr { margin-top: 0; min-height: 17px; }

/* header slots waiting for their column name */
.hdr .cell.pending { background: repeating-linear-gradient(135deg, transparent 0 4px, rgba(45,42,110,0.08) 4px 6px); box-shadow: inset 0 0 0 1px var(--line-2); border-radius: 2px; }
.hdr .cell.pending.rside { background-color: transparent; }

/* bigger type where there is room: the loading screen and the resting database view */
.loading-brand { font-size: 30px; gap: 18px; }
.loading-box { width: 300px; }
.loading-bar { height: 4px; }
.board { font-size: 13px; }
.board.idle { font-size: 13px; }   /* same type as while a query runs */
.board.idle .prow { gap: 28px; }

/* brand reads as one word; only the mark keeps a gap */
.title { gap: 0; }
.title .logo { margin-right: 10px; }
.loading-brand > div { letter-spacing: 0.06em; }
/* the resting database view is one frame: let its tables wrap and scroll instead of hiding */

/* empty header slots must still have a body */
.hdr .cell.pending { min-height: 14px; align-self: stretch; background: repeating-linear-gradient(135deg, transparent 0 4px, rgba(45,42,110,0.16) 4px 6px); box-shadow: inset 0 0 0 1.5px var(--line-2); }
.cell.badgecol { min-height: 1px; }
/* progress strip: clauses the query does not use are tiny dots, so the used ones get the room */
.seg.absent { width: 10px; opacity: .7; }
.seg.absent .seg-bar { height: 6px; border: 1.5px dashed var(--line-2); background: transparent; }
.seg.absent .seg-label { display: none; }
.progress { min-width: 300px; }
/* explanation block: enough for two lines plus the question, no more */
.explain { height: 104px; }
.explain:has(.predict[hidden]) .narration { font-size: 14px; }

/* every used clause gets room for its name; the step hint yields first */
.seg:not(.absent) { min-width: 60px; }
.progress { min-width: 360px; }
.next-hint { min-width: 0; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.result-btn .meta { display: none; }

/* resting view: one row, whole tables, type sized by the board (see Board.fitIdle) */
.board.idle { overflow: hidden; }
.board.idle .board-inner { height: auto; min-height: 100%; }
.board.idle .panels { display: flex; flex-direction: column; gap: 14px; }
.board.idle .prow { flex-wrap: nowrap; overflow: visible; align-items: flex-start; padding: 0; gap: 1.6em; }
.board.idle .prow.grid2 { display: grid; grid-template-columns: repeat(2, max-content); gap: 1.4em 1.6em; justify-content: start; }
.board.idle .panel { max-height: none; flex: 0 0 auto; }
.board.idle .tbl { overflow: visible; }


.board.idle.overflow { overflow: auto; }

/* ==================================================================
   THE CARD IN HAND (JOIN): one object the eye can follow
   ================================================================== */
.row.blank { background: transparent !important; border-bottom-color: transparent !important; border-left-color: transparent !important; }
.row.held { background: var(--accent-3); border-left-color: var(--accent); font-weight: 700; box-shadow: 2px 2px 0 var(--ink); outline: 1.5px solid var(--ink); outline-offset: -1px; }
.row.held .cell { color: var(--text); }
.row.taken { opacity: .45; outline: 1.5px dashed var(--accent); outline-offset: -1.5px; background: transparent !important; }
.row.taken .cell { color: var(--text-faint); }
.panel[data-panel="hand"] { box-shadow: none; border-style: dashed; background: transparent; }
.panel[data-panel="hand"] .panel-title { background: transparent; color: var(--accent-ink); border-bottom-style: dashed; }
.panel[data-panel="hand"].lit { box-shadow: none; border-color: var(--accent); }
.panel[data-panel="hand"].lit .panel-title { background: var(--accent-3); }
.panel[data-panel="hand"] .row.hdr { background: transparent; }
.panel[data-panel="hand"] .empty { color: var(--text-faint); }

/* comparison links: the verdict is drawn on the line between the two cells */
.link.keep { stroke: var(--green); }
.link-dot.keep { fill: var(--green); }
.link.drop { stroke: var(--red); stroke-dasharray: 5 4; animation: none; stroke-dashoffset: 0; }
.link-dot.drop { fill: var(--red); }
.link.null { stroke: var(--grey); stroke-dasharray: 3 4; animation: none; stroke-dashoffset: 0; }
.link-label rect { fill: var(--panel); stroke-width: 1.5; }
.link-label text { font-family: var(--mono); font-weight: 700; font-size: 1em; }
.link-label.keep rect { stroke: var(--green); } .link-label.keep text { fill: var(--green); }
.link-label.drop rect { stroke: var(--red); } .link-label.drop text { fill: var(--red); }
.link-label.null rect { stroke: var(--grey); } .link-label.null text { fill: var(--grey); }
.link-label { opacity: 0; animation: linkDot .2s ease-out forwards; animation-delay: calc(var(--link-delay, 0ms) + .3s); }

.link-label text { font-size: 0.9em; }

/* room between the card in hand and the right table for the comparison labels */
.panel[data-panel="hand"] + .panel { margin-left: 70px; }

/* ==================================================================
   THE CLAUSE ON THE BOARD — the words the animation is made of
   ================================================================== */
.panel.code { border-style: solid; background: var(--panel); box-shadow: 3px 3px 0 var(--ink); flex: 0 0 auto; max-width: 100%; }
.panel.code.lit { box-shadow: 4px 4px 0 var(--accent); }
.code-strip { font-family: var(--mono); font-size: 15px; font-weight: 600; padding: 9px 16px 6px 12px; white-space: pre-wrap; color: var(--text-dim); line-height: 1.5; }
.code-label { display: inline-block; font-family: var(--display); font-weight: 800; font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); background: var(--accent); padding: 2px 6px; margin-right: 12px; vertical-align: 2px; }
.tok { position: relative; display: inline-block; }
.tok.kw { color: var(--ink); font-weight: 800; }
.tok.t1, .tok.t2, .tok.t3, .tok.num { color: var(--text); padding: 0 3px 1px; border-bottom: 3px solid var(--ink); }
.tok.t1 { border-color: var(--t1); }
.tok.t2 { border-color: var(--t2); background: var(--accent-3); }
.tok.t3 { border-color: var(--t3); background: var(--t3-3); }
.tok.num { border-bottom-style: dotted; }
.tok.num::after { content: attr(data-n); display: inline-block; font-family: var(--display); font-size: 9px; font-weight: 800; line-height: 1; vertical-align: super; background: var(--ink); color: #fff; padding: 1px 3px; margin-left: 2px; border-radius: 2px; }
.tok-group { display: inline; }
.tok-note { position: absolute; left: 0; top: 100%; margin-top: 3px; font-family: var(--display); font-size: 8.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; color: var(--text-faint); line-height: 1; }
.tok.t1 .tok-note { color: var(--t1); }
.tok.t2 .tok-note { color: var(--accent-ink); }
.tok.t3 .tok-note { color: var(--t3-ink); }
.tok.kw .tok-note { color: var(--ink); }

/* the clause strip keeps its full height even when the tables below must shrink */
.prow.prow-code { flex: 0 0 auto; overflow: visible; padding-bottom: 8px; }


.tok-note.n2 { margin-top: 16px; }

/* the legend under the clause: word → meaning */
.code-legend { display: flex; flex-wrap: wrap; gap: 4px 18px; padding: 0 14px 9px 12px; font-size: 11px; color: var(--text-dim); }
.lg { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.lg-tok { font-family: var(--mono); font-weight: 700; color: var(--text); border-bottom: 2.5px solid var(--ink); padding: 0 2px; }
.lg-tok.kw { color: var(--ink); border-bottom-color: transparent; }
.lg-tok.t1 { border-bottom-color: var(--t1); }
.lg-tok.t2 { border-bottom-color: var(--t2); background: var(--accent-3); }
.lg-tok.t3 { border-bottom-color: var(--t3); background: var(--t3-3); }
.lg-arrow { color: var(--text-faint); }
.lg-note { font-family: var(--display); font-weight: 800; font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.tok-note { display: none; }
.prow.prow-code { padding-bottom: 8px; }

/* fast-forward ribbon: several steps happen at once, and the board says so */
.ribbon { position: absolute; top: 10px; right: 14px; z-index: 6; display: inline-flex; align-items: center; gap: 8px; padding: 5px 12px; background: var(--accent); color: var(--ink); border: 1.5px solid var(--ink); box-shadow: 3px 3px 0 var(--ink); font-family: var(--display); font-weight: 800; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; animation: ribbonIn .45s cubic-bezier(.22,.8,.26,1) both; }
.ribbon-icon { font-size: 14px; line-height: 1; }
@keyframes ribbonIn { from { transform: translateY(-14px); opacity: 0; } to { transform: none; opacity: 1; } }
.row.fast { background: repeating-linear-gradient(135deg, transparent 0 6px, rgba(242,184,75,0.35) 6px 9px) !important; }

/* ==================================================================
   WHAT CHANGED — eased colours for state changes, one flash for new text
   ================================================================== */
.row { transition: background-color .5s ease, color .5s ease, opacity .5s ease, border-color .5s ease, outline-color .5s ease; }
.cell { transition: color .5s, background-color .5s, opacity .5s; }
.cell.chg, .ptitle.chg, .pcount.chg { animation: chgFlash 1.3s ease-out; }
@keyframes chgFlash {
  0%   { box-shadow: inset 0 0 0 2px var(--accent); background-color: var(--accent); color: var(--ink); }
  35%  { box-shadow: inset 0 0 0 2px var(--accent); background-color: var(--accent-3); }
  100% { box-shadow: inset 0 0 0 0 transparent; }
}
.cell.verdict.chg { animation-duration: 1.6s; }
@media (prefers-reduced-motion: reduce) { .cell.chg, .ptitle.chg, .pcount.chg { animation: none; } }

/* the clause strip has ONE height, in every stage: one line of code, one line of legend */
.panel.code { width: 100%; max-width: 100%; }
.code-strip { height: 42px; box-sizing: border-box; padding: 9px 16px 0 12px; white-space: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.code-strip::-webkit-scrollbar { display: none; }
.code-legend { height: 24px; box-sizing: border-box; flex-wrap: nowrap; overflow: hidden; align-items: center; padding: 0 14px 4px 12px; }
.code-legend.empty { visibility: hidden; }
.prow.prow-code { padding-bottom: 8px; }
.board.idle .prow.prow-code { padding-bottom: 8px; }

/* ==================================================================
   VERTICAL BUDGET — everything that is not the board gets exactly what it needs
   ================================================================== */
/* explanation: two lines of caption, no more */
.explain { height: 58px; }
.explain .narration { font-size: 14px; padding: 8px 14px; line-height: 1.45; }
.explain:has(.predict[hidden]) .narration, .explain:has(.predict:not([hidden])) .narration { font-size: 14px; padding: 8px 14px; line-height: 1.45; }
/* prediction: floats over the board's empty bottom-right corner, takes no layout height */
.board-wrap { position: relative; }
.board-wrap .predict { position: absolute; right: 16px; bottom: 14px; z-index: 7; max-width: min(720px, calc(100% - 32px)); margin: 0; padding: 8px 14px; background: var(--accent-3); border: 1.5px solid var(--ink); box-shadow: 4px 4px 0 var(--ink); font-size: 13.5px; flex-wrap: wrap; gap: 6px 14px; animation: ribbonIn .45s cubic-bezier(.22,.8,.26,1) both; }
.board-wrap .predict::before, .board-wrap .predict::after { display: none; }
.board-wrap .predict .pq-opts { gap: 6px; }
/* the editor steps back while watching: the clause that matters is on the board */
.app.rail-hidden .editor { max-height: 96px; }
.app.rail-hidden .editor .hl, .app.rail-hidden .editor textarea { font-size: 13px; line-height: 1.45; padding-top: 7px; padding-bottom: 7px; }
.app.rail-hidden .editor-foot { padding: 3px 8px 3px 14px; }
.app.rail-hidden .editor-foot .btn { padding: 4px 10px; }
/* welcome: one breath, not a poster */
.welcome { padding: 10px 16px; }
.welcome-title { font-size: 20px; margin-bottom: 4px; }
.welcome p { margin: 2px 0; font-size: 13.5px; }
.welcome-actions { flex-direction: row; gap: 8px; }
/* the board gets a little more of its own frame */
.board-inner { padding: 10px 14px 12px; }
.prow.prow-code, .board.idle .prow.prow-code { padding-bottom: 6px; }
.controls { padding-top: 2px; }
.status:empty { display: none; }
.status::before { content: "● "; color: var(--green); }

/* ==================================================================
   ZONES — INPUT (the database) / WORK (the table so far) / OUTPUT (the result)
   ================================================================== */
.panels { gap: 10px; }
.zone { display: flex; flex-direction: column; min-height: 0; position: relative; border-left: 3px solid var(--line-2); padding-left: 12px; }
.zone-input { flex: 0 0 auto; }
.zone-work { flex: 1 1 auto; }
.zone-output { flex: 0 0 auto; }
.zone-focus { border-left-color: var(--accent); }
.zone-label { display: flex; align-items: baseline; gap: 10px; margin: 0 0 6px; }
.zone-name { font-family: var(--display); font-weight: 800; font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink); background: var(--panel); border: 1.5px solid var(--ink); padding: 1px 7px; }
.zone-focus .zone-name { background: var(--accent); }
.zone-hint { font-size: 11px; color: var(--text-faint); }
.zone-body { display: flex; flex-direction: column; gap: 14px; min-height: 0; }
.zone-work .zone-body { flex: 1 1 auto; }
.zone-note { font-family: var(--mono); font-style: italic; color: var(--text-faint); font-size: 12px; padding: 6px 2px; }
.zone-empty { opacity: .8; }
/* tiles: the database, folded */
.panel.tile { box-shadow: 2px 2px 0 var(--ink); }
.panel.tile .panel-title { height: 24px; padding-top: 4px; font-size: 10px; }
.panel.tile .row.hdr { font-size: 11px; min-height: 15px; color: var(--text-faint); }
.panel.tile .row.tilerow { min-height: 16px; font-family: var(--display); font-weight: 800; font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.panel.tile.taken { border-style: dashed; box-shadow: none; background: transparent; }
.panel.tile.taken .panel-title { background: transparent; color: var(--text-faint); border-bottom-style: dashed; }
.panel.tile.taken .row.hdr { opacity: .5; }
.panel.tile.taken .row.tilerow { color: var(--accent-ink); }
.zone-input .prow { gap: 14px; padding-bottom: 4px; }
/* the output slot */
.panel.slot { border-style: dashed; box-shadow: none; background: transparent; width: 100%; max-width: 100%; }
.panel.slot .panel-title { background: transparent; color: var(--text-faint); border-bottom: 0; height: 24px; padding-top: 4px; font-size: 10px; }
.panel.slot .row.hdr { display: none; }
.panel.slot .empty { padding: 0 10px 6px; color: var(--text-faint); font-size: 11.5px; }
.zone-output .panel.result { width: auto; }
.zone-output .prow { padding-bottom: 6px; }
/* the RESULT frame: OUTPUT takes the room WORK leaves */
/* whole-database views (idle, FROM's first frame): INPUT is the big thing */
.board.idle .zone-input .prow { flex-wrap: nowrap; }

/* tighter zones: INPUT and OUTPUT take only what they need */
.zone-label { margin: 0 0 4px; }
.panel.tile .row.hdr { display: none; }
.panel.tile .panel-title { height: 22px; padding-top: 3px; }
.panel.tile .row.tilerow { min-height: 15px; }
.panel.tile .pcount { display: none; }
.panel.slot .panel-title { height: 22px; padding-top: 3px; }
.panel.slot .empty { display: none; }
.zone-output .prow { padding-bottom: 4px; }
.zone-input .prow { padding-bottom: 3px; }
.panels { gap: 8px; }
/* in whole-database views the WORK zone must not stretch, or the fit would think the board is full */
.board.idle .zone-work { flex: 0 0 auto; }
.board.idle .zone-work .zone-body { flex: 0 0 auto; }

/* a pointed-at INPUT tile: named by the clause, not yet moved */
.panel.tile.pointed { border-color: var(--accent); box-shadow: 3px 3px 0 var(--accent); animation: panelPulse 1s ease-out; }
.panel.tile.pointed .panel-title { background: var(--accent); color: var(--ink); }

/* ==================================================================
   WORK | OUTPUT side by side — the result slides right into a tray that
   already has its final size
   ================================================================== */
.zone-row { display: flex; gap: 18px; flex: 1 1 auto; min-height: 0; align-items: stretch; }
.zone-row .zone-work { flex: 1 1 auto; min-width: 0; }
.zone-row .zone-output { flex: 0 0 auto; max-width: 38%; min-width: 160px; }
.zone-output .zone-body { flex: 1 1 auto; min-height: 0; }
.zone-output .prow { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 6px 6px 0; }
.zone-output .panel { max-height: 100%; }
.panel.slot { width: auto; border-style: dashed; }
.panel.slot .panel-title { border-bottom: 1.5px dashed var(--line-2); height: 28px; padding-top: 5px; }
.panel.slot .row.hdr { display: flex; }
.panel.slot .hdr .cell.pending { min-height: 14px; }
.panel.slot .empty { display: block; padding: 8px 10px; color: var(--text-faint); font-size: 11.5px; }
.panel.done { border-style: dashed; box-shadow: none; }
.panel.done .panel-title { background: var(--panel-2); color: var(--text-faint); }
.board.idle .zone-row { flex: 0 0 auto; }
.board.idle .zone-output { min-width: 200px; }
/* WORK gave a column to the tray: tighter gaps so the JOIN row still fits at full size */
.zone-work .prow { gap: 18px; }
.panel[data-panel="hand"] + .panel { margin-left: 56px; }

/* the rule drawn between the two key columns */
.link.rule { stroke: var(--ink); stroke-width: 2; }
.link-dot.rule { fill: var(--ink); }
.link-label.rule rect { stroke: var(--ink); fill: var(--accent-3); } .link-label.rule text { fill: var(--ink); }

/* a column that has just been named and is about to move */
.hdr .cell.pointcol { background: var(--accent) !important; color: var(--ink) !important; box-shadow: inset 0 -3px 0 var(--ink); }
