
:root {
  color-scheme: light dark;
  --ground: light-dark(oklch(92.2% 0.016 106.7), oklch(22.3% 0.054 258.1));
  --paper: light-dark(oklch(95.3% 0.012 101.5), oklch(28.8% 0.077 258.1));
  --paper-2: light-dark(oklch(92.9% 0.015 102.5), oklch(24.2% 0.065 259.0));
  --ink: light-dark(oklch(30.3% 0.010 151.5), oklch(91.9% 0.023 248.1));
  --ink-soft: light-dark(oklch(48.8% 0.016 135.0), oklch(72.8% 0.049 255.4));
  --ink-faint: light-dark(oklch(50.7% 0.012 136.6), oklch(67.6% 0.057 255.5));
  --line: light-dark(oklch(82.6% 0.025 112.1), oklch(37.2% 0.082 258.1));
  --edge: light-dark(oklch(73.5% 0.025 112.2), oklch(41.7% 0.088 259.4));
  --accent: light-dark(oklch(42.4% 0.077 253.0), oklch(77.9% 0.081 248.9));
  --accent-soft: light-dark(oklch(61.8% 0.055 252.3), oklch(60.3% 0.087 253.0));
  /* fills keep the red red; in the dark the salmon survives as the hatch stroke */
  --red: light-dark(oklch(50.5% 0.141 30.3), oklch(65.5% 0.142 33.2));
  --red-hatch: light-dark(oklch(50.5% 0.141 30.3), oklch(72.4% 0.114 39.2));
  --green: light-dark(oklch(49.6% 0.055 149.0), oklch(73.8% 0.069 152.0));
  --halo: light-dark(color-mix(in oklch, var(--accent) 10%, transparent), color-mix(in oklch, var(--accent) 12%, transparent));
  /* Annotation grey and the Cherokee-red chop. Declared for the whole set;
     read today only by the type specimen (app/src/specimen.ts). */
  --pencil: light-dark(oklch(59.3% 0.013 133.4), oklch(66.9% 0.057 255.5));
  --cherokee: light-dark(oklch(48.7% 0.136 31.0), oklch(67.1% 0.144 32.5));
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

*, *::before, *::after { box-sizing: border-box; min-width: 0; margin: 0; }
:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  interpolate-size: allow-keywords;
  scrollbar-gutter: stable;
  text-wrap: pretty;
  overflow-wrap: break-word;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
img, video { display: block; max-width: 100%; height: auto; }
button, a, [role="button"] { touch-action: manipulation; }
button, [role="button"] { user-select: none; -webkit-user-select: none; }
@media (pointer: coarse) { input, select, textarea { font-size: max(16px, 1rem); } }
/* ---- THE TYPE ROLES ----
   Decided 2026-09-05 on the type specimen (app/src/specimen.ts, pairing
   5 · THE ATLAS SET). Each stack names the ADOBE FONTS family FIRST — it draws
   on the site, where generator/stage-site.mjs injects the kit — the Google
   Fonts stand-in SECOND, and a generic last. The artifact, and any host
   without the kit, resolves the second name; nothing is ever synthesised.
   Weight 600 is asked for wherever the plan said Demi: Adobe serves 400/700
   and CSS resolves a 600 request upward to 700, Google serves a real 600, so
   ONE number covers both hosts.

   --display  the atlas name, EVERYWHERE it is drawn: rail head, cover title,
              and the wordmark (.project-mark) in every sheet-head PROJECT line
              and title block PROJECT value
   --title    sheet titles, card and prose headings, rail entry titles
   --data     kickers, tracked caps, numbers, schedules, the title block
   --prose    running text, figcaptions, general notes, About. Source Serif
              is the one role whose two names are the SAME design under two
              releases: source-serif-pro from the kit on the site, Source
              Serif 4 from Google in the artifact.
   --code     code identifiers. Source Code Pro on BOTH hosts (2026-09-06):
              source-code-pro from the kit on the site, the same Slimbach
              design from Google in the artifact. Since 2026-09-06 the PLATES
              draw in --data too (see text.lbl* below): mono is reserved for
              code, and --mono survives only as the tail of this stack.
   --hand     P22 FLLW Eaglefeather Informal, MIXED CASE, on the title block's
              DRAWN BY value and at most one callout line per sheet — nowhere
              else. No Google stand-in by decision: off the kit it falls to
              --data, so the artifact loads nothing new.
   --serif    kept as an alias of --prose so nothing downstream breaks. */
:root {
  /* the system stack; since 2026-09-06 nothing reads it but --code's tail */
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --display: "p22-fllw-eaglefeather", "Josefin Sans", sans-serif;
  --title: "p22-flw-exhibition", "Josefin Sans", sans-serif;
  --data: "din-2014", "Barlow Semi Condensed", sans-serif;
  --prose: "source-serif-pro", "Source Serif 4", "Charter", "Bitstream Charter", "Sitka Text", Cambria, Georgia, serif;
  --code: "source-code-pro", "Source Code Pro", var(--mono);
  --hand: "p22-fllw-eaglefeather-inf", var(--data);
  --serif: var(--prose);
}
body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--prose);
  padding: clamp(12px, 0.25rem + 2.7vw, 40px);
  min-height: 100svh;
  line-height: 1.5;
  /* what a sticky inset clears: the routed app raises it for its utility bar */
  --sticky-top: 12px;
}

/* THE SHEET. Full width at every viewport — no centred cap, so a widescreen
   shows the plate near its drawn size; the inner rule at 8 and the text at
   22 keep the double frame reading as one. Only running text keeps a measure. */
.sheet {
  position: relative;
  max-width: none;
  margin-block: 0 40px;
  margin-inline: 0;
  background: var(--paper);
  border: 1.5px solid var(--ink);
  padding: 22px;
  /* paper on a light table casts no soft shadow: the 1px edge only */
  box-shadow: 0 1px 0 var(--edge);
}
.sheet::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1px solid var(--edge);
  pointer-events: none;
}
.sheet > * { position: relative; }

.sheet-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
  border-block-end: 1px solid var(--ink);
  padding-block: 4px 10px;
  padding-inline: 2px;
  margin-block-end: 18px;
}
/* The ledger. 11px of the data face carries the same cap-height as the 10.5px
   mono it replaces (specimen GLYPH SIZE readout, within 1%), so the sizes here
   step up by half a pixel rather than by eye. */
.lettering, .sheet-head, .titleblock, .keyblock, .stat-bar {
  font-family: var(--data);
  font-variant-numeric: tabular-nums;
}
.sheet-head .proj {
  font-size: 11.5px;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
}
.sheet-head .shno {
  font-size: 11.5px;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
}
.sheet-title {
  font-family: var(--title);
  font-size: clamp(18px, 0.25rem + 2.25vw, 24px);
  letter-spacing: 0.06em;
  font-weight: 600;
  text-wrap: balance;
  margin-block-end: 4px;
}
/* THE ARTICLE (T9, shipped 2026-09-06). Every sheet title begins with THE and
   the title face is unicase — no small cap, no alternate, nothing to demote it
   with. So the article is drawn as a superior in the DATA face: lowercase, 0.6em
   of the title, soft ink. It needs no kit face, so it is identical on the site,
   the bare plates and the artifact. line-height 0 keeps the superior out of the
   title's line box. */
sup.art {
  font-family: var(--data);
  font-size: 0.6em;
  font-weight: 400;
  font-variant-numeric: normal;
  letter-spacing: 0;
  text-transform: lowercase;
  line-height: 0;
  color: var(--ink-soft);
  /* the sup carries its own no-break space (so the title reads "the MEASURED
     CITY" to a reader and never breaks after the article); this is the rest */
  margin-inline-end: 0.1em;
}
/* THE WORDMARK — the atlas has ONE name for itself and draws it one way:
   plain uppercase THE ALTITUDE ATLAS in the display face, nothing set apart.
   The rail head and the cover title carry it as text; the ledger sites — every
   sheet-head PROJECT line and the title block's PROJECT value — emit
   PROJECT_MARK, which wraps the same name in .project-mark so the face travels
   with the mark. Only the size differs by site. */
/* THE NAME, wherever the wordmark is drawn in a ledger line. The face travels
   with the MARK, not with the site: the sheet-head line and the title block's
   PROJECT value both emit PROJECT_MARK, so both set THE ALTITUDE ATLAS in
   Eaglefeather at the weight the rail head and the cover title use.
   1.06em, MEASURED not guessed: Eaglefeather at the resolved 700 caps at 0.651
   of its em and DIN 2014 at 0.690, so 0.690/0.651 = 1.06 is the size at which
   the name's cap sits on the ledger's. In a sheet head that is 12.19px of
   display beside 11.5px of data — both cap at 7.94px — and the tail
   (" — DRAWING SET") keeps the ledger face at the line's own size. In a title
   block it is 14.31px inside the 13.5px .dsp, capping at 9.32px: the same cap
   the ledger face would have drawn there, a tenth under the sheet title's. */
.project-mark {
  font-family: var(--display);
  font-size: 1.06em;
  font-weight: 600;
}
.sheet-sub {
  font-family: var(--data);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin-block-end: 16px;
}

/* THE PLATE IS THE PAGE. It never shrinks below 1000px — under that width it
   scrolls in its own wrap like a drawing on a light table, and the wrap says so.
   Above that it grows with the column but is CONTAINED: the whole plate stays on
   one screen. An inline SVG letterboxes under max-height instead of shrinking,
   so the cap reaches it through max-width times the plate's own viewBox ratio
   (--plate-ar, written per sheet). */
.plate { position: relative; container-type: inline-size; margin-block: 36px 8px; margin-inline: 0; --plate-cap: min(84vh, 1400px); }
.figure-wrap { overflow-x: auto; }
.figure-wrap:focus-visible { outline: max(2px, 0.08em) solid var(--accent); outline-offset: -2px; }
.figure-wrap svg { display: block; width: 100%; max-width: min(100%, calc(var(--plate-cap) * var(--plate-ar, 1.4))); height: auto; min-width: 1000px; margin: 0 auto; }
.plate::after {
  content: "SCROLL →";
  display: none;
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  width: 72px;
  padding-block: 6px 0;
  padding-inline: 0;
  text-align: end;
  font-family: var(--data);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
  background: linear-gradient(90deg, transparent, var(--paper) 70%);
  pointer-events: none;
  transition: opacity 0.2s;
}
@container (width < 1000px) { .plate::after { display: block; } }
/* at the end of the scroll the affordance steps aside — the plate's right edge is the point */
.plate[data-end]::after { opacity: 0; }
/* a fillable figure carries a .fill button: fullscreen where the browser grants it, the is-filled overlay where it does not */
.fillable { position: relative; }
.fill { position: absolute; inset-block-start: 8px; inset-inline-end: 8px; z-index: 3; font-family: var(--data); font-size: 9.5px;
  font-weight: 600; letter-spacing: 0.16em; line-height: 1; color: var(--ink); background: var(--paper);
  border: 1px solid var(--ink); padding: 6px 8px; cursor: pointer; opacity: 0.72; }
@media (hover: hover) and (pointer: fine) { .fill:hover { opacity: 1; background: var(--paper-2); } }
.fill:focus-visible { opacity: 1; background: var(--paper-2); outline: max(2px, 0.08em) solid var(--accent); outline-offset: 0.25em; }
.fill:active { transform: scale(0.97); }
@media (prefers-reduced-motion: no-preference) { .fill { transition: transform 160ms var(--ease-out, ease-out); } }
.fill::before { content: "ENLARGE ⤢"; }
.fillable:fullscreen .fill::before, .fillable.is-filled .fill::before { content: "LEAVE ⤡"; }
.fillable:fullscreen, .fillable.is-filled { background: var(--paper); margin: 0; }
.fillable.is-filled { position: fixed; inset: 0; z-index: 60; overflow: auto; }
html.has-filled { overflow: hidden; }
/* a plate fills by its own ratio: as wide as the window allows under its height */
.plate:fullscreen, .plate.is-filled { display: grid; place-items: center; padding: 16px; box-sizing: border-box; overflow: auto; }
.plate:fullscreen .figure-wrap, .plate.is-filled .figure-wrap { width: 100%; }
.plate:fullscreen .figure-wrap svg, .plate.is-filled .figure-wrap svg {
  max-width: min(100%, calc((100vh - 32px) * var(--plate-ar, 1.4))); min-width: 0; }
.plate:fullscreen::after, .plate.is-filled::after { display: none; }
/* a plate's lettering reaches its corners, so its button hangs in the margin above; the filled plate takes it back into the corner */
.plate > .fill { inset-block-start: auto; inset-block-end: calc(100% + 4px); inset-inline-end: 0; }
.plate:fullscreen > .fill, .plate.is-filled > .fill { inset-block-start: 8px; inset-block-end: auto; inset-inline-end: 8px; }
figure { margin: 0; }
/* the caption is a margin note: a rule on the sheet's edge, its text inset to the plate's column */
figcaption {
  font-family: var(--prose);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: calc(750px + 45.5px);
  margin-block: 0 40px;
  margin-inline: 0;
  padding-block: 2px 4px;
  padding-inline: 22px;
  border-inline-start: 1.5px solid var(--ink);
  font-style: italic;
  text-wrap: pretty;
}
figcaption code { font-family: var(--code); font-size: 0.86em; font-style: normal; color: var(--ink); }
/* beside a fixed key column the caption stops where the notes column does */
@media (min-width: 1181px) { figcaption { max-width: min(calc(750px + 45.5px), calc(100% - 352px - 24px)); } }
@media (max-width: 720px) { figcaption { padding-block: 0 2px; padding-inline: 14px 0; font-size: 15px; line-height: 1.55; } }
figcaption .figno {
  font-family: var(--data);
  font-style: normal;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
  margin-inline-end: 10px;
}

/* ONE MEASURE, INSETS TO THE RIGHT. Running text in the left column; the key,
   the title block and the revisions are one inset strip that rides alongside
   whatever paragraph is on screen. The strip and its gutter are named because
   the notes' column count has to subtract them to know its own width. */
.notes-grid {
  --inset: 352px;
  --inset-gap: 24px;
  display: grid;
  grid-template-columns: minmax(0, 7fr) var(--inset);
  gap: var(--inset-gap);
  border-block-start: 1px solid var(--ink);
  padding-block-start: 16px;
  align-items: start;
}
@media (max-width: 1180px) { .notes-grid { grid-template-columns: minmax(0, 3fr) minmax(260px, 2fr); } }
@media (max-width: 720px) { .notes-grid { grid-template-columns: minmax(0, 1fr); } }
.keyblock { position: sticky; inset-block-start: var(--sticky-top); }
@media (max-width: 720px) { .keyblock { position: static; } }
/* COLUMNS AT THE WIDTH THE PAPER GIVES. The count is an integer read off the
   paper itself — one column per 28rem of the notes cell, which is the grid
   less the inset strip and its gutter, both named above so the subtraction
   cannot drift from the track it is subtracting. The query hangs off
   .notes-grid because an element's own container-type does not feed its own
   properties; declared on .notes it would silently resolve against the
   viewport. Under 1180 the grid re-proportions and the cell is never wide
   enough to divide, so the count is simply 1 and no second formula is owed.
   Rounded to nearest, not down: rounding down cannot hold both ends at once —
   two columns at 1440 wants the divisor under 469px, three rather than four at
   2560 wants it over 514px. Nearest at 38rem takes both, and lands 4 at 3008,
   3 at 2560, 2 at 1440, with no column narrower than 447px or wider than 706
   between 1200 and 3400. The measure cap on the paragraph is the one guard the
   count cannot give: it bites only at a single column. */
.notes-grid { container-type: inline-size; }
.notes {
  column-count: calc((100cqw - var(--inset) - var(--inset-gap)) / 38rem);
  column-gap: 44px;
}
@media (max-width: 1180px) { .notes { column-count: 1; } }
.notes h3, .keyblock h3 {
  font-family: var(--data);
  font-size: 11px;
  letter-spacing: 0.18em;
  font-weight: 600;
  color: var(--ink-soft);
  margin-block-end: 8px;
}
/* the head rules the whole block, so it spans it — and is lettered to match */
.notes h3 {
  column-span: all;
  font-size: 12.5px;
  margin-block-end: 18px;
}
.notes p {
  font-family: var(--prose);
  font-size: 18px;
  line-height: 1.8;
  /* Only ever bites at one column: the count holds every wider layout under
     706px on its own, so this is the guard for the 1180–1440 band, where a
     lone column would otherwise run out to 91ch. */
  max-width: 74ch;
  margin-block-end: 2em;
}
.notes p strong { font-weight: 600; }
/* a paragraph's opening strong is a run-in head — give it its own line, but
   only where it opens the paragraph, never a strong caught mid-sentence. It
   never ends a column alone: a head is a promise about the text under it. */
.notes p > strong:first-child { display: block; break-after: avoid; }
/* every inline chip is the code face, not the UA's own monospace default */
code, kbd, samp { font-family: var(--code); }
.notes p code, .gal-body code {
  font-family: var(--code);
  font-size: 0.88em;
  background: var(--paper-2);
  /* fill only: at 14 chips in 15 lines a border made the paragraph a form */
  padding: 0 3px;
  border-radius: 2px;
  /* A chip breaks only when it would otherwise run off the column, and then at
     a space, never inside an identifier. */
  overflow-wrap: break-word;
  hyphens: none;
}
.keyblock table { border-collapse: collapse; width: 100%; }
.keyblock td {
  font-size: 11.5px;
  letter-spacing: 0.03em;
  padding-block: 5px;
  padding-inline: 0 8px;
  border-block-end: 1px solid var(--line);
  vertical-align: middle;
}
.keyblock td:first-child { width: 58px; }
.keyblock svg { display: block; }

.titleblock {
  margin-block-start: 20px;
  margin-inline-start: auto;
  width: min(460px, 100%);
  border: 1.5px solid var(--ink);
  display: grid;
  grid-template-columns: 1fr 1fr;
  font-variant-numeric: tabular-nums;
}
.titleblock > div {
  padding-block: 6px 7px;
  padding-inline: 10px;
  border-block-start: 1px solid var(--ink);
  font-size: 11.5px;
  letter-spacing: 0.06em;
}
.titleblock > div:nth-child(-n+2) { border-block-start: none; }
.titleblock > div:nth-child(2n) { border-inline-start: 1px solid var(--ink); }
.titleblock .span2 { grid-column: 1 / -1; border-inline-start: none !important; }
.titleblock .fld {
  display: block;
  font-family: var(--data);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
  margin-block-end: 2px;
}
/* The two values that carry the atlas's own name, and the sheet's. PROJECT is
   the wordmark, whole and uppercase in the display face — the same wordmark the
   sheet-head line above it carries, at the size this field asks for. */
.titleblock .dsp {
  font-family: var(--display);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.10em;
}
.titleblock .ttl {
  font-family: var(--title);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
/* THE ARTICLE, INLINE — the title block's SHEET TITLE field ALONE. A ledger
   field is read as a value, not as a headline, so here the word is set at the
   value's own size on its own baseline in the data face, rather than lifted
   into a superior. Its own class, so it can never reach sup.art. */
.titleblock .ttl .art-inline {
  font-family: var(--data);
  font-size: inherit;
  font-weight: 400;
  font-variant-numeric: normal;
  text-transform: lowercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  vertical-align: baseline;
}
/* DRAWN BY: the one signed value, in the hand, in mixed case — never tracked
   caps. Sized up from the .dsp 13.5px because Eaglefeather Informal runs a
   smaller cap for its em. */
.titleblock .hand {
  font-family: var(--hand);
  font-size: 16px;
  letter-spacing: 0.02em;
  text-transform: none;
}
/* The chop: a plain square in the Cherokee red, unrotated — the corner stamp,
   not a jaunty sticker. It sits at the right edge of the SHEET cell. */
.titleblock .sh { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.titleblock .chop {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  margin-inline-end: 2px;
  border: 1.5px solid var(--cherokee);
  box-shadow: inset 0 0 0 1.5px var(--paper), inset 0 0 0 4px var(--cherokee);
}

/* ---- SVG drawing classes ---- */
.sk   { stroke: var(--ink); fill: none; stroke-width: 1.3; }
.sk2  { stroke: var(--ink); fill: none; stroke-width: 2; }
.skf  { stroke: var(--line); fill: none; stroke-width: 1; }
.sks  { stroke: var(--ink-soft); fill: none; stroke-width: 1.1; }
.ska  { stroke: var(--accent); fill: none; stroke-width: 1.6; }
.skr  { stroke: var(--red); fill: none; stroke-width: 1.4; }
.skg  { stroke: var(--green); fill: none; stroke-width: 1.4; }
.fp   { fill: var(--paper); }
.fp2  { fill: var(--paper-2); }
.fi   { fill: var(--ink); }
.fis  { fill: var(--ink-soft); }
.fa   { fill: var(--accent); }
.fr   { fill: var(--red); }
.fg   { fill: var(--green); }
.fhalo{ fill: var(--halo); }
.fnone{ fill: none; }
/* THE PLATES DRAW IN THE DATA FACE (2026-09-06). Mono is reserved for code.
   DIN is a strict contraction of the system mono at these sizes — median -26%,
   nothing grows — and every label is start- or end-anchored, so the lettering
   only opens air. Sizes, weights, fills and tracking are unchanged. */
text.lbl   { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 11.5px; fill: var(--ink); letter-spacing: 0.05em; }
text.lblb  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 11.5px; font-weight: 600; fill: var(--ink); letter-spacing: 0.07em; }
text.lbls  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 10.5px; fill: var(--ink-soft); letter-spacing: 0.05em; }
text.lblf  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 10px; fill: var(--ink-faint); letter-spacing: 0.05em; }
text.lbla  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 11px; font-weight: 600; fill: var(--accent); letter-spacing: 0.07em; }
text.lblr  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 9.5px; fill: var(--red); letter-spacing: 0.05em; }
text.lblt  { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 600; fill: var(--ink); letter-spacing: 0.12em; }
text.serif { font-family: var(--serif); font-size: 13px; fill: var(--ink); }

@media (prefers-reduced-motion: no-preference) {
  .sheet { transition: box-shadow 0.2s; }
}
a { color: var(--accent); }
:focus-visible { outline: max(2px, 0.08em) solid var(--accent); outline-offset: 0.25em; }
/* A link inside a plate (helpers.mjs link()): the lettering it wraps underlines on hover and press. */
svg a { cursor: pointer; }
svg a:active text { text-decoration: underline; }
svg a:focus-visible { outline: max(2px, 0.08em) solid var(--accent); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { svg a:hover text { text-decoration: underline; } }

/* The icon table's sprite (icons.mjs): never painted, but not display:none,
   which would stop a <use> resolving. */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: clip; }
/* A lane glyph: 12px in the running colour, centred on the cap height of the
   tracked caps it leads, a small gap before its label. */
.gl.lane { display: inline-block; width: 12px; height: 12px; flex: none;
  vertical-align: calc(0.5cap - 6px); margin-inline-end: 0.45em; }
.gl.lane.after { margin-inline-end: 0; margin-inline-start: 0.45em; }

