/* The room: pale mint, with grape the one hue the interface speaks in and one ink for every word on it.
   Nothing is dimmed: rank is size and weight, never a fainter ink.
   The fellow keeps his own oranges, being a drawing rather than a decision, and is the only thing wearing them.
   Joy lives at the hello and the payoff; the working surfaces stay calm. */

@font-face { font-family: 'Baloo 2';            src: url(fonts/baloo2.woff2) format('woff2');                       font-weight: 400 800; font-display: swap; }
@font-face { font-family: 'Nunito';             src: url(fonts/nunito.woff2) format('woff2');                       font-weight: 200 1000; font-display: swap; }
@font-face { font-family: 'IM Fell English';    src: url(fonts/imfell-400-italic.woff2) format('woff2');            font-style: italic;   font-display: swap; }
@font-face { font-family: 'Sarasa Mono J';      src: url(fonts/sarasamonoj-400.woff2) format('woff2');              font-weight: 400;     font-display: swap; }
@font-face { font-family: 'Sarasa Mono J';      src: url(fonts/sarasamonoj-700.woff2) format('woff2');              font-weight: 700;     font-display: swap; }

/* Sarasa's stand-ins while it downloads, size-adjusted to its half-em advance: whichever local mono
   paints first occupies exactly the columns Sarasa will, so its arrival changes letterforms, never layout.
   Each local is spelled in every name it answers to, because Firefox matches local() by full or PostScript name, never family. */
@font-face { font-family: 'Sarasa Stand-in'; src: local('Menlo'), local('Menlo-Regular'), local('Menlo Regular'); size-adjust: 83.02%; }
@font-face { font-family: 'Sarasa Stand-in'; src: local('Consolas'), local('Consolas Regular'); size-adjust: 90.91%; }
@font-face { font-family: 'Sarasa Stand-in'; src: local('DejaVu Sans Mono'), local('DejaVuSansMono'); size-adjust: 83.02%; }
@font-face { font-family: 'Sarasa Stand-in'; src: local('Roboto Mono'), local('RobotoMono-Regular'), local('Roboto Mono Regular'); size-adjust: 83.32%; }

/* The speaking fonts' stand-ins, one row per metric family. Each wears the target's own ascent, descent, and
   line gap, plus a size-adjust matching frequency-weighted average advances measured from the faces themselves:
   the swap changes letterforms, never line count nor baseline. Liberation Sans carries Arial's metrics by design,
   so the one row serves every spelling. */
@font-face { font-family: 'Nunito Stand-in'; src: local('Arial'), local('ArialMT'), local('Liberation Sans'), local('LiberationSans');
             font-weight: 200 1000; size-adjust: 97.86%; ascent-override: 101.1%; descent-override: 35.3%; line-gap-override: 0%; }
@font-face { font-family: 'Baloo Stand-in'; src: local('Arial'), local('ArialMT'), local('Liberation Sans'), local('LiberationSans');
             font-weight: 400 800; size-adjust: 96.8%; ascent-override: 107.8%; descent-override: 52.4%; line-gap-override: 0%; }
@font-face { font-family: 'Fell Stand-in'; src: local('Georgia Italic'), local('Georgia-Italic'), local('Georgia');
             font-style: italic; size-adjust: 77.67%; ascent-override: 90.53%; descent-override: 36.33%; line-gap-override: 0%; }
@font-face { font-family: 'Fell Stand-in'; src: local('Times New Roman Italic'), local('TimesNewRomanPS-ItalicMT'), local('Times New Roman');
             font-style: italic; size-adjust: 86.57%; ascent-override: 90.53%; descent-override: 36.33%; line-gap-override: 0%; }

:root {
  --room: #E7F3EE;
  --panel: #FCFDFC;
  --hairline: #8BC3AC;
  --ink: #16241D;
  /* Grape is the only fill words ever sit on, and they sit on it at --weight-loud:
     thin strokes on a saturated ground bloom into it, which is the glare, not the hue. */
  --ink-on-grape: #FFFFFF;

  --grape: #8E44AD;
  --grape-tint: #F5EDF9;
  /* a word in the grape hue on a light ground takes this one, dark enough for tint, room, or panel */
  --grape-deep: #6C2D83;

  /* a blank waiting for a file wears the room's hue; a hint you can rest on wears the accent */
  --dash: #3C7960;
  --dash-hint: #8E44AD;

  --ok-ink: #3E5A34;     --ok-room: #F2F7EE;      --ok-line: #CFE3C4;
  --caution-ink: #8A5A2F; --caution-room: #FFF3E6; --caution-line: #E7D2A8;

  /* the terminal strip keeps its own dark ground; the page accent never sits on it,
     and every word on it speaks bright and saturated — no greys, no browns */
  --terminal-room: #221E1A;      --terminal-ink: #EFE7DD;
  --terminal-verb: #D9ABFA;      --terminal-flag: #7EE787;
  --terminal-value: #FFC66D;

  /* The field labels' own column, and where the glosses under them start.
     Set when the labels were monospace and 19 columns wide; Nunito at this size is narrower,
     so it still clears the longest label ("omit verification", plus its story asterisk) with room left over. */
  --label-column: calc(var(--type-micro) * 9.5);


  /* The weights of speech. Anything small, and anything on a saturated fill, takes firm or louder. */
  --weight-plain: 400;     /* prose at reading size */
  --weight-firm: 600;      /* controls, labels, and every whisper: enough stroke to survive being small */
  --weight-loud: 700;      /* words on a fill, and the marks that carry a verdict */
  --weight-display: 800;   /* the sticker */

  /* The banner is a picture of a terminal, measured in its own glyphs rather than the page's steps;
     every length inside it is an em of this. */
  --motd-size: 15px;

  /* The sizes of speech, each a 1.25 step from the next. Everything the page says wears one of these. */
  --type-micro: 16px;    /* whispers: glosses, captions, readouts */
  --type-text: 20px;       /* the speaking voice: prose, inputs, the sentence, and anything you press */
  --type-emphasis: 25px; /* what leads: the run button, the sticker word */
  --type-display: 31px;    /* what celebrates: the headline */

  /* The three radii: a pick is a pill, a holder is a card, and a thing inside a card sits nearly square. */
  --radius-pick: 999px;
  --radius-hold: 12px;
  --radius-inside: 4px;

  /* The room breathes in fractions of its speaking voice: every gap and pad is a step of --type-text,
     so the rhythm re-derives itself whenever the type does. */
  --space-quarter: calc(var(--type-text) / 4);            /* 4.5px */
  --space-half: calc(var(--type-text) / 2);               /* 9px */
  --space-three-quarters: calc(var(--type-text) * 0.75);  /* 13.5px */
  --space-whole: var(--type-text);                        /* 18px */
  --space-one-and-a-half: calc(var(--type-text) * 1.5);   /* 27px */
  --space-double: calc(var(--type-text) * 2);             /* 36px */

  --display: 'Baloo 2', 'Baloo Stand-in', system-ui, sans-serif;
  --body: 'Nunito', 'Nunito Stand-in', system-ui, sans-serif;
  --mono: 'Sarasa Mono J', 'Sarasa Stand-in', ui-monospace, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--room);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--type-text);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.page { max-width: 890px; margin: 0 auto; padding: var(--space-double) var(--space-whole) var(--space-double); }

/* Parked above the page until focus asks for it. */
.skip-link {
  position: absolute; left: 20px; top: -100px; z-index: 10;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--grape); border-radius: var(--radius-pick);
  padding: var(--space-half) var(--space-three-quarters); font-family: var(--body); font-size: var(--type-micro);
}
.skip-link:focus { top: 12px; }

button { font: inherit; cursor: pointer; }
:focus-visible { outline: 2px solid var(--grape); outline-offset: 2px; }

/* Only the colours a surface answers a pointer with, and under the tenth of a second that still reads as at once.
   Nothing that carries a fact moves: what a control says, and when it says it, is unchanged. */
.chip, .tile, .more-chip, .toggle-chip, .verb, .slot, .quiet-button, .field-input, .field-textarea {
  transition: background-color 90ms ease-out, border-color 90ms ease-out, color 90ms ease-out;
}

/* ---------------------------------------------------------- masthead ---- */

.masthead { display: flex; align-items: center; justify-content: space-between; gap: var(--space-whole); margin-bottom: var(--space-one-and-a-half); flex-wrap: wrap; }
@media (max-width: 640px) {
  .masthead { flex-wrap: nowrap; gap: var(--space-three-quarters); }
  .sticker { flex: none; }
  .motd { flex: 0 1 auto; min-width: 0; }
  .motd-banner { display: flex; width: 100%; }
  .motd-lines { min-width: 0; }
}

.sticker {
  display: inline-flex; align-items: center; gap: var(--space-half);
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-pick);
  padding: var(--space-half) var(--space-three-quarters) var(--space-half) var(--space-half);
  transform: rotate(-4deg);
  box-shadow: 0 4px 0 rgba(90, 51, 39, 0.12);
}
.sticker img { display: block; width: 1.05em; height: 1.05em; font-size: var(--type-emphasis); }
.sticker-word { font-family: var(--display); font-weight: var(--weight-display); font-size: var(--type-emphasis); line-height: 1; color: var(--grape-deep); margin: 0; }

.motd { text-decoration: none; display: inline-block; }
/* The banner's type, spacing, and curves are its own, outside the page's token systems: every number in it is glyph arithmetic. */
.motd-banner {
  font-family: var(--mono);
  background: var(--terminal-room);
  color: var(--terminal-ink);
  border-radius: 0.75em;
  padding: 0.75em 1.15em;
  display: inline-flex; align-items: center; text-align: left;
}
/* 17 columns at Sarasa's half-em advance, reserved before the font arrives:
   a fallback's wider glyphs paint inside the same box instead of resizing it when the real font lands. */
.motd-wordmark {
  margin: 0;
  font-family: inherit;
  font-size: var(--motd-size); line-height: 1.12;
  width: 8.5em; overflow: hidden;
  color: var(--terminal-value);
}
.motd-lines   { font-size: var(--motd-size); line-height: 1.5; }
.motd-label   { color: var(--terminal-ink); }
.motd-prompt  { color: var(--terminal-flag); }
.motd-command { color: var(--terminal-verb); }
.motd-flag    { color: var(--terminal-ink); }
.motd-cursor {
  display: inline-block;
  width: 0.5em; height: 1em;
  background: var(--terminal-flag);
  border-radius: 1px;
  transform: translateY(1px);
  opacity: 0;
}
@keyframes motdCursorBlink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.motd:hover .motd-cursor,
.motd:focus-visible .motd-cursor { opacity: 1; animation: motdCursorBlink 1.02s steps(1, end) infinite; }
.motd:focus-visible { outline: 2px solid var(--terminal-flag); outline-offset: 2px; border-radius: 9px; }
@media (max-width: 640px) { .motd-wordmark { display: none; } }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------- verbs ---- */

.verbs {
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--space-one-and-a-half);
}
.verb {
  font-family: var(--body); font-size: var(--type-text); font-weight: var(--weight-firm);
  background: none; border: none; color: var(--ink);
  padding: var(--space-half) var(--space-three-quarters); margin-bottom: -1px;
  border-bottom: 2px solid transparent;
}
.verb:hover { color: var(--grape-deep); }
.verb.on { color: var(--grape-deep); font-weight: var(--weight-loud); border-bottom-color: var(--grape); }
.verb.lesser { padding: var(--space-half) var(--space-half); }
.verb-gap { width: 1px; height: 15px; background: var(--hairline); margin: 0 var(--space-half); }

/* ---------------------------------------------------------- sentence ---- */

.sentence { font-family: var(--body); font-size: var(--type-text); line-height: 2.5; color: var(--ink); margin: var(--space-quarter) 0 var(--space-half); }
.sentence.second { margin-top: calc(-1 * var(--space-half)); }
.swap-line { margin: calc(-1 * var(--space-quarter)) 0 2px; }
.slot { background: none; border: none; padding: 0 5px; font: inherit; line-height: 1.45; }
.slot.empty { color: var(--ink); border-bottom: 2px dashed var(--dash); }
.slot.empty:hover { color: var(--grape-deep); border-bottom-color: var(--grape); }
.slot.filled { color: var(--ink); border-bottom: 2px solid var(--grape); }
/* a blank slap knows you still owe it, in the colour the page keeps for things not yet answered */
.slot.empty.owed { color: var(--grape-deep); border-bottom-color: var(--dash); }
/* a storied slot keeps the seat's dashes: the asterisk already says the fellow will speak */
.slot.has-story:hover, .slot.has-story:focus-visible { text-decoration: none; }
.slot.inert { cursor: default; }
.slot-stack { display: inline-block; position: relative; }
/* Centred under what it names, on one line however wide: boxed to the blank's own width it would wrap
   into whatever sits below. */
.role-whisper {
  position: absolute; left: 50%; transform: translateX(-50%); top: 100%;
  margin-top: calc(-1 * var(--space-half)); white-space: nowrap;
  font-family: var(--body); font-size: var(--type-micro); line-height: 1;
  color: var(--ink); pointer-events: none;
}
.format-chip {
  font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-firm);
  color: var(--grape-deep); background: var(--grape-tint);
  border: 1px solid var(--hairline); border-radius: var(--radius-pick);
  padding: 2px var(--space-half); margin-left: var(--space-quarter); vertical-align: 2px;
}

/* --------------------------------------------------- cards and groups ---- */

.facts-card, .group {
  background: var(--room);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-whole);
  margin: var(--space-three-quarters) 0;
}
.facts-card .file-line { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-half); flex-wrap: wrap; }
.facts-card .file-name { font-family: var(--body); font-size: var(--type-text); }
.facts-card .file-size { font-family: var(--mono); font-size: var(--type-micro); color: var(--ink); }
.facts-card .hashes { font-family: var(--mono); font-size: var(--type-micro); color: var(--ink); margin-top: var(--space-half); line-height: 1.9; overflow-wrap: break-word; }
.facts-card .hashes b { color: var(--ink); font-weight: var(--weight-plain); }

.verdict { display: flex; gap: var(--space-half); align-items: flex-start; margin-top: var(--space-three-quarters); padding-top: var(--space-half); border-top: 1px solid var(--hairline); font-size: var(--type-text); }
.verdict .mark { font-family: var(--body); font-weight: var(--weight-loud); font-size: var(--type-emphasis); line-height: 1.1; flex: none; }
.verdict.good     { color: var(--ok-ink); }
.verdict.puzzled  { color: var(--caution-ink); }
.verdict.shrug    { color: var(--ink); }
.verdict.waiting  { color: var(--ink); }
.verdict code { font-family: var(--mono); font-size: var(--type-micro); background: var(--room); border: 1px solid var(--hairline); border-radius: var(--radius-inside); padding: 1px 5px; }
.mismatch-line { display: block; margin-top: var(--space-quarter); }
.rescue-line { margin: var(--space-half) 0 0; }
.rescue-way { margin: var(--space-quarter) 0 0; }

.group h3 {
  font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-loud);
  letter-spacing: 0.08em; color: var(--ink);
  margin: 0 0 var(--space-half);
}
.group .aside { color: var(--ink); font-size: var(--type-micro); margin: var(--space-half) 0 0; }
.group > .aside:first-child { margin-top: 0; }
.group .aside.explainer { margin: 0 0 var(--space-half); }

.advisory {
  display: flex; gap: var(--space-half); align-items: flex-start;
  font-size: var(--type-micro); border-radius: var(--radius-hold); padding: var(--space-half) var(--space-three-quarters); margin: var(--space-half) 0 0;
  background: var(--caution-room); border: 1px solid var(--caution-line); color: var(--caution-ink);
}
.advisory.note { background: var(--room); border-color: var(--hairline); color: var(--ink); }
.advisory-face { flex: none; margin-top: 1px; width: 2.6em; height: 2.6em; }

.choice-row { display: flex; gap: var(--space-half); flex-wrap: wrap; margin: var(--space-quarter) 0; }
/* a row stands ready to be named even while it holds nothing, so it takes no space until it does */
.choice-row:empty { display: none; }
.chip {
  font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-firm);
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: var(--radius-pick);
  padding: var(--space-half) var(--space-three-quarters);
}
.chip:hover { border-color: var(--grape); }
.chip.on { background: var(--grape-tint); border-color: var(--grape); color: var(--ink); font-weight: var(--weight-loud); }
.choice-label { font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-firm); color: var(--ink); margin: var(--space-three-quarters) 0 var(--space-quarter); }

.toggle { display: flex; align-items: center; gap: var(--space-half); margin: var(--space-half) 0 2px; }
.toggle + .toggle { border-top: 1px solid var(--hairline); padding-top: var(--space-half); }
.toggle-input { position: absolute; opacity: 0; pointer-events: none; }
.toggle-chip { cursor: pointer; }
/* the tick's seat is never empty: a hollow ring holds it while off, so the chip reads fillable and never shifts */
.toggle-chip::before { content: '○'; display: inline-block; width: 1.2em; color: var(--ink); }
.toggle-input:checked + .toggle-chip { background: var(--grape-tint); border-color: var(--grape); color: var(--ink); font-weight: var(--weight-loud); }
.toggle-input:checked + .toggle-chip::before { content: '✓'; color: inherit; }
.toggle-input:focus-visible + .toggle-chip { outline: 2px solid var(--grape); outline-offset: 2px; }

/* One-of-N choices ride hidden radios the way the toggles ride hidden checkboxes; the labels wear the chips. */
.choice-input { position: absolute; opacity: 0; pointer-events: none; }
.choice-input:focus-visible + .chip, .choice-input:focus-visible + .tile { outline: 2px solid var(--grape); outline-offset: 2px; }
label.chip, label.tile { cursor: pointer; }
.choice-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
legend.choice-label { padding: 0; }
.toggle .why { color: var(--ink); font-family: var(--body); font-size: var(--type-micro); }

/* ------------------------------------------------------------ create ---- */

.tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-half); margin: var(--space-quarter) 0 var(--space-half); }
.tile {
  display: flex; flex-direction: column; gap: var(--space-quarter); text-align: left;
  background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-three-quarters); font: inherit; cursor: pointer;
}
.tile:hover { border-color: var(--grape); }
.tile.on { border-color: var(--grape); background: var(--grape-tint); }
.tile-name { font-family: var(--display); font-weight: var(--weight-loud); font-size: var(--type-text); color: var(--ink); }
.tile.on .tile-name { color: var(--grape-deep); }
.tile-copy { font-size: var(--type-micro); color: var(--ink); line-height: 1.45; }

/* the dashed border borrows the empty slot's promise of more; the chip shape previews what unfolds */
.more-chip {
  font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-firm);
  color: var(--ink); background: var(--panel);
  border: 1px dashed var(--dash-hint); border-radius: var(--radius-pick);
  padding: var(--space-half) var(--space-three-quarters);
}
.more-chip:hover { border-color: var(--grape); background: var(--grape-tint); }
.more-chip.open { border-style: solid; }

.field { display: flex; align-items: baseline; gap: var(--space-half); margin: var(--space-half) 0; flex-wrap: wrap; }
.field-label { font-family: var(--body); font-size: var(--type-micro); font-weight: var(--weight-firm); color: var(--ink); flex: 0 0 var(--label-column); }
/* the gloss takes the whole line under the control it speaks for, standing where the control stands */
.field-gloss { flex: 0 0 100%; margin: 2px 0 0 calc(var(--label-column) + var(--space-half));
               color: var(--ink); font-size: var(--type-micro); }
.field .why, .choice-label .why { color: var(--ink); font-family: var(--body); font-size: var(--type-micro); flex: none; }
.byte-count { font-family: var(--mono); font-size: var(--type-micro); color: var(--ink); flex: none; }
.byte-count.over-ceiling { color: var(--caution-ink); }
/* inline-flex, so the chip inside is sized by its padding exactly like its free-standing peers;
   as inline content its padding would paint without counting, leaving a short box the row would center. */
.chip-stack { display: inline-flex; position: relative; }
.chip-stack .role-whisper { margin-top: 2px; }
/* the hanging whisper needs headroom when the row wraps, and below the row either way */
.choice-row:has(.chip-stack) { row-gap: var(--space-whole); margin-bottom: var(--space-whole); }
.choice-gloss { color: var(--ink); font-size: var(--type-micro); margin: var(--space-quarter) 0 2px; }
/* The sentence's format blank. Its neighbours are seats that open when pressed; this one is answered in the
   group below, so it wears that group's dress — the quiet-formats chip, in the sentence's own face, since a
   sentence never mixes typefaces — and fills solid once a format is chosen. */
.format-seat {
  font: inherit; line-height: 1.45; display: inline-block;
  color: var(--grape-deep); background: none;
  border: 1px dashed var(--dash); border-radius: var(--radius-pick);
  padding: 1px 10px;
}
.format-seat.chosen { border-style: solid; border-color: var(--hairline); background: var(--grape-tint); }
/* the chip's own answer to a pointer, in place of the underline a story would otherwise draw */
.format-seat:hover, .format-seat:focus-visible { text-decoration: none; border-color: var(--grape); background: var(--grape-tint); }
/* where a spoken story is pointing */
.pointed-at { outline: 2px solid var(--grape); outline-offset: 3px; }

/* a story is marked the way a footnote is: the asterisk finds the eye across a form, and resting on it makes good.
   it is raised on a zero line-height, so marking a label never moves the line the label sits on. */
.has-story { cursor: help; background: none; border: 0; padding: 0; color: inherit; text-align: inherit; }
.has-story::after {
  content: '*'; color: var(--grape-deep); font-weight: var(--weight-loud);
  vertical-align: super; font-size: 0.8em; line-height: 0; margin-left: 1px;
}
.has-story:hover, .has-story:focus-visible {
  color: var(--grape-deep);
  text-decoration: underline dotted var(--grape); text-underline-offset: 3px;
}
.field-input, .field-textarea {
  font-family: var(--body); font-size: var(--type-text); color: var(--ink);
  background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-inside); padding: var(--space-quarter) var(--space-half);
}
.field-input { flex: 1; min-width: 0; }
/* a count is a short word: it takes the width of one, and the browser's steppers step by a byte at a time — useless here */
.field-input[type="number"] { flex: 0 0 auto; width: 11ch; appearance: textfield; }
.field-input[type="number"]::-webkit-outer-spin-button,
.field-input[type="number"]::-webkit-inner-spin-button { appearance: none; margin: 0; }
.field-input:invalid { border-color: var(--caution-ink); }
.field-textarea { width: 100%; min-height: 64px; resize: vertical; margin-top: var(--space-quarter); }
.counted-lane .byte-count { display: block; text-align: right; margin-top: 3px; }

/* A way out is the friendliest thing in a blocked answer, so it is dressed as speech and only the mark is faint. */
.way-out { margin: 2px 0 var(--space-quarter); padding-left: 1em; text-indent: -1em; color: var(--ink); }
.way-out::before { content: '· '; color: var(--ink); }

/* ------------------------------------------------------------ answer ---- */

.answer { display: flex; gap: var(--space-whole); align-items: center; margin: var(--space-whole) 0 var(--space-quarter); }
/* The answer rides the window's bottom edge while its place in the flow is below it, so a story or a verdict
   never speaks off-screen; reaching its place, it settles back into the flow.
   The ground dissolves upward instead of ending at an edge, so what scrolls behind fades rather than hitting
   a wall — and the fellow's head stands in the dissolve, taller than the bar that seats him. */
.answer {
  position: sticky; bottom: 0; z-index: 4;
  padding: 0 0 var(--space-quarter);
  background: linear-gradient(to bottom, transparent, var(--room) var(--space-whole));
}
.fellow-seat { flex: none; width: 92px; height: 92px; }
.fellow-seat svg { width: 100%; height: 100%; overflow: visible; cursor: pointer; transform-origin: 50% 50%; }
.voice {
  flex: 1; min-width: 0;
  position: relative;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-whole);
  font-size: var(--type-text);
}
/* A spoken story's card, floated over the voice box rather than joining its flow. It grows upward over the
   stage, so a story never runs off the window's bottom while the answer rides there;
   stories.mjs says why the page must not move while a story speaks. */
.story-card {
  position: absolute; bottom: -1px; left: -1px; right: -1px; z-index: 5;
  min-height: calc(100% + 2px);
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-whole);
  box-shadow: 0 6px 16px rgba(90, 51, 39, 0.18);
}
.voice .plain-line { margin: 0; color: var(--ink); }
.voice .story-hint { margin-top: var(--space-quarter); font-size: var(--type-micro); color: var(--ink); }
.voice .story-hint .story-mark { color: var(--grape-deep); font-weight: var(--weight-loud); }
/* The pill is showing the reader what a pill looks like, so it must not break across two lines. */
.voice .story-hint .pill-mark {
  color: var(--grape-deep); border: 1px dashed var(--dash-hint); border-radius: var(--radius-pick); padding: 0 7px;
  white-space: nowrap;
}
.voice .breathing { animation: breathing 1.9s ease-in-out infinite; }
@keyframes breathing { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.voice .elapsed { font-family: var(--mono); font-size: var(--type-micro); color: var(--ink); font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .voice .breathing { animation: none; } }
.voice .headline { font-family: var(--display); font-weight: var(--weight-loud); font-size: var(--type-display); color: var(--grape-deep); margin: 0 0 var(--space-half); line-height: 1.2; }
.voice .headline .sparkle { color: var(--grape); font-size: var(--type-emphasis); }
.voice .said { margin: 0 0 var(--space-quarter); }
.voice .said code { font-family: var(--mono); font-size: var(--type-micro); background: var(--room); border: 1px solid var(--hairline); border-radius: var(--radius-inside); padding: 1px 5px; }
/* A refusal is slap saying what a file is, not an alarm — the monospace is the whole of its register.
   Caution's ink is kept for the one card where something is actually broken: a boot that did not happen. */
.voice .refusal { font-family: var(--mono); font-size: var(--type-micro); white-space: pre-wrap; margin: 0 0 var(--space-quarter); color: var(--ink); }
.voice .boot-detail { color: var(--caution-ink); }
.voice .boot-stamp { margin: var(--space-half) 0 0; font-size: var(--type-micro); color: var(--ink); }
.voice .download {
  display: flex; align-items: center; gap: var(--space-half); flex-wrap: wrap;
  margin-top: var(--space-three-quarters); padding-top: var(--space-three-quarters); border-top: 1px solid var(--hairline);
  font-family: var(--body); font-size: var(--type-micro);
}
.voice .download .arrow { color: var(--ok-ink); font-weight: var(--weight-loud); }
.voice .download a { color: var(--ink); }
.voice .download .aside { color: var(--ink); }
.voice .afterward { display: flex; gap: var(--space-half); flex-wrap: wrap; margin-top: var(--space-three-quarters); }

/* ---------------------------------------------------- read verb panels ---- */

.results {
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-whole);
  margin: var(--space-three-quarters) 0;
}
.readout { font-family: var(--mono); font-size: var(--type-micro); line-height: 1.6; }
.readout-row { display: flex; gap: var(--space-three-quarters); padding: 3px 0; }
/* 17 Sarasa columns: "data segment MD5", the widest label a reader speaks, and one to breathe. */
.readout-label { color: var(--ink); flex: 0 0 calc(var(--type-micro) * 8.5); }
.readout-value { color: var(--ink); }
.readout-heading { font-family: var(--body); font-size: var(--type-micro); letter-spacing: 0.08em; color: var(--ink); margin: var(--space-three-quarters) 0 var(--space-quarter); }

.bar-shelf { margin-top: var(--space-three-quarters); }
.map-label { font-family: var(--body); font-size: var(--type-micro); color: var(--ink); margin: 0 0 var(--space-half); }
.heat-map { display: flex; height: 32px; border-radius: var(--radius-inside); overflow: hidden; border: 1px solid var(--hairline); }
.heat-cell { flex: 1; cursor: crosshair; }
.map-caption { font-family: var(--mono); font-size: var(--type-micro); color: var(--ink); margin: var(--space-half) 0 var(--space-quarter); min-height: 1.3em; }
.heat-legend { display: flex; align-items: center; gap: var(--space-half); font-size: var(--type-micro); color: var(--ink); margin: 2px 0 var(--space-three-quarters); }
.heat-scale { width: 72px; height: 9px; border-radius: var(--radius-inside); border: 1px solid var(--hairline);
              background: linear-gradient(to right, #EFE6F2, #B99AC5, #6C2D83); }


.walk {
  font-family: var(--mono); font-size: var(--type-micro);
  /* Column widths in Sarasa half-em columns: the widest payload word beside its dot,
     "0x" and eight digits, a grouped byte count. The hex indent lands under the offset column. */
  --walk-operation-column: calc(var(--type-micro) * 6 + var(--space-whole));
  --walk-offset-column: calc(var(--type-micro) * 5.5);
  --walk-size-column: calc(var(--type-micro) * 5);
}
.walk-row { display: flex; gap: var(--space-three-quarters); align-items: baseline; padding: var(--space-quarter) 0; border-bottom: 1px solid var(--room); flex-wrap: wrap; }
.walk-op { display: flex; align-items: center; gap: var(--space-half); flex: 0 0 var(--walk-operation-column); }
.walk-offset { color: var(--ink); flex: 0 0 var(--walk-offset-column); }
.walk-size { flex: 0 0 var(--walk-size-column); }
.walk-detail { color: var(--ink); }
.walk-hex { color: var(--ink); font-size: var(--type-micro); letter-spacing: 0.04em; padding: 1px 0 5px calc(var(--walk-operation-column) + var(--space-three-quarters)); overflow-wrap: break-word; }
.walk-more { display: flex; align-items: baseline; gap: var(--space-half); margin-top: var(--space-half); font-size: var(--type-micro); }

.blob { border: 1px solid var(--hairline); border-radius: var(--radius-hold); background: var(--room); margin: var(--space-quarter) 0 var(--space-three-quarters); }
.blob-header { font-family: var(--body); font-size: var(--type-micro); color: var(--ink); padding: var(--space-half) var(--space-three-quarters); border-bottom: 1px solid var(--hairline); }
.blob pre { margin: 0; padding: var(--space-half) var(--space-three-quarters); font-family: var(--mono); font-size: var(--type-micro); white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.55; }

.encoding-family { display: flex; gap: var(--space-half); align-items: baseline; margin: var(--space-quarter) 0; }
.family-label { font-family: var(--body); font-size: var(--type-micro); color: var(--ink); flex: 0 0 84px; text-align: right; }

/* ------------------------------------------------------------- tutor ---- */

.tutor-label {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-three-quarters);
  font-family: var(--body); font-size: var(--type-micro); letter-spacing: 0.08em; color: var(--ink); margin: var(--space-whole) 0 var(--space-half);
}
.tutor-label .quiet-button { letter-spacing: 0.08em; }
.terminal {
  cursor: pointer;
  font-family: var(--mono); font-size: var(--type-micro); line-height: 1.75;
  background: var(--terminal-room); color: var(--terminal-ink);
  border-radius: var(--radius-hold); padding: var(--space-three-quarters) var(--space-three-quarters); margin: 0;
  white-space: pre-wrap; overflow-wrap: break-word;
}
.terminal .verb-word   { color: var(--terminal-verb); }
.terminal .flag-word   { color: var(--terminal-flag); }
.terminal .value-word  { color: var(--terminal-value); }
/* a placeholder speaks at full brightness; the dashed underline — the sentence slots' own idiom — says "yours to fill" */
.terminal .placeholder { text-decoration: underline dashed rgba(239, 231, 221, 0.5); text-underline-offset: 4px; text-decoration-thickness: 1px; }

/* --------------------------------------------------------------- act ---- */

.act { margin-top: var(--space-whole); display: flex; align-items: center; gap: var(--space-three-quarters); flex-wrap: wrap; }
.run {
  font-family: var(--display); font-weight: var(--weight-loud); font-size: var(--type-emphasis);
  background: var(--grape); color: var(--ink-on-grape);
  border: none; border-radius: var(--radius-hold);
  padding: var(--space-half) var(--space-double);
  box-shadow: 0 3px 0 rgba(106, 45, 128, 0.35);
}
.run:hover { filter: brightness(1.05); }
/* a run that is not ready stays dim, and answers a pointer by outlining everything it is still waiting on */
.run[aria-disabled="true"] { background: #E7E2E4; color: #9A9095; box-shadow: none; }
.run[aria-disabled="true"]:hover { filter: none; }
.quiet-button {
  font-family: var(--body); font-size: var(--type-text); font-weight: var(--weight-firm); color: var(--ink);
  background: none; border: none;
  text-decoration: underline; text-underline-offset: 3px;
}
.quiet-button:hover { color: var(--grape-deep); }

/* --------------------------------------------------------- signature ---- */

.signature {
  display: flex; justify-content: flex-end; align-items: baseline; gap: var(--space-three-quarters); flex-wrap: wrap;
  margin-top: var(--space-double); padding-top: var(--space-three-quarters);
  border-top: 1px solid var(--hairline);
}

/* the one thing a page whose work is all script can still say for itself */
.noscript-note {
  background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-hold);
  padding: var(--space-three-quarters) var(--space-whole); margin: var(--space-three-quarters) 0; font-size: var(--type-text); color: var(--ink);
}
.noscript-note a { color: var(--grape-deep); }
.makers-mark { font-family: 'IM Fell English', 'Fell Stand-in', serif; font-style: italic; font-size: var(--type-text); color: var(--ink); margin: 0; }
.makers-mark a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.makers-mark a:hover { color: var(--grape-deep); }

/* ---------------------------------------------------------- dropveil ---- */

.dropveil[hidden] { display: none; }
.dropveil {
  position: fixed; inset: 10px;
  background: rgba(142, 68, 173, 0.07);
  border: 3px dashed var(--grape);
  border-radius: var(--radius-hold);
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; z-index: 50;
}
.dropveil span {
  font-family: var(--body); font-size: var(--type-text); color: var(--grape-deep);
  background: var(--panel); border: 1px solid var(--hairline);
  border-radius: var(--radius-hold); padding: var(--space-three-quarters) var(--space-whole);
}

/* ------------------------------------------------------------ mobile ---- */

@media (max-width: 640px) {
  .fellow-seat { width: 64px; height: 64px; }
  .run { width: 100%; }
  .signature { flex-direction: column; align-items: flex-end; }
  /* the stacked field has no label column, and wrapped walk rows keep no offset column:
     the indents that aligned under them have nothing to point at, so both sit flush */
  .field-gloss { margin-left: 0; }
  .walk-hex { padding-left: 0; }
  .tiles { grid-template-columns: 1fr; }
  .field { flex-direction: column; align-items: stretch; gap: 3px; }
  .field-label { flex: none; }
}

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