/* Official Cap Check. One instrument's QC screen, built on his 1989 lab terminal photograph
   (art/ref/terminal-qc.jpg, measured in NOTE.md) and reworked on his review of 2026-10-27:
   one rule per panel, one grammar for every label-to-value row, the texture behind the glass and
   never under a letter, and a floor under every text tier instead of an alpha ramp.

   Measured on the field #86f3c0:
     --ink     13.75 : 1   body, values, titles
     --ink-2    9.30 : 1   labels, captions, log, placeholders (his floor for small type is 7:1)
     field on --ink  13.75 : 1   the knocked-out parts: the name bar, the verdict, a pressed key
   --line-soft is a hairline and a leader. It is a graphic and never carries a letter. */

@font-face {
  font-family: "3270";
  src: url("/fonts/3270-regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "3270 Condensed";
  src: url("/fonts/3270-semicondensed.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

:root {
  --field: #86f3c0;             /* his phosphor, lifted until the muted tier clears 7:1 */
  --field-dim: #6ee2ac;         /* the glass away from the centre, and a key at rest */
  --ink: #04170d;               /* his black is not pure: the dark-field mean is #010602 */
  --ink-2: #113b26;             /* the second tier is a colour, not an alpha: 9.3:1 */
  --line-soft: rgba(4, 23, 13, 0.32);  /* hairlines, leaders, separators. Never text. */
  --glow: rgba(134, 243, 192, 0.45);

  --page: min(1120px, 92vw);    /* the column, at the scale his density order sets */
  --rule: 2px;                  /* ONE rule per panel, one thickness on the whole site */
  --hair: 1px;

  /* the only spacings on this site: 4 8 12 16 24 32 48 */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s6: 24px; --s8: 32px; --s12: 48px;
  --pad: var(--s8);             /* a panel is a window body: his inner padding order says 32 */
  --key-h: 48px;

  /* the only sizes here: 16 20 24 32, out of his 12/14/16/20/24/32, cut at the kit's 16 px floor.
     The label tier is therefore a COLOUR and a case, never a smaller size. */
  --t-s: 16px;                  /* labels, captions, table body, keys */
  --t: 16px;                    /* body, values */
  --t-m: 20px;                  /* a panel title */
  --t-l: 24px;                  /* the name on the bar */
  --t-xl: 32px;                 /* the ONE display element of a screen */
  --lh: 1.6;
  --track: 0.04em;              /* capitals get this much and no more: his labels were unreadable */

  --screen-gap: var(--s6);      /* the air between panels, which the live tab has to cross */
  --mono: "3270", ui-monospace, "Cascadia Mono", Consolas, monospace;
  --cond: "3270 Condensed", "3270", ui-monospace, Consolas, monospace;
  --press: 0.08s;
}

* { box-sizing: border-box; }

html { background: var(--field-dim); }

body {
  margin: 0;
  background: var(--field-dim);
  color: var(--ink);
  font: 400 var(--t) / var(--lh) var(--mono);
  letter-spacing: 0.01em;       /* a mono needs no tracking inside a sentence */
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  /* the whole site is set one notch heavier than the regular face: a hairline mono on a coloured
     field was the first thing he could not read. A stroke, not a synthetic bold, which on a
     bitmap-derived mono doubles the stem and closes the counters. */
  -webkit-text-stroke: 0.3px currentColor;
  padding: var(--s6) 0 var(--s12);
  min-height: 100vh;
}

/* the glass sits BEHIND the panels: the scanlines and the bloom are the bezel, not a filter over
   the readout. Everything with a letter in it is painted on an opaque field above this layer. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    repeating-linear-gradient(to bottom, rgba(4, 23, 13, 0.030) 0 1px, rgba(4, 23, 13, 0) 1px 3px),
    radial-gradient(120% 90% at 50% 46%, rgba(4, 23, 13, 0) 44%, rgba(4, 23, 13, 0.22) 100%);
}
.retrace {
  position: fixed;
  left: 0; right: 0; top: 0;
  height: 74px;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.16) 50%, rgba(255, 255, 255, 0) 100%);
  animation: retrace 9s linear infinite;
}
@keyframes retrace {
  from { transform: translateY(-80px); }
  to   { transform: translateY(100vh); }
}

.screen {
  position: relative;
  z-index: 1;
  width: var(--page);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s6);
}

/* ---- the panel: ONE rule, one padding, one background -------------------------------------- */

.panel {
  border: var(--rule) solid var(--ink);
  background: var(--field);
  padding: var(--pad);
}
.panel > :first-child { margin-top: 0; }
.panel > :last-child { margin-bottom: 0; }

/* a title, then ONE rule to the right of it: the old =====TITLE===== was two stubs of different
   lengths, which reads as a mistake rather than as a frame */
.ptitle {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin: 0 0 var(--s6);
  font-size: var(--t-m);
  font-weight: 400;
  letter-spacing: var(--track);
  text-transform: uppercase;
}
.ptitle::after {
  content: "";
  flex: 1 1 var(--s4);
  min-width: var(--s4);
  border-top: var(--rule) solid var(--ink);
}
.ptitle span { min-width: 0; }

/* a section inside a panel: the same device, one weight down */
.shead {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 0 0 var(--s4);
  font-size: var(--t);
  font-weight: 400;
  letter-spacing: var(--track);
  text-transform: uppercase;
}
.shead::after { content: ""; flex: 1 1 var(--s3); min-width: var(--s3); border-top: var(--hair) solid var(--line-soft); }
* + .shead { margin-top: var(--s6); }
.reading__col > .keys { margin-top: var(--s6); }
.verdict + .note { margin-top: var(--s4); }
.keys--row + .note { margin-top: var(--s6); }

hr.rule { border: 0; border-top: var(--hair) solid var(--line-soft); margin: var(--s6) 0; }

/* ---- the name bar -------------------------------------------------------------------------- */

.masthead { padding: 0; }
.masthead__bar {
  background: var(--ink);
  color: var(--field);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s6);
  padding: var(--s4) var(--s8);
}
.masthead__bar strong { font-size: var(--t-l); font-weight: 400; letter-spacing: var(--track); text-shadow: 0 0 14px var(--glow); }
.masthead__label, .masthead__stamp {
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--field);
}
.masthead__body { padding: var(--s8); }
.premise { margin: 0 0 var(--s4); max-width: 76ch; }

.log { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--s2); }
.log li { display: flex; gap: var(--s3); align-items: baseline; font-size: var(--t-s); color: var(--ink-2); }
.log li::before {
  content: "";
  flex: none;
  width: 8px; height: 8px;
  background: var(--ink-2);
  transform: translateY(-0.1em);
}
.log li.pending::before { animation: blink 1.1s steps(1) infinite; }
.log--wide li { font-size: var(--t); color: var(--ink); }
.log--wide li::before { background: var(--ink); }

/* ---- the disk tabs, joined to the file they open ------------------------------------------- */

.tabs {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s1);
  position: relative;
  z-index: 2;
}
/* the file sits ON the tabs: the panel is pulled up through the screen's own gap so that the live
   tab's bottom edge lands on the panel's top rule and paints it out */
.tabs + .panel { margin-top: calc(-1 * (var(--screen-gap) + var(--rule))); }
.tabs__label {
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-2);
  padding: 0 var(--s2) var(--s3) 0;
}
.tabs a {
  display: inline-flex;
  align-items: center;
  min-height: var(--key-h);
  padding: var(--s3) var(--s6);
  border: var(--rule) solid var(--ink);
  background: var(--field-dim);
  color: var(--ink);
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  text-decoration: none;
  transition: background var(--press) linear;
}
.tabs a:hover { background: var(--field); }
.tabs a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.tabs a:active { background: var(--ink); color: var(--field); }
.tabs a[aria-current="page"] {
  background: var(--field);
  border-bottom-color: var(--field);
  padding-bottom: calc(var(--s3) + var(--rule));
}
.tabs a[aria-current="page"]::before {
  content: "";
  flex: none;
  width: 8px; height: 8px;
  background: var(--ink);
  margin-right: var(--s2);
}

/* ---- one grammar for every label-to-value row ---------------------------------------------- */
/* the label on the left, a dotted leader, the value on ONE right line. His exit ladder read
   better than the card beside it, so the card is now the ladder. */

.rec {
  display: grid;
  /* the value track takes exactly what it needs. A value too long to sit on a line of its own
     (a 44 character mint) takes .wide instead, or it starves the label column to nothing. */
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  gap: var(--s2) var(--s4);
  align-items: baseline;
  margin: 0;
}
.rec > dt {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  min-width: 0;
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
.rec > dt::after {
  content: "";
  flex: 1 1 var(--s3);
  min-width: var(--s3);
  border-bottom: var(--hair) dotted var(--line-soft);
  transform: translateY(-0.3em);
}
.rec > dd {
  margin: 0;
  min-width: 0;
  text-align: right;
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}
.rec > dd.wide { grid-column: 1 / -1; text-align: left; }

/* a prose record: a sentence is not a reading, so it keeps its left edge and takes no leader */
.defs {
  display: grid;
  /* 20ch holds the longest label of this site on one line: under that, "painted, rule 1" drops
     its own last word onto a second line and reads as a fault */
  grid-template-columns: minmax(0, 20ch) minmax(0, 1fr);
  gap: var(--s3) var(--s6);
  margin: 0;
  align-items: baseline;
}
.defs > dt {
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-2);
}
.defs > dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* the same record inside a half width column: the label column gives the sentence its room back */
.defs--tight { grid-template-columns: minmax(0, 14ch) minmax(0, 1fr); gap: var(--s3) var(--s4); }

.v--empty { color: var(--ink-2); }

/* ---- the reading: one coin, two columns, one panel ----------------------------------------- */

.reading { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.reading__col { min-width: 0; }
.reading__col:first-child { padding-right: var(--s8); }
.reading__col + .reading__col { padding-left: var(--s8); border-left: var(--hair) solid var(--line-soft); }

/* the one display element of the screen */
.verdict { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s4) var(--s6); }
.verdict__n {
  font-size: var(--t-xl);
  line-height: 1.1;
  letter-spacing: 0.02em;
  background: var(--ink);
  color: var(--field);
  padding: var(--s4) var(--s8);
  text-shadow: 0 0 14px var(--glow);
}
.verdict__w { text-transform: uppercase; letter-spacing: 0.06em; }

/* ---- the state of a coin: one box, one width, a square that is filled or not --------------- */

.status {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  /* wide enough for the longest of the three words, so the boxes of a column are one width and
     their left edges line up instead of stepping */
  min-width: 160px;   /* measured: "no reading" is the longest of the three at 152 px */
  padding: var(--s2) var(--s6);
  border: var(--hair) solid var(--ink);
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  white-space: nowrap;
}
.status::before { content: ""; flex: none; width: 8px; height: 8px; border: var(--hair) solid var(--ink); }
.status--on::before { background: var(--ink); }
.status--none { border-style: dotted; color: var(--ink-2); }
.status--none::before { border-color: var(--ink-2); }

/* ---- the prompt: the one action of the site ------------------------------------------------- */

.prompt { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: stretch; }
.prompt__label {
  flex: 1 1 100%;
  font-size: var(--t-s);
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-2);
}
.field {
  flex: 1 1 280px;
  min-width: 0;
  min-height: var(--key-h);
  font: inherit;
  font-size: var(--t);
  letter-spacing: inherit;
  color: var(--ink);
  background: var(--field);
  border: var(--rule) solid var(--ink);
  padding: var(--s3) var(--s6);
  -webkit-text-stroke: inherit;
}
.field::placeholder { color: var(--ink-2); opacity: 1; }
.field:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.field[aria-invalid="true"] { border-width: 3px; }
.prompt .key { flex: 0 0 auto; min-width: 128px; }
/* in a column stack flex-basis is a HEIGHT, so the field states its width instead */
.stack .field { flex: 0 0 auto; width: 100%; }

/* what the field answers: a refusal is knocked out, which in this grammar is an alarm */
.hint { margin: var(--s3) 0 0; font-size: var(--t-s); color: var(--ink-2); }
.hint--ok { color: var(--ink); }
.hint--bad { background: var(--ink); color: var(--field); padding: var(--s3) var(--s6); display: inline-block; }

/* ---- keys: one height, one padding, four states --------------------------------------------- */

.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: var(--key-h);
  padding: var(--s3) var(--s6);
  border: var(--rule) solid var(--ink);
  background: var(--field);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-s);
  letter-spacing: var(--track);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  -webkit-text-stroke: inherit;
  transition: transform var(--press) linear, background var(--press) linear, color var(--press) linear;
}
.key:hover, .key:focus-visible { background: var(--ink); color: var(--field); }
.key:hover .brand--dark, .key:focus-visible .brand--dark { display: none; }
.key:hover .brand--light, .key:focus-visible .brand--light { display: block; }
.key:active { transform: translateY(2px); background: var(--ink); color: var(--field); }
.key:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.key:disabled, .key[aria-disabled="true"] {
  background: var(--field-dim);
  color: var(--ink-2);
  /* a key that cannot be pressed loses its solid rule: the dim fill alone is too quiet to read */
  border: var(--rule) dashed var(--ink-2);
  cursor: not-allowed;
  transform: none;
}
.key:disabled:hover, .key[aria-disabled="true"]:hover { background: var(--field-dim); color: var(--ink-2); }
.key:disabled .brand, .key[aria-disabled="true"] .brand { opacity: 0.6; }
.key[aria-disabled="true"]:hover .brand--dark { display: block; }
.key[aria-disabled="true"]:hover .brand--light { display: none; }
.brand { width: 16px; height: 16px; display: block; flex: none; }

.keys { display: flex; flex-wrap: wrap; gap: var(--s3); margin: 0; }
/* every platform key the same width, on one left line, across the whole panel: the right two
   thirds of this panel used to be empty while the keys stood in a staircase */
.keys--row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); margin: 0; }
.keys--row .key { width: 100%; }

/* the mint and its copy key: one line, one height */
.mintline { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: stretch; }
.mintline + .rec, form + .note, dl + p { margin-top: var(--s4); }
.mintbox {
  flex: 1 1 200px;   /* small enough that the key beside it stays on the line in a half column */
  min-width: 0;
  min-height: var(--key-h);
  display: flex;
  align-items: center;
  padding: var(--s3) var(--s6);
  /* the same rule width as the key beside it, or the two boxes stand 2 px apart in height */
  border: var(--rule) solid var(--line-soft);
  background: var(--field);
  overflow-wrap: anywhere;
}
.mintline .key { flex: 0 0 auto; min-width: 112px; }
.copy-state { font-size: var(--t-s); color: var(--ink-2); align-self: center; }

/* ---- tables: the pass ---------------------------------------------------------------------- */

.tablewrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-family: var(--cond); font-size: var(--t-s); }
caption { text-align: left; color: var(--ink-2); padding-bottom: var(--s3); font-size: var(--t-s); }
th, td { padding: var(--s3) var(--s6); text-align: right; white-space: nowrap; }
th:first-child, td:first-child { text-align: left; }
thead th {
  text-transform: uppercase;
  letter-spacing: var(--track);
  color: var(--ink-2);
  border-bottom: var(--rule) solid var(--ink);
  font-weight: 400;
}
tbody tr { border-bottom: var(--hair) solid var(--line-soft); }
tbody tr:hover { background: var(--field-dim); }
tbody td a { color: inherit; text-decoration: underline; text-decoration-color: var(--line-soft); text-underline-offset: 4px; }
tbody td a:hover, tbody td a:focus-visible { text-decoration-color: var(--ink); }

/* a file with nothing in it says so, in words. A seven column head over one row read as a fault.
   A bar, not a box: a frame inside a framed panel is the noise he asked to be rid of. */
.empty { border-left: var(--rule) solid var(--line-soft); padding: 0 0 0 var(--s6); display: grid; gap: var(--s3); }
.empty > p { margin: 0; max-width: 76ch; }

/* ---- small parts ---------------------------------------------------------------------------- */

.note { color: var(--ink-2); font-size: var(--t-s); }
.stack { display: flex; flex-direction: column; gap: var(--s4); }
.spread { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s6); align-items: baseline; justify-content: space-between; }
.hide { display: none !important; }
h1, h2, h3 { font-weight: 400; margin: 0; }
p { margin: 0 0 var(--s4); max-width: 76ch; }
a { color: var(--ink); }
a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--field); padding: var(--s3) var(--s6); z-index: 60;
}
.skip:focus { left: var(--s3); top: var(--s3); }

/* the method page's numbered steps, set like the log lines */
.steps { margin: 0; padding-left: 1.6em; display: grid; gap: var(--s3); }
.steps li { padding-left: var(--s1); }
.steps b { font-weight: 400; text-transform: uppercase; letter-spacing: var(--track); }

/* ---- narrow: the two columns stack, the tabs become a block of four ------------------------- */

@media (max-width: 920px) {
  .reading { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .reading__col:first-child { padding-right: 0; padding-bottom: var(--s6); border-bottom: var(--hair) solid var(--line-soft); }
  .reading__col + .reading__col { padding-left: 0; border-left: 0; }
  .defs { grid-template-columns: minmax(0, 1fr); gap: var(--s1) 0; }
  .defs > dd { margin-bottom: var(--s3); }
  .keys--row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
  :root { --pad: var(--s6); --page: min(1120px, 94vw); --screen-gap: var(--s4); }
  body { padding: var(--s4) 0 var(--s8); }
  .screen { gap: var(--s4); }
  .masthead__body { padding: var(--s6); }
  .masthead__bar { padding: var(--s3) var(--s6); }
  .ptitle { font-size: var(--t); }
  .verdict__n { font-size: var(--t-l); }
  /* a tab row that wraps cannot be joined to anything, so on a phone the live tab is knocked out
     instead and the panel below keeps its own rule */
  .tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
  .tabs + .panel { margin-top: 0; }
  .tabs__label { grid-column: 1 / -1; padding: 0; }
  .tabs a { justify-content: center; }
  .tabs a[aria-current="page"] { background: var(--ink); color: var(--field); border-color: var(--ink); padding-bottom: var(--s3); }
  .tabs a[aria-current="page"]::before { background: var(--field); }
  .keys--row { grid-template-columns: minmax(0, 1fr); }
  .mintline .key { flex: 1 1 100%; }   /* a key that has wrapped under the box takes its width */
}

/* the pass needs 905 px for its seven columns (measured). Under that, two of them are dropped
   rather than squeezed into a sideways scroll: the gap and the mark are what the table is for. */
@media (max-width: 1099px) {
  .col-opt { display: none; }
  th, td { padding: var(--s3) var(--s4); }
}

/* under 360 px a label, a leader and a value cannot share a line: the row becomes two lines rather
   than pushing a word through the edge of the panel (measured at 320: the label column fell to 66 px) */
@media (max-width: 360px) {
  .rec { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .rec > dt::after { display: none; }
  .rec > dd { text-align: left; margin-bottom: var(--s3); }
}

@media (prefers-reduced-motion: reduce) {
  .retrace { display: none; }
  .log li.pending::before { animation: none; }
  * { transition: none !important; }
}
