/* ==========================================================================
   Variable atlas

   Palette is taken from Ordnance Survey mapping rather than the usual
   editorial cream: drafting-film paper, deep ink, contour magenta as the
   single accent, ochre for attention, moss for verified. The subject is a
   life course being mapped, so map colours are the honest source.

   Monospace is the DISPLAY face, not just the code face. Every noun in this
   corpus is a code - a variable name, a value label, a file - so setting
   headings in mono is true to the material. Body copy stays in a sans.
   ========================================================================== */

:root {
  --paper:    #e9ece7;
  --paper-2:  #f5f7f3;
  --paper-3:  #dfe3dc;
  --ink:      #131a22;
  --ink-2:    #4d5862;
  --ink-3:    #78838c;
  --rule:     #c5ccc3;
  --contour:  #8e2f6b;
  --ochre:    #9a6410;
  --moss:     #2c6b50;
  --sea:      #2a5c8a;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  --step: 4px;
  --rail: 400px;
  --chat-w: 420px;
  --shadow: 0 1px 0 rgba(19, 26, 34, .04), 0 2px 10px -6px rgba(19, 26, 34, .18);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:   #11171b;
    --paper-2: #192026;
    --paper-3: #232c33;
    --ink:     #e7ece7;
    --ink-2:   #9aa6ac;
    --ink-3:   #6d7a82;
    --rule:    #2b353d;
    --contour: #e879b8;
    --ochre:   #d9a145;
    --moss:    #6cc198;
    --sea:     #82b8e8;
    --shadow:  0 1px 0 rgba(0, 0, 0, .3), 0 2px 12px -6px rgba(0, 0, 0, .7);
  }
}

:root[data-theme="dark"] {
  --paper:   #11171b;  --paper-2: #192026;  --paper-3: #232c33;
  --ink:     #e7ece7;  --ink-2:   #9aa6ac;  --ink-3:   #6d7a82;
  --rule:    #2b353d;  --contour: #e879b8;  --ochre:   #d9a145;
  --moss:    #6cc198;  --sea:     #82b8e8;
  --shadow:  0 1px 0 rgba(0, 0, 0, .3), 0 2px 12px -6px rgba(0, 0, 0, .7);
}
:root[data-theme="light"] {
  --paper:   #e9ece7;  --paper-2: #f5f7f3;  --paper-3: #dfe3dc;
  --ink:     #131a22;  --ink-2:   #4d5862;  --ink-3:   #78838c;
  --rule:    #c5ccc3;  --contour: #8e2f6b;  --ochre:   #9a6410;
  --moss:    #2c6b50;  --sea:     #2a5c8a;
  --shadow:  0 1px 0 rgba(19, 26, 34, .04), 0 2px 10px -6px rgba(19, 26, 34, .18);
}

* { box-sizing: border-box; }

/* Any rule that sets `display` outranks the `hidden` attribute's UA default,
   so a hidden .btn or .pinned stays on screen. Everything on this page that
   toggles visibility does it with `hidden`, so it is settled once here. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--sea); }

code, kbd { font-family: var(--mono); font-size: .92em; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--contour); color: #fff; padding: 8px 14px;
}
.skip:focus { left: 8px; top: 8px; }

:where(button, a, input, select, textarea):focus-visible {
  outline: 2px solid var(--contour);
  outline-offset: 2px;
}

/* ── Masthead ─────────────────────────────────────────────────────── */

.masthead {
  display: flex; align-items: center; gap: 20px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-2);
  flex-wrap: wrap;
}

.mark { display: flex; align-items: baseline; gap: 8px; margin-right: auto; }

.mark-name {
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.04em;
}

.mark-sub {
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--ink-3);
}

.views { display: flex; gap: 2px; }

.view-tab {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 7px 13px;
  border: 1px solid transparent;
  border-radius: 2px;
  background: none;
  color: var(--ink-2);
  cursor: pointer;
}
.view-tab:hover { color: var(--ink); background: var(--paper-3); }
.view-tab.is-current {
  color: var(--contour);
  border-color: var(--rule);
  background: var(--paper);
  font-weight: 700;
}

.tally {
  display: inline-block; min-width: 17px; margin-left: 5px;
  padding: 0 4px; border-radius: 9px;
  background: var(--contour); color: #fff;
  font-size: 10px; text-align: center;
}

.theme {
  width: 30px; height: 30px; padding: 0;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper); cursor: pointer;
}
.theme::after { content: "◑"; color: var(--ink-2); font-size: 15px; }

/* ── The spine ────────────────────────────────────────────────────── */

.spine {
  padding: 12px 20px 14px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-2);
}

.spine-head {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 9px;
  font-family: var(--mono); font-size: 11px;
  text-transform: uppercase; letter-spacing: .12em;
}
.spine-title { color: var(--ink-3); }
.spine-note { color: var(--contour); text-transform: none; letter-spacing: .02em; }

.spine-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 3px;
  margin: 0; padding: 0; list-style: none;
}

.node {
  display: flex; flex-direction: column; align-items: stretch; gap: 5px;
  padding: 5px 3px 4px;
  border: 1px solid transparent;
  border-radius: 2px;
  background: none;
  cursor: pointer;
  font: inherit;
  width: 100%;
}
.node:hover { background: var(--paper-3); }
.node[aria-pressed="true"] { border-color: var(--contour); background: var(--paper); }

.node-bar {
  height: 26px;
  display: flex; align-items: flex-end;
  border-bottom: 2px solid var(--rule);
}
.node-fill {
  width: 100%;
  background: var(--contour);
  min-height: 2px;
  transition: height .18s ease;
}
/* Absence is information here, so an empty wave is drawn as a dashed void
   rather than simply being a shorter bar. */
.node.is-empty .node-bar { border-bottom-style: dashed; }
.node.is-empty .node-fill { background: none; }

.node-age {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink-2);
}
.node[aria-pressed="true"] .node-age { color: var(--contour); }
.node-n { font-family: var(--mono); font-size: 10px; color: var(--ink-3); }
.node.is-empty .node-age, .node.is-empty .node-n { color: var(--ink-3); }

/* ── Layout ───────────────────────────────────────────────────────── */

main { flex: 1; min-height: 0; }

.view { display: none; height: 100%; }
.view.is-current {
  display: grid; grid-template-columns: var(--rail) 1fr;
  position: relative;   /* the grip below is positioned against this */
}

.pane { min-height: 0; overflow-y: auto; }
.pane-list { border-right: 1px solid var(--rule); background: var(--paper-2); }
.pane-detail { padding: 24px 28px 60px; }

/* ── The pane divider ─────────────────────────────────────────────────

   Absolutely positioned over the border rather than made a third grid track:
   the two-column layout stays exactly as it was, and the hit area can be
   wider than the 1px rule it sits on without pushing anything around.

   `--rail` lives on :root, so all three views share one width. That is
   deliberate — the list column means the same thing in each, and a width you
   set while reading raw variables should still be there when you switch to
   research ready. It is the same arrangement the assistant drawer uses for
   --chat-w. */
.grip {
  position: absolute; top: 0; bottom: 0;
  left: calc(var(--rail) - 3px); width: 7px;
  z-index: 5;
  cursor: col-resize;
  background: none; border: 0;
}
.grip:hover, .grip:focus-visible { background: var(--contour); opacity: .35; }
.grip:focus-visible { outline: none; }
/* While dragging, the whole page keeps the resize cursor and stops selecting
   text under the pointer — otherwise a drag across the list highlights it. */
body.is-resizing { cursor: col-resize; user-select: none; }
body.is-resizing .grip { background: var(--contour); opacity: .5; }

/* ── Finder ───────────────────────────────────────────────────────── */

.finder {
  position: sticky; top: 0; z-index: 4;
  padding: 16px 16px 12px;
  background: var(--paper-2);
  border-bottom: 1px solid var(--rule);
}

.field { display: block; margin-bottom: 14px; }
.field:last-child { margin-bottom: 0; }

.field-label {
  display: block; margin-bottom: 5px;
  font-family: var(--mono); font-size: 11px;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-3);
}
.field-label em { font-style: normal; color: var(--contour); text-transform: lowercase; letter-spacing: 0; }

.field-help { display: block; margin-top: 5px; font-size: 12px; color: var(--ink-3); }

input[type="search"], input[type="text"], input:not([type]), select, textarea {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono); font-size: 13px;
}
textarea { font-family: var(--sans); font-size: 14px; resize: vertical; }
input::placeholder, textarea::placeholder { color: var(--ink-3); }

.finder-meta {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
}
.finder-help { margin: 4px 0 0; font-size: 12px; color: var(--ink-3); }

.link-btn {
  border: 0; background: none; padding: 0;
  color: var(--contour); cursor: pointer;
  font-family: var(--mono); font-size: 11px;
}

/* Facets: measurement level in the metadata view, category in the derived
   one. Toggles, not a select, because the count beside each option is half
   the information - and a zero is kept visible rather than dropped. */
.facet-group { margin-bottom: 12px; }

.facets { display: flex; flex-wrap: wrap; gap: 4px; }

.facet {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 3px 8px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--mono); font-size: 11px;
  cursor: pointer;
}
.facet:hover:not(:disabled) { border-color: var(--ink-2); color: var(--ink); }
.facet.is-on {
  border-color: var(--contour); color: var(--contour);
  font-weight: 700;
  box-shadow: inset 0 -2px 0 var(--contour);
}
.facet-n { font-size: 10px; color: var(--ink-3); font-weight: 400; }
.facet.is-on .facet-n { color: var(--contour); }
.facet.is-empty { border-style: dashed; color: var(--ink-3); }
.facet:disabled { cursor: default; opacity: .7; }

.chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 7px;
  border: 1px solid var(--contour); border-radius: 2px;
  background: var(--paper);
  color: var(--contour);
  font-family: var(--mono); font-size: 11px;
  cursor: pointer;
}

/* ── Selecting variables to download ──────────────────────────────────
   Sits under the derived view's filters. Present even with nothing ticked,
   because otherwise the feature is invisible until you find the checkboxes
   that are the only thing announcing it. */

.picked {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center; gap: 6px 10px;
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.picked-count {
  margin: 0;
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
}
.picked-count strong { color: var(--ink); }
.picked-warn { color: var(--ochre); }
/* The count line doubling as a status line — see say() in atlas/basket.js. */
.picked-count.is-saying { color: var(--ochre); }
.picked-actions { display: flex; gap: 10px; grid-row: 1; grid-column: 2; justify-self: end; }
.picked .btn { grid-column: 1 / -1; width: 100%; }
/* The affirmative twin of .warn — for telling someone the thing they were
   about to look for is already handled. */
.note-box {
  display: flex; gap: 10px;
  margin: 0 0 16px; padding: 10px 12px;
  border-left: 2px solid var(--moss);
  background: color-mix(in srgb, var(--moss) 8%, transparent);
  font-size: 13px;
}
.note-box > span { color: var(--moss); font-weight: 700; }

/* ── Result list ──────────────────────────────────────────────────── */

.results { list-style: none; margin: 0; padding: 0; }

.row {
  width: 100%; text-align: left;
  display: block; padding: 9px 16px;
  border: 0; border-bottom: 1px solid var(--rule);
  background: none; cursor: pointer; font: inherit;
}
.row:hover { background: var(--paper-3); }
.row.is-current { background: var(--paper); box-shadow: inset 3px 0 0 var(--contour); }

/* An add control beside the row, sharing its bottom rule so the two read as
   one line rather than as a control floating over a list. The hover and the
   open-row marker belong to the whole line for the same reason: anything
   drawn on the button alone starts to the right of the control and leaves it
   stranded outside. */
.pickable {
  display: flex; align-items: stretch;
  border-bottom: 1px solid var(--rule);
}
.pickable .row { border-bottom: 0; }
.pickable:hover { background: var(--paper-3); }
.pickable.is-current {
  background: var(--paper);
  box-shadow: inset 3px 0 0 var(--contour);
}
.pickable.is-current .row { background: none; }

/* The ＋, and the ✓ it becomes. Quiet until the row is hovered or it is
   focused: 300 result rows each shouting an affordance is noise, but the
   gesture still has to be discoverable and reachable without a mouse. */
.add {
  flex: 0 0 auto; align-self: center;
  margin-left: 10px; width: 22px; height: 22px;
  display: grid; place-items: center;
  padding: 0; border: 1px solid transparent; border-radius: 2px;
  background: none; color: var(--ink-3);
  font-family: var(--mono); font-size: 13px; line-height: 1;
  cursor: pointer;
  opacity: .45; transition: opacity .12s, color .12s, border-color .12s;
}
.pickable:hover .add, .add:focus-visible { opacity: 1; }
.add:hover { border-color: var(--contour); color: var(--contour); }
/* In the bundle, and removable. The ✓ becomes ✕ under the pointer because
   "already in" and "click to remove" are different statements, and a control
   that only ever says the first reads as a dead end. */
.add.is-in { opacity: 1; color: var(--moss); border-color: transparent; }
.add .add-no { display: none; }
.add.is-in:hover, .add.is-in:focus-visible { color: var(--contour); }
.add.is-in:hover .add-yes, .add.is-in:focus-visible .add-yes { display: none; }
.add.is-in:hover .add-no, .add.is-in:focus-visible .add-no { display: inline; }

/* Not a button: the identifier is in every download whether you ask or not,
   so this states a fact rather than offering an action. */
.add.is-always { opacity: 1; color: var(--ink-3); cursor: default; }

/* ── A family of research-ready variables ─────────────────────────────
   One concept measured at each wave. People want all of it or none of it far
   more often than one wave of it, so the header carries a control for the
   whole family — and a disclosure, because twelve rows you have already taken
   are twelve rows in the way of the next thing. */

.fam {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 16px 8px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}

.fam-twist {
  flex: 0 0 auto; width: 16px; height: 16px;
  display: grid; place-items: center;
  padding: 0; border: 0; background: none;
  color: var(--ink-3); font-size: 10px; cursor: pointer;
  transition: transform .12s;
}
.fam-twist:hover { color: var(--ink); }
.fam.is-collapsed .fam-twist { transform: rotate(-90deg); }

.fam-what { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.fam-name {
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink);
}
.fam-meta { font-size: 11px; color: var(--ink-3); }

.fam-add {
  flex: 0 0 auto;
  padding: 3px 8px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper-2); color: var(--ink-2);
  font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .06em;
  cursor: pointer; white-space: nowrap;
}
.fam-add:hover { border-color: var(--contour); color: var(--contour); }
.fam-add.is-in { color: var(--moss); border-color: var(--moss); }
.fam-add.is-in:hover { color: var(--contour); border-color: var(--contour); }

/* A sibling sits under its header, and a rule down the left says which header
   it belongs to - the list alternates grouped and ungrouped rows, so the
   indent alone would leave a lone variable looking like a stray child. */
.pickable.is-nested { padding-left: 16px; box-shadow: inset 1px 0 0 var(--rule); }
.pickable.is-nested .add { margin-left: 6px; }
.add.is-in:hover { color: var(--moss); border-color: transparent; }

.row-top { display: flex; align-items: baseline; gap: 8px; }
.row-name {
  font-family: var(--mono); font-size: 13px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink);
}
.row-wave {
  margin-left: auto;
  font-family: var(--mono); font-size: 10px;
  color: var(--ink-3);
}
.row-label {
  display: block; margin-top: 2px;
  font-size: 13px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row-file { font-family: var(--mono); font-size: 10px; color: var(--ink-3); }

mark { background: color-mix(in srgb, var(--contour) 22%, transparent); color: inherit; }

.more { padding: 12px 16px; margin: 0; font-size: 12px; color: var(--ink-3); }

/* ── Detail ───────────────────────────────────────────────────────── */

.empty { max-width: 46ch; padding-top: 32px; color: var(--ink-2); }
.empty h2 {
  margin: 0 0 10px;
  font-family: var(--mono); font-size: 15px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink);
}
.empty p { margin: 0 0 12px; font-size: 14px; }
.empty-hint { font-size: 13px; color: var(--ink-3); }

.detail-head { border-bottom: 2px solid var(--ink); padding-bottom: 12px; margin-bottom: 18px; }

.detail-eyebrow {
  font-family: var(--mono); font-size: 11px;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-3);
}

.detail-name {
  margin: 4px 0 6px;
  font-family: var(--mono); font-size: 25px; font-weight: 700;
  letter-spacing: -.045em; line-height: 1.15;
  overflow-wrap: anywhere;
}

.detail-label { margin: 0; font-size: 16px; color: var(--ink-2); max-width: 62ch; }

.facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; margin: 0 0 20px;
  background: var(--rule); border: 1px solid var(--rule);
}
.fact { background: var(--paper); padding: 9px 11px; }
.fact dt {
  font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3);
}
.fact dd { margin: 3px 0 0; font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }

.section-title {
  margin: 24px 0 10px;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-3);
  border-bottom: 1px solid var(--rule); padding-bottom: 5px;
}

.codes { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 13px; }
.codes th {
  text-align: left; padding: 5px 10px 5px 0;
  font-size: 10px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-3); font-weight: 400;
  border-bottom: 1px solid var(--rule);
}
.codes td { padding: 5px 10px 5px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
.codes .val { width: 4.5em; color: var(--ink-2); }
/* Negative codes are missing-value sentinels across this corpus - marking
   them is the single most useful thing this table can do. */
.codes tr.is-missing .val { color: var(--ochre); font-weight: 700; }
.codes tr.is-missing td { color: var(--ink-3); }

pre.code {
  margin: 0; padding: 14px 16px;
  background: var(--paper-2);
  border: 1px solid var(--rule); border-left: 3px solid var(--contour);
  border-radius: 2px;
  overflow-x: auto;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.6;
  tab-size: 2;
}

.note { font-size: 14px; color: var(--ink-2); max-width: 68ch; white-space: pre-wrap; }

.pill {
  display: inline-block; padding: 1px 7px;
  border: 1px solid currentColor; border-radius: 2px;
  font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .08em;
}
.pill-draft { color: var(--ochre); }
.pill-verified { color: var(--moss); }
.pill-ready { color: var(--sea); }

.warn {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; margin: 0 0 18px;
  border: 1px solid var(--contour); border-left-width: 3px;
  background: color-mix(in srgb, var(--contour) 7%, transparent);
  font-size: 13px; color: var(--ink-2);
}
.warn strong { color: var(--ink); }

.linklist { list-style: none; margin: 0; padding: 0; }
.linklist li { border-bottom: 1px solid var(--rule); }
.linklist button {
  width: 100%; text-align: left; padding: 8px 0;
  border: 0; background: none; cursor: pointer; font: inherit;
  display: flex; align-items: baseline; gap: 10px;
}
.linklist button:hover .ll-name { color: var(--contour); }
.ll-name { font-family: var(--mono); font-size: 13px; font-weight: 700; }
.ll-meta { font-family: var(--mono); font-size: 10px; color: var(--ink-3); margin-left: auto; }
.ll-desc { font-size: 12px; color: var(--ink-2); }

.btn {
  display: inline-block; padding: 8px 15px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper-2); color: var(--ink);
  font-family: var(--mono); font-size: 12px;
  text-transform: uppercase; letter-spacing: .07em;
  text-decoration: none; cursor: pointer;
}
.btn:hover { border-color: var(--ink-2); }
.btn-primary { background: var(--contour); border-color: var(--contour); color: #fff; }
.btn-primary:hover { filter: brightness(1.1); }
.btn-primary[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.btn-quiet { background: none; color: var(--ink-3); }

.detail-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 22px; }

/* ── Request form ─────────────────────────────────────────────────────
   Drawn only by the assistant's draft panel now; the atlas's own copy of
   this form became the R bundle view. */

.basket-empty { padding: 16px; margin: 0; font-size: 13px; color: var(--ink-3); }

.draft-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 24px; }
.draft-status { margin: 12px 0 0; font-family: var(--mono); font-size: 12px; color: var(--moss); min-height: 1.2em; }

.drop {
  border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-family: var(--mono); font-size: 15px; line-height: 1;
  padding: 2px 6px;
}
.drop:hover { color: var(--contour); }

/* ── The R bundle ─────────────────────────────────────────────────────

   The view's own list pane is a drop target while you are in it; the TAB is a
   drop target from anywhere else, which is the only way a drag from the
   metadata list can reach a view you are not currently on. Both advertise
   themselves only while something is in flight, so neither sits there as
   decoration.
   ------------------------------------------------------------------- */

body.is-dragging-var .view-tab[data-view="basket"] {
  border-color: var(--contour); color: var(--contour);
}
.view-tab.is-dropping, .pane.is-dropping {
  background: color-mix(in srgb, var(--contour) 10%, transparent);
  box-shadow: inset 0 0 0 2px var(--contour);
}

/* The remove control on a collected row. Mirrors the ＋ that put it there:
   same size, same column, so adding and removing land in the same place. */
.basket-x {
  flex: 0 0 auto; align-self: center;
  margin-left: 10px; width: 22px; height: 22px;
}

/* ── The output columns ───────────────────────────────────────────────
   What the CSV will actually contain. A collision between two deposits that
   both call something `sex` is the normal case, not the exception, and it is
   invisible until the two are listed side by side — which is what this is
   for. */

.cols { list-style: none; margin: 0 0 16px; padding: 0; }

/* Badge, then everything else stacked. It used to be three tracks with the
   name pinned to 18ch, which is narrower than plenty of real ids -
   parental_employment_status_father_0y is thirty-six characters - so a long
   one ran straight over the text beside it. Nothing here has a fixed width
   now, so no name can collide with anything at any length. */
.col-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start; gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}
.col-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.col-row.is-bad { background: color-mix(in srgb, var(--ochre) 9%, transparent); }

.col-kind {
  width: 18px; height: 18px;
  display: grid; place-items: center;
  border-radius: 2px;
  font-family: var(--mono); font-size: 10px; font-weight: 700;
}
.col-kind-derived { background: var(--moss); color: var(--paper-2); }
.col-kind-raw { background: none; color: var(--ink-3); border: 1px solid var(--rule); }
.col-kind-id { background: var(--ink-3); color: var(--paper-2); }

/* The identifier's row: present, permanent, and plainly not yours to change. */
.col-row.is-fixed { opacity: .75; }

/* A harmonised variable's script is shipped verbatim, so its output name is
   not ours to change. Set in the same column as the editable ones, but plainly
   not a field. */
.col-name {
  font-family: var(--mono); font-size: 12.5px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink);
  /* A deposited name can be anything; wrap rather than overflow. */
  overflow-wrap: anywhere;
}
.col-input {
  width: 24ch; max-width: 100%; padding: 3px 6px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper); color: var(--ink);
  font-family: var(--mono); font-size: 12.5px;
}
.col-input[aria-invalid="true"] { border-color: var(--ochre); }

.col-note {
  font-size: 12px; color: var(--ink-3);
  overflow-wrap: anywhere;
}
.col-problem {
  font-family: var(--mono); font-size: 11px; color: var(--ochre);
}

/* ── Footer ───────────────────────────────────────────────────────── */

.foot {
  padding: 10px 20px;
  border-top: 1px solid var(--rule);
  background: var(--paper-2);
  font-size: 11.5px; color: var(--ink-3);
  display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline;
}
.foot-sep { opacity: .5; }

/* ── The assistant ────────────────────────────────────────────────────

   A drawer, not a view. It sits alongside whatever is on screen so a
   variable can be dragged straight out of the results and into the
   conversation, which is the one interaction that makes it worth having.
   The transcript borrows the corpus's own voice: names in mono, sweeps as
   small caps, contour magenta only for what the researcher said and what
   still needs answering.
   ------------------------------------------------------------------- */

.chat-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper); color: var(--ink-2);
  font-family: var(--mono); font-size: 11px;
  text-transform: uppercase; letter-spacing: .07em;
  cursor: pointer;
}
.chat-toggle:hover { border-color: var(--ink-2); color: var(--ink); }
.chat-toggle[aria-expanded="true"] {
  background: var(--contour); border-color: var(--contour); color: #fff;
}
.chat-toggle-mark { font-size: 13px; line-height: 1; }

body.chat-open { padding-right: var(--chat-w); }

.chat-drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: var(--chat-w);
  z-index: 12;
  display: flex; flex-direction: column;
  background: var(--paper-2);
  border-left: 1px solid var(--rule);
  box-shadow: -8px 0 24px -18px rgba(0, 0, 0, .5);
}

.chat-grip {
  position: absolute; left: -3px; top: 0; bottom: 0; width: 7px;
  cursor: col-resize; z-index: 2;
}
.chat-grip:hover { background: var(--contour); opacity: .35; }

.chat-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--rule);
}
.chat-name {
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
}

/* One dot carries the whole connection story: grey unknown, moss for a
   local model, ochre when the model is hosted elsewhere, contour when
   Ollama isn't answering. */
.chat-status {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-3); flex: none;
}
.chat-status.is-ok { background: var(--moss); }
.chat-status.is-ok.is-remote { background: var(--ochre); }
.chat-status.is-down { background: var(--contour); }

.chat-mode {
  padding: 1px 5px;
  white-space: nowrap;
  border: 1px solid var(--rule); border-radius: 2px;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .05em;
  cursor: help;
}
.chat-mode.is-agentic { color: var(--sea); border-color: var(--sea); }

/* Who answered, and what it reached for. Both were invisible: the agent was
   only implied by the shape of the reply, and a lookup in flight was a
   spinner saying "searching" with no clue what for. */
.msg-agent {
  display: inline-block; margin-bottom: 5px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--sea);
  border: 1px solid var(--sea); border-radius: 2px; padding: 1px 5px;
}
.tool-name {
  font-family: var(--mono); font-size: 10.5px; color: var(--moss);
  background: none; padding: 0; letter-spacing: -.01em;
}
.working .who {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--sea); margin-right: 7px;
}
.working .tool-arg { color: var(--ink-3); }

.chat-tabs { margin-left: auto; display: flex; gap: 2px; }
.chat-tabs button {
  border: 0; background: none; cursor: pointer;
  padding: 4px 8px; border-radius: 2px;
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.chat-tabs button:hover { color: var(--ink); background: var(--paper-3); }
.chat-tabs button.is-current { color: var(--contour); background: var(--paper-3); }

.chat-x {
  border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-size: 14px; line-height: 1; padding: 4px;
}
.chat-x:hover { color: var(--contour); }
.chat-x.is-armed {
  color: var(--contour); border: 1px solid var(--contour); border-radius: 2px;
  font-family: var(--mono); font-size: 10px; padding: 2px 5px;
  text-transform: uppercase; letter-spacing: .05em;
}

.chat-remote {
  margin: 0; padding: 8px 12px;
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--ochre) 12%, transparent);
  font-size: 11.5px; color: var(--ink-2);
}
.chat-remote strong { color: var(--ochre); }

/* The assistant off. The drawer still opens and still closes - it just has
   nothing in it but the reason - so the two ways in (the toggle, and Pin to
   assistant) behave the same and neither can strand the panel open. Pinning
   has nowhere to go, so that button is not offered. */
body.chat-off .chat-drawer > :not(.chat-head):not(#chat-dead),
body.chat-off .chat-drawer .chat-tabs,
body.chat-off #chat-reset,
body.chat-off #pin-chat { display: none; }

/* The checklist. Six steps is small enough to show whole, which is the
   point - you can see how much of the request is still unanswered without
   reading the transcript back. */
.chat-strip {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--rule);
}
.chat-steps { display: flex; flex-wrap: wrap; gap: 3px; flex: 1; min-width: 0; }
.step {
  border: 1px solid var(--rule); border-radius: 2px;
  background: none; cursor: pointer;
  padding: 2px 6px;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .04em;
}
.step:hover { color: var(--ink); border-color: var(--ink-2); }
.step.is-done { color: var(--moss); border-color: var(--moss); }
.step.is-now { color: var(--contour); border-color: var(--contour); font-weight: 700; }
.chat-strip-meta {
  display: flex; flex-direction: column; align-items: flex-end; gap: 3px;
  flex: none;
}
.chat-progress {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
}

/* Quiet until you want it. Leaving is recoverable — the draft is kept — so
   this does not need to shout, but it does need to be findable without
   reading the transcript for the right words to type. */
.chat-stop {
  flex: none;
  border: 1px solid var(--rule); border-radius: 2px;
  background: none; cursor: pointer;
  padding: 2px 7px;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .04em;
}
.chat-stop:hover { color: var(--contour); border-color: var(--contour); }

.chat-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 12px; }
.chat-form { padding: 16px 14px 40px; background: var(--paper-2); }
.chat-form .section-title { margin-top: 26px; }

.chat-intro { color: var(--ink-2); }
.chat-intro h3 {
  margin: 4px 0 8px;
  font-family: var(--mono); font-size: 15px; letter-spacing: -.02em; color: var(--ink);
}
.chat-intro p { margin: 0 0 10px; font-size: 13px; }
.chat-intro-hint { color: var(--ink-3); font-size: 12px !important; }
.chat-seeds { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 14px; }
.seed {
  border: 1px dashed var(--rule); border-radius: 2px;
  background: none; cursor: pointer;
  padding: 4px 8px; font-size: 12px; color: var(--ink-2); text-align: left;
}
.seed:hover { border-style: solid; border-color: var(--contour); color: var(--contour); }

.msg { margin-bottom: 16px; font-size: 13.5px; line-height: 1.5; }
.msg-body p { margin: 0 0 8px; }
.msg-body p:last-child { margin-bottom: 0; }
.msg-body ul { margin: 6px 0; padding-left: 18px; }
.msg-body code { background: var(--paper-3); padding: 0 3px; border-radius: 2px; }
.chat-pre {
  background: var(--paper-3); border: 1px solid var(--rule);
  padding: 8px; overflow-x: auto;
  font-family: var(--mono); font-size: 11.5px; white-space: pre-wrap;
}

.msg-mode {
  display: inline-block; margin-bottom: 3px;
  font-family: var(--mono); font-size: 9.5px; color: var(--sea);
  text-transform: uppercase; letter-spacing: .06em;
}

.msg-user .msg-body {
  border-left: 2px solid var(--contour);
  padding-left: 10px; color: var(--ink);
}
.msg-bot .msg-body { color: var(--ink-2); }
.msg-bot .msg-body strong { color: var(--ink); }

/* The working line: one row at the foot of the transcript, with dots that
   move. Shown only while there is nothing else to watch — once tokens are
   streaming, the text is the progress indicator. */
.working {
  margin: 4px 0 12px;
  font-family: var(--mono); font-size: 11.5px; color: var(--contour);
  text-transform: uppercase; letter-spacing: .07em;
}
.working.is-quiet { color: var(--ink-3); }

.ellipsis span {
  display: inline-block;
  animation: blink 1.2s infinite both;
}
.ellipsis span:nth-child(2) { animation-delay: .2s; }
.ellipsis span:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 60%, 100% { opacity: .2; } 30% { opacity: 1; } }

/* Reasoning on/off, beside Send. Quiet when off; it is not the default and
   should not look like the point of the composer. */
.think-toggle {
  border: 1px solid var(--rule); border-radius: 2px;
  background: none; cursor: pointer;
  padding: 6px 9px;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.think-toggle:hover { color: var(--ink); border-color: var(--ink-2); }
.think-toggle.is-on { color: var(--sea); border-color: var(--sea); }

.msg-think pre {
  margin: 6px 0 0; padding: 8px;
  background: var(--paper-3); border-left: 2px solid var(--rule);
  font-family: var(--mono); font-size: 11px; white-space: pre-wrap;
  color: var(--ink-3); max-height: 220px; overflow-y: auto;
}

/* What the model chose to look up, and what came back. Set apart from both
   voices in the conversation because it is neither - it is the working. */
.msg-tool .msg-head code {
  text-transform: none; letter-spacing: 0;
  color: var(--sea); background: none; font-weight: 700;
}
.tool-mark { color: var(--sea); font-size: 12px; }
.msg-tool.is-running { opacity: .7; }
.msg-tool .codes { margin-top: 4px; font-size: 11.5px; }
.msg-tool .codes td { padding: 3px 8px 3px 0; }
.msg-tool .hits { max-height: 320px; overflow-y: auto; }
.msg-head {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px;
}
.msg-head code { text-transform: none; letter-spacing: 0; color: var(--ink-2); }
.msg-note { color: var(--ink-3); font-size: 11px; }

/* Coverage: one row per wave, every wave, including the ones with nothing.
   Absence is drawn here for the same reason it is drawn on the spine — "not
   measured then" is the answer as often as a variable name is. The verdict
   column carries the tool's three states, so measured and merely-possible
   cannot be read as the same finding. */
.coverage { list-style: none; margin: 6px 0 0; padding: 0; }
.msg-tool .coverage { max-height: 320px; overflow-y: auto; }
.cov {
  display: grid;
  grid-template-columns: 46px 62px 1fr;
  gap: 0 8px;
  align-items: baseline;
  padding: 4px 0;
  border-bottom: 1px solid var(--rule);
}
.cov-wave {
  font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--ink);
}
.cov-verdict {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3);
}
.cov.is-measured .cov-verdict { color: var(--moss); }
.cov.is-possible .cov-verdict { color: var(--ochre); }
.cov.is-nothing { opacity: .55; }
.cov-names {
  font-family: var(--mono); font-size: 11.5px; color: var(--ink);
  overflow-wrap: anywhere;
}
.cov-label {
  grid-column: 3;
  font-size: 11.5px; color: var(--ink-2);
}
.cov-label:empty { display: none; }

.hits { list-style: none; margin: 6px 0 0; padding: 0; }
.hit {
  position: relative;
  padding: 5px 40px 5px 0;
  border-bottom: 1px solid var(--rule);
  cursor: grab;
}
.hit:hover { background: var(--paper-3); }
.hit-names {
  display: block;
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--ink);
  overflow-wrap: anywhere;
}

/* A variable name the assistant surfaced, and a way into the atlas. Dotted
   underline rather than a link colour: these sit inside a dense list of codes
   and would shout. */
.varlink {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; color: var(--ink);
  border-bottom: 1px dotted var(--ink-3);
}
.varlink:hover { color: var(--contour); border-bottom-color: var(--contour); }
.varlink.is-missing {
  color: var(--ochre); border-bottom-style: none; cursor: default;
  text-decoration: line-through;
}
.hit-more { color: var(--ink-3); font-weight: 400; }
.hit-label { display: block; font-size: 12px; color: var(--ink-2); }
.hit-meta {
  display: block;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3); letter-spacing: .04em;
}
.hit-pin {
  position: absolute; right: 0; top: 6px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper-2); cursor: pointer;
  padding: 1px 5px;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.hit-pin:hover:not(:disabled) { border-color: var(--contour); color: var(--contour); }
.hit-pin:disabled { color: var(--moss); border-color: var(--moss); cursor: default; }

.chat-foot { border-top: 1px solid var(--rule); padding: 10px 12px; }

/* Answers to whatever was just asked, stacked above the composer. A list
   rather than a row of chips: these are alternatives to read and choose
   between, and a wrapping row makes a set of choices look like a set of
   tags. Numbered, arrow-navigable, and every one of them editable once
   chosen — picking fills the box rather than sending. */
.replies { margin-bottom: 8px; }

.choices-head {
  margin: 0 0 5px;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}

.choice-list { list-style: none; margin: 0; padding: 0; }
.choice-list li { margin-bottom: 3px; }

.choice {
  display: flex; align-items: baseline; gap: 8px; width: 100%;
  padding: 5px 9px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper);
  cursor: pointer; text-align: left;
  font-family: var(--sans); font-size: 13px; line-height: 1.35;
  color: var(--ink-2);
}
.choice:hover, .choice:focus-visible {
  border-color: var(--contour); color: var(--ink);
  background: var(--paper-3);
  outline: none;
}
.choice:focus-visible { box-shadow: inset 3px 0 0 var(--contour); }

.choice-key {
  flex: none; min-width: 1.1em;
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
}
.choice:hover .choice-key, .choice:focus-visible .choice-key { color: var(--contour); }
.choice-text { flex: 1; }

/* The one action left when the checklist is done. Reads as a destination
   rather than as another thing to say. */
.choice.is-go {
  width: 100%; border-color: var(--contour); color: var(--contour);
  background: var(--paper-2); font-weight: 600;
}
.choice.is-go:hover, .choice.is-go:focus-visible {
  background: var(--contour); color: var(--paper-2);
}
.choice.is-go .choice-key { color: var(--contour); }
.choice.is-go:hover .choice-key, .choice.is-go:focus-visible .choice-key {
  color: var(--paper-2);
}

.choices-hint {
  margin: 6px 0 0;
  font-size: 10.5px; color: var(--ink-3);
}
.choices-hint kbd {
  border: 1px solid var(--rule); border-radius: 2px;
  padding: 0 3px; margin-right: 1px;
  font-size: 9.5px; color: var(--ink-3);
}

.pinned { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; }
.pinchip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 4px 2px 7px;
  border: 1px solid var(--contour); border-radius: 2px;
  background: color-mix(in srgb, var(--contour) 8%, transparent);
  font-family: var(--mono); font-size: 10.5px;
}
.pinchip.is-derived {
  border-color: var(--moss);
  background: color-mix(in srgb, var(--moss) 8%, transparent);
}
.pinchip-name { color: var(--ink); font-weight: 700; }
.pinchip-wave { color: var(--ink-3); }
.pinchip button {
  border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-size: 11px; line-height: 1; padding: 0 2px;
}
.pinchip button:hover { color: var(--contour); }

.composer textarea {
  width: 100%; resize: none;
  padding: 8px 10px;
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper); color: var(--ink);
  font-family: var(--sans); font-size: 13.5px; line-height: 1.45;
}
.composer textarea:focus { outline: 2px solid var(--contour); outline-offset: -1px; }
.composer-actions { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.composer-spacer { flex: 1; }
/* Says why a send was refused. Empty most of the time, and takes no room
   when it is, so the buttons do not shift as it comes and goes. */
.composer-note {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  max-width: 24ch; line-height: 1.3;
}
.composer-note:empty { display: none; }

/* The dropzone is drawn only while a variable is in flight over the
   drawer, so it never sits there as decoration. */
.chat-dropzone {
  position: absolute; inset: 6px;
  display: none; align-items: center; justify-content: center;
  border: 2px dashed var(--contour); border-radius: 3px;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  z-index: 5; pointer-events: none;
}
.chat-drawer.is-dropping .chat-dropzone { display: flex; }
.chat-dropzone span {
  font-family: var(--mono); font-size: 12px; color: var(--contour);
  text-transform: uppercase; letter-spacing: .08em;
}
/* While something is being dragged anywhere on the page, the drawer edge
   advertises itself as a target. */
body.is-dragging-var .chat-drawer { border-left-color: var(--contour); }

.warn-stack summary {
  cursor: pointer; list-style: none;
  font-family: var(--mono); font-size: 10px; color: var(--ochre);
  text-transform: uppercase; letter-spacing: .06em; margin-top: 6px;
}
.warn-stack summary::before { content: "▸ "; }
.warn-stack[open] summary::before { content: "▾ "; }
.warn-stack pre {
  margin: 6px 0 0; padding: 8px;
  background: var(--paper-3); border-left: 2px solid var(--ochre);
  font-family: var(--mono); font-size: 10.5px; white-space: pre-wrap;
  color: var(--ink-2); max-height: 200px; overflow-y: auto;
}

.srcvars { list-style: none; margin: 6px 0 18px; padding: 0; }
.srcvars li {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 0; border-bottom: 1px solid var(--rule);
  font-size: 11.5px;
}
.srcvars code { font-size: 11.5px; font-weight: 700; }
.srcvars li span { flex: 1; color: var(--ink-3); font-family: var(--sans); }
.srcvars li.is-known code { color: var(--moss); }
.srcvars li.is-unknown code { color: var(--ochre); }
.srcvars li.is-unknown span { color: var(--ochre); }
.srcvars li button {
  border: 0; background: none; cursor: pointer; color: var(--ink-3);
  font-size: 12px; line-height: 1; padding: 0 2px;
}
.srcvars li button:hover { color: var(--contour); }
.srcvars-empty { color: var(--ink-3); border-bottom: 0 !important; }


.chat-form input[type="text"], .chat-form input:not([type]),
.chat-form select, .chat-form textarea { width: 100%; }
.chat-form .field.check {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 8px; align-items: center;
}
.chat-form .field.check input { width: auto; }
.chat-form .field.check .field-help { grid-column: 2; margin-top: 0; }
.chat-form .field-label em {
  font-style: normal; color: var(--ochre); text-transform: lowercase; letter-spacing: 0;
}

/* ── Responsive ───────────────────────────────────────────────────── */

@media (max-width: 900px) {
  /* Below this width there is nothing left to drag a variable out of, so
     the drawer stops being a side panel and covers the page instead. */
  body.chat-open { padding-right: 0; }
  .chat-drawer { width: 100%; }
  .chat-grip { display: none; }

  .view.is-current { grid-template-columns: 1fr; }
  .grip { display: none; }
  .pane-list { border-right: 0; border-bottom: 1px solid var(--rule); max-height: 42vh; }
  .pane { overflow-y: visible; }
  main { overflow-y: auto; }
  .spine-track { grid-auto-flow: row; grid-template-columns: repeat(7, 1fr); }
  .detail-name { font-size: 20px; }
  .masthead { gap: 10px; }
  .mark { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
