/*
 * Trueline — the instrument.
 *
 * ## The direction, and why this one
 *
 * The product claims to be a measuring instrument, so the site is built out of
 * one: gunmetal and machined grey, chalk-white line work scribed on top of it,
 * and safety yellow used the way it is used on a tool — on the graduations, the
 * cursor and the control you are touching, never as a surface.
 *
 * That is a deliberate move away from where this site was. It used to be warm
 * cream, a serif body face and a terracotta accent, which is the single most
 * recognisable machine-generated look of the moment. Nothing about a Starrett
 * rule or a Stabila level is warm or literary.
 *
 * ## Type
 *
 * - Saira Condensed for display. Condensed, squared, industrial — the face on
 *   the side of the case rather than the one in the book.
 * - IBM Plex Sans for body. Engineering type, drawn by a hardware company.
 * - IBM Plex Mono for every figure, dimension and label, tabular, so a column
 *   of numbers lines up the way it does on a sheet.
 *
 * No serif anywhere, and every face has a real fallback stack because Google
 * Fonts is the only outside host the deployed CSP allows and a blocked font
 * must not take the layout with it.
 *
 * ## Colour
 *
 * Dark is the default and the tuned one; light is the same design in anodised
 * aluminium rather than a washed-out afterthought. Every hex is written once,
 * at the top, and the two themes are a mapping over them.
 *
 * The one set of colours that does NOT belong to the site is the provenance
 * pair — the amber the app paints a scanned length with and the green it paints
 * a measured one. Those are the product's own and they are reproduced exactly.
 * They appear on provenance tags and their legend and nowhere else, so safety
 * yellow never has to fight them for the same job.
 */

:root {
  /* ---- gunmetal, the default ---- */
  --dk-paper:      #14181B;
  --dk-sunk:       #1A1F23;
  --dk-raised:     #21272C;
  --dk-ink:        #E9ECEE;
  --dk-quiet:      #9BA5AC;
  --dk-rule:       #333B41;
  --dk-rule-faint: #262C31;
  --dk-yellow:     #FFD400;
  --dk-yline:      #FFD400;
  --dk-on-yellow:  #14181B;
  --dk-steel:      #8FA0AC;
  --dk-scanned:    #E8873A;
  --dk-measured:   #5FBF85;
  --dk-on-tag:     #14181B;

  /* ---- machined aluminium ---- */
  --lt-paper:      #E7E9EA;
  --lt-sunk:       #DDE0E2;
  --lt-raised:     #F3F4F5;
  --lt-ink:        #14181B;
  --lt-quiet:      #4F585F;
  --lt-rule:       #C0C5C8;
  --lt-rule-faint: #D2D6D9;
  --lt-yellow:     #F2C200;
  /* Yellow cannot be read on aluminium — 1.4:1. Anything drawn in yellow that
     has to be SEEN in the light theme is drawn in this instead: the same hue
     taken down until it clears 3:1 against both of that theme's grounds. */
  --lt-yline:      #8A6A00;
  --lt-on-yellow:  #14181B;
  --lt-steel:      #55636D;
  --lt-scanned:    #B8590A;
  --lt-measured:   #1F6B3A;
  --lt-on-tag:     #FFFFFF;

  /* ---- the mapping: dark unless told otherwise ---- */
  --paper: var(--dk-paper);
  --sunk: var(--dk-sunk);
  --raised: var(--dk-raised);
  --ink: var(--dk-ink);
  --quiet: var(--dk-quiet);
  --rule: var(--dk-rule);
  --rule-faint: var(--dk-rule-faint);
  --yellow: var(--dk-yellow);
  --yline: var(--dk-yline);
  --on-yellow: var(--dk-on-yellow);
  --steel: var(--dk-steel);
  --scanned: var(--dk-scanned);
  --measured: var(--dk-measured);
  --on-tag: var(--dk-on-tag);

  --f-display: 'Saira Condensed', 'Roboto Condensed', 'Arial Narrow',
               'Helvetica Neue', system-ui, sans-serif;
  --f-body: 'IBM Plex Sans', 'Segoe UI', system-ui, -apple-system,
            'Helvetica Neue', Arial, sans-serif;
  --f-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --measure: 66ch;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --page: 68rem;
}

/*
 * Dark unless somebody asks for light, and only if they ask ON THIS SITE.
 *
 * This used to follow the visitor's operating system, which meant most people
 * arrived on the light layout — and the dark one is the site. Sam, looking at
 * both: *"i like the look, but i like the dark layout better as a default."*
 *
 * So the OS preference no longer flips it. `[data-theme='light']` below is the
 * only route to the light palette, and the control in the footer is the only
 * thing that sets it. The palette is not deleted: somebody reading a guide in a
 * bright cab should be able to have it, and the choice is remembered.
 */
@media (prefers-color-scheme: light) {
  :root[data-theme='ask-the-system'] {
    --paper: var(--lt-paper);
    --sunk: var(--lt-sunk);
    --raised: var(--lt-raised);
    --ink: var(--lt-ink);
    --quiet: var(--lt-quiet);
    --rule: var(--lt-rule);
    --rule-faint: var(--lt-rule-faint);
    --yellow: var(--lt-yellow);
    --yline: var(--lt-yline);
    --on-yellow: var(--lt-on-yellow);
    --steel: var(--lt-steel);
    --scanned: var(--lt-scanned);
    --measured: var(--lt-measured);
    --on-tag: var(--lt-on-tag);
  }
}

:root[data-theme='light'] {
  --paper: var(--lt-paper);
  --sunk: var(--lt-sunk);
  --raised: var(--lt-raised);
  --ink: var(--lt-ink);
  --quiet: var(--lt-quiet);
  --rule: var(--lt-rule);
  --rule-faint: var(--lt-rule-faint);
  --yellow: var(--lt-yellow);
  --yline: var(--lt-yline);
  --on-yellow: var(--lt-on-yellow);
  --steel: var(--lt-steel);
  --scanned: var(--lt-scanned);
  --measured: var(--lt-measured);
  --on-tag: var(--lt-on-tag);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1.0625rem/1.62 var(--f-body);
  font-synthesis-weight: none;
  overflow-x: hidden;
}

/* ------------------------------------------------------------------ layout */

.wrap { max-width: var(--page); margin-inline: auto; padding-inline: var(--gutter); }
.narrow { max-width: 44rem; margin-inline: auto; }

/* Sections carry their own spacing so nothing needs a divider between them.
   The old page put an <hr> between all nine, which is most of what made it read
   as a stack of identical slabs. */
/* Each band pays half the gap at each end, so two of them make one gap and a
   band with a ground of its own sits in the same rhythm as one without. */
.band { padding-block: clamp(1.7rem, 3.6vw, 2.9rem); }
.band--sunk { background: var(--sunk); border-block: 1px solid var(--rule-faint); }
.band > .wrap > .eyebrow { margin-top: 0; }

/* ------------------------------------------------------------------- type */

h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.02;
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: clamp(2.7rem, 7vw, 4.9rem); font-weight: 700; line-height: .96; }
h2 { font-size: clamp(1.75rem, 3.6vw, 2.6rem); font-weight: 700; margin: 2.6rem 0 .6rem; }
h3 { font-size: 1.18rem; font-weight: 600; letter-spacing: .005em; }
/* A heading that opens a section already has the section's own space above it,
   and the field label above that. Only a heading standing in running prose has
   to make its own room. */
.eyebrow + h2, .duo h2, .proof h2, .signup h2, .shelf > h2 { margin-top: 0; }
h1 + p, h1 + .lede { margin-top: .95rem; }
p { margin: 0 0 1.05rem; max-width: var(--measure); }
a { color: inherit; text-decoration-color: var(--yline); text-underline-offset: .2em;
    text-decoration-thickness: 1.5px; }
a:hover { text-decoration-thickness: 3px; }
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 2px solid var(--yline); outline-offset: 3px; border-radius: 1px;
}
strong { font-weight: 600; }
code, .num { font-family: var(--f-mono); font-variant-numeric: tabular-nums; font-size: .92em; }

/* The field label. Mono, small, letterspaced, with a GRADUATED rule running off
   it the way a scale runs off a zero mark. */
.eyebrow {
  font-family: var(--f-mono); font-size: .68rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--quiet);
  display: flex; align-items: center; gap: .8rem; margin: 0 0 .9rem; max-width: none;
}
.eyebrow::after {
  content: ''; flex: 1; height: 9px; min-width: 2rem;
  background:
    linear-gradient(var(--rule), var(--rule)) left bottom / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, var(--rule) 0 1px, transparent 1px 8px);
}

.lede { font-size: clamp(1.08rem, 1.9vw, 1.24rem); color: var(--quiet); max-width: 44ch; }

/* -------------------------------------------------------------- title bar */

.bar {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}
.bar .wrap { display: flex; align-items: center; gap: 1.5rem; min-height: 3.5rem; }
.mark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--f-display); font-weight: 700; letter-spacing: .01em;
  font-size: 1.22rem; text-transform: uppercase; color: var(--ink); text-decoration: none;
}
.mark svg { width: 1.5rem; height: 1.5rem; flex: none; }
.mark .b { color: var(--quiet); font-weight: 500; }
.bar nav { margin-left: auto; display: flex; gap: 1.3rem; align-items: center; }
.bar nav a {
  white-space: nowrap;
  font-family: var(--f-mono); font-size: .74rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--quiet); text-decoration: none;
  padding-block: .35rem; border-bottom: 2px solid transparent;
}
.bar nav a:hover { color: var(--ink); }
.bar nav a[aria-current] { color: var(--ink); border-bottom-color: var(--yellow); }
/* One row, every link, at every width, and never a sideways scroll.
   Nothing is hidden and nothing wraps: the type and the wordmark shrink until
   four sections and the mark fit the narrowest phone sold. The width this has
   to survive is 320px -- the iPhone SE and the old SE before it -- measured in
   the browser at 320, 360, 390 and 430 rather than worked out on paper. */
@media (max-width: 46rem) {
  .bar .wrap { gap: .7rem; }
  .bar nav { gap: .62rem; }
  .bar nav a { font-size: .64rem; letter-spacing: .03em; }
  .mark { font-size: 1.02rem; gap: .42rem; }
  .mark svg { width: 1.18rem; height: 1.18rem; }
}
@media (max-width: 23.5rem) {
  .bar .wrap { gap: .5rem; }
  .bar nav { gap: .45rem; }
  .bar nav a { font-size: .58rem; letter-spacing: .008em; }
  .mark { font-size: .92rem; gap: .34rem; }
  .mark svg { width: 1.02rem; height: 1.02rem; }
}

/* ------------------------------------------------- the scale down the edge */

/* The signature, part two: a graduated steel rule pinned to the left edge that
   says where in the page you are. It is drawn by JS and stays `hidden` until
   then, and it only appears where there is margin to hold it without pushing
   the column — so it can never cause a sideways scroll on a phone. */
.scale { display: none; }
@media (min-width: 80rem) {
  .scale:not([hidden]) {
    display: block; position: fixed; left: 0; top: 3.5rem; bottom: 0; width: 5rem;
    z-index: 30; pointer-events: none;
  }
  .scale svg { width: 100%; height: 100%; display: block; overflow: visible; }
  .scale .grad { stroke: var(--quiet); stroke-width: 1; opacity: .38; }
  .scale .grad-major { stroke: var(--quiet); stroke-width: 1; }
  .scale .mark-t { font: 500 9px var(--f-mono); fill: var(--quiet); opacity: .55;
                   letter-spacing: .06em; }
  .scale .mark-t.on { fill: var(--ink); opacity: 1; }
  .scale .mark-l { stroke: var(--rule); stroke-width: 1; }
  .scale .mark-l.on { stroke: var(--yellow); stroke-width: 2; }
  .scale .cursor { fill: var(--yellow); }
  .scale .cursor-l { stroke: var(--yellow); stroke-width: 1; }
}

/* ----------------------------------------------------------------- the hero */

.hero { padding: clamp(1.2rem, 3vw, 2rem) 0 clamp(1.5rem, 3vw, 2.2rem); }
.hero-head { display: grid; gap: 1.4rem 3rem; align-items: end; margin-bottom: 1.6rem; }
@media (min-width: 58rem) { .hero-head { grid-template-columns: 1.15fr .85fr; } }
.hero h1 { max-width: 12ch; }
.hero-act { display: flex; gap: .7rem; flex-wrap: wrap; margin-top: 1.25rem; }

/* The stage: the room, and the panel of controls under it. One instrument. */
.stage {
  position: relative; aspect-ratio: 4 / 3; width: 100%;
  border: 1px solid var(--rule); border-bottom: 0;
  border-radius: .25rem .25rem 0 0;
  background: var(--sunk);
  overflow: hidden; touch-action: none;
}
/* Capped so the panel of switches under it is above the fold on a 900 px
   laptop. The room being driveable is the point of the hero, and a control you
   have to scroll to find is a control most people never find. */
@media (min-width: 58rem) { .stage { aspect-ratio: 16 / 9; max-height: 48vh; } }
.stage[data-view='3d'] { cursor: grab; }
.stage[data-view='3d']:active { cursor: grabbing; }
.stage canvas, .stage > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* The plan is inset from the stage's own corners rather than filling it, so the
   drawing can never end up under the two chips pinned to the top of the frame.
   On a phone the stage is 4:3 and small, and the title block sat squarely on
   top of the north arrow. */
.stage > svg.plan {
  inset: 2.5rem .6rem .6rem;
  /* Sized outright rather than left to the insets: an <svg> carries its own
     intrinsic size, and with width/height auto Chrome keeps that instead of the
     box the insets describe, so the drawing runs off the bottom of the frame. */
  width: calc(100% - 1.2rem); height: calc(100% - 3.1rem);
}
.stage > svg { pointer-events: none; }
.stage canvas[hidden], .stage > svg[hidden] { display: none; }
.stage noscript img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; border: 0; }

.stage .hint, .stage .block {
  position: absolute; top: .55rem; z-index: 2;
  font-family: var(--f-mono); font-size: .64rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--quiet);
  background: color-mix(in srgb, var(--sunk) 82%, transparent);
  padding: .22rem .5rem; border-radius: .15rem;
}
.stage .hint { left: .55rem; }
.stage .block { right: .55rem; text-align: right; line-height: 1.6; border: 1px solid var(--rule-faint); }
.stage .block b { color: var(--scanned); font-weight: 600; letter-spacing: .12em; }
.stage[data-view='plan'] .hint { display: none; }

/* The dimension overlay drawn over the 3D room.
 *
 * These rules used to live in a <style> element inside the <svg> itself, which
 * is exactly one careless `innerHTML = ''` away from every line on the drawing
 * losing its stroke while still being there. In the stylesheet nothing the
 * renderer does can clear them. */
.stage .dim { stroke: var(--quiet); stroke-width: 1; fill: none; }
.stage .tick { stroke: var(--yellow); stroke-width: 1.4; }
.stage .fig {
  font: 500 13px var(--f-mono); fill: var(--ink); text-anchor: middle;
  dominant-baseline: middle; paint-order: stroke; stroke: var(--sunk); stroke-width: 4px;
}
.stage .wall {
  font: 500 11px var(--f-mono); fill: var(--quiet); text-anchor: middle;
  dominant-baseline: middle; letter-spacing: .1em;
  paint-order: stroke; stroke: var(--sunk); stroke-width: 4px;
}

/* The blueprint. Drawn in feet — every stroke width below is a width in feet,
 * so the whole sheet scales as one drawing however big the stage is. */
.plan .p-poche { fill: color-mix(in srgb, var(--ink) 20%, var(--sunk));
                 stroke: var(--ink); stroke-width: .075; stroke-linejoin: miter; }
.plan .p-open { stroke: var(--ink); stroke-width: .06; fill: none; }
.plan .p-swing { stroke: var(--quiet); stroke-width: .05; fill: none; stroke-dasharray: .3 .25; }
.plan .p-furn rect { fill: none; stroke: var(--quiet); stroke-width: .05; }
.plan .p-furn rect.key { stroke: var(--ink); stroke-width: .07; }
.plan .p-dim, .plan .p-wit { stroke: var(--quiet); stroke-width: .04; fill: none; }
.plan .p-wit { opacity: .6; }
.plan .p-arrow { fill: var(--quiet); stroke: none; }
.plan .p-fig {
  fill: var(--ink); font-family: var(--f-mono); text-anchor: middle;
  dominant-baseline: middle; paint-order: stroke; stroke: var(--sunk); stroke-width: .16;
}
.plan .p-lab {
  fill: var(--quiet); font-family: var(--f-mono); text-anchor: middle;
  dominant-baseline: middle; letter-spacing: .06em;
}
.plan .p-north { fill: var(--yellow); stroke: none; }

/* The three switches drive both views from one set of attributes, so a toggle
   cannot mean one thing in 3D and another in plan. */
.stage[data-furn='off'] .p-furn,
.stage[data-dims='off'] .p-dims,
.stage[data-labels='off'] .p-labels { display: none; }

/* The control panel. Every control here is server-rendered and `hidden` until
   the script that drives it has actually attached, so there is never a switch
   on the page that does nothing. */
.panel {
  display: flex; flex-wrap: wrap; align-items: center; gap: .45rem .8rem;
  border: 1px solid var(--rule); border-radius: 0 0 .25rem .25rem;
  background: var(--raised); padding: .55rem .7rem;
}
.panel[hidden] { display: none; }
.panel .lab {
  font-family: var(--f-mono); font-size: .6rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--quiet); margin-right: -.3rem;
}
.panel .grp { display: flex; gap: .35rem; flex-wrap: wrap; }
.sw {
  font-family: var(--f-mono); font-size: .66rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--quiet); background: transparent; cursor: pointer;
  border: 1px solid var(--rule); border-radius: .15rem;
  padding: .38rem .6rem; min-height: 2rem; display: inline-flex; align-items: center; gap: .45rem;
  transition: color .12s ease, border-color .12s ease;
}
.sw::before {
  content: ''; width: .5rem; height: .5rem; border: 1px solid var(--rule); border-radius: 1px;
  background: transparent; flex: none;
}
.sw:hover { color: var(--ink); border-color: var(--quiet); }
.sw[aria-pressed='true'] { color: var(--ink); border-color: var(--yline); }
.sw[aria-pressed='true']::before { background: var(--yellow); border-color: var(--yellow); }
.grp--view .sw::before { display: none; }
.grp--view .sw[aria-pressed='true'] {
  background: var(--yellow); color: var(--on-yellow); border-color: var(--yellow); font-weight: 500;
}
.panel .note-t { font-family: var(--f-mono); font-size: .62rem; color: var(--quiet); letter-spacing: .04em; }
.panel .spacer { flex: 1 1 0; min-width: 0; }

/* ------------------------------------------------------- section rhythms */

/* Two shapes, so that the page is not nine of the same slab. `.proof` puts the
   evidence first and the argument beside it; `.duo` hangs a heading and its one
   onward link off the left and lets the content run wide on the right. */
.proof { display: grid; gap: 1.5rem 3rem; align-items: center; }
/* The plate is a phone screenshot, so it is held at the width of a phone. Given
   half the page it stops being evidence and becomes the page. */
@media (min-width: 58rem) { .proof { grid-template-columns: minmax(0, 21rem) 1fr; } }
.proof figure { margin: 0; }
.proof h2 { margin-top: 0; }

.duo { display: grid; gap: 1.6rem 3rem; }
@media (min-width: 62rem) { .duo { grid-template-columns: 19rem 1fr; align-items: start; } }
.duo > div > p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------ pieces */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--f-display); font-weight: 600; font-size: 1.02rem;
  letter-spacing: .02em; text-transform: uppercase;
  min-height: 2.9rem; padding-inline: 1.4rem; border-radius: .2rem;
  border: 1px solid transparent; text-decoration: none; cursor: pointer;
  transition: transform .1s ease, background-color .12s ease, border-color .12s ease;
}
.btn:active { transform: translateY(1px); }
.btn-solid { background: var(--yellow); color: var(--on-yellow); border-color: var(--yellow); }
.btn-solid:hover { background: color-mix(in srgb, var(--yellow) 85%, var(--ink)); }
.btn-line { border-color: var(--rule); color: var(--ink); background: transparent; }
.btn-line:hover { border-color: var(--ink); }

/* Provenance. The app's own two colours, printed as a stamp rather than as
   tinted text, because tinted amber text on aluminium is 3.9:1 and this is
   0.64rem uppercase — the exact size at which that is not readable. */
.nb { white-space: nowrap; }
.tag {
  display: inline-block; font-family: var(--f-mono); font-size: .64rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; padding: .2rem .42rem;
  border-radius: .12rem; vertical-align: .12em; color: var(--on-tag);
}
.tag-scanned  { background: var(--scanned); }
.tag-measured { background: var(--measured); }

.card {
  border: 1px solid var(--rule); border-radius: .25rem; padding: 1.15rem 1.2rem;
  background: var(--raised);
}
.cards { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.card h3, .card h2 { margin-bottom: .35rem; }
.card h2 { font-size: 1.18rem; font-weight: 600; letter-spacing: .005em; }
.card p { font-size: .95rem; color: var(--quiet); margin: 0; }

figure { margin: 2rem 0; }
figure img {
  display: block; width: 100%; height: auto; border: 1px solid var(--rule);
  border-radius: .25rem; background: var(--sunk);
}
figcaption {
  font-family: var(--f-mono); font-size: .74rem; line-height: 1.6; color: var(--quiet);
  margin-top: .7rem; padding-left: 1.5rem; position: relative; max-width: var(--measure);
}
figcaption::before {
  content: ''; position: absolute; left: 0; top: .62em; width: 1rem; height: 2px;
  background: var(--yline);
}

/* The two films. Both portrait, because both are of a phone. */
.films {
  display: grid; gap: 2rem; margin-top: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  align-items: start;
}
.films figure { margin: 0; }
.films video {
  display: block; width: 100%; max-width: 23rem; height: auto; max-height: 74vh;
  border: 1px solid var(--rule); border-radius: .3rem; background: var(--sunk);
}

table { border-collapse: collapse; width: 100%; min-width: 32rem; font-size: .95rem; }
.scroll { overflow-x: auto; margin: 1.4rem 0; }
th, td { text-align: left; padding: .62rem .55rem; border-bottom: 1px solid var(--rule-faint); vertical-align: top; }
th {
  font-family: var(--f-mono); font-size: .66rem; font-weight: 500; letter-spacing: .12em;
  text-transform: uppercase; color: var(--quiet); border-bottom-color: var(--rule);
}
td:first-child { font-weight: 500; }

.formula { border-left: 2px solid var(--yline); padding: .8rem 0 .8rem 1.1rem; margin: 1.6rem 0; }
.formula .eq { font-family: var(--f-mono); font-size: 1.02rem; color: var(--ink); }
.formula .why { font-family: var(--f-mono); font-size: .8rem; color: var(--quiet); margin-top: .4rem; }

.note {
  background: var(--sunk); border: 1px solid var(--rule-faint); border-left: 2px solid var(--yline);
  border-radius: 0 .25rem .25rem 0; padding: .95rem 1.1rem; margin: 1.6rem 0;
  font-size: .97rem; color: var(--quiet); max-width: var(--measure);
}
.note p:last-child { margin-bottom: 0; }

ol.steps { counter-reset: s; list-style: none; margin: 1.5rem 0 0; padding: 0; }
ol.steps > li { counter-increment: s; padding-top: .8rem; border-top: 1px solid var(--rule-faint); }
ol.steps > li::before {
  content: counter(s, decimal-leading-zero);
  display: block; font-family: var(--f-mono); font-size: .68rem; font-weight: 500;
  color: var(--yline); letter-spacing: .14em; margin-bottom: .45rem;
}
ol.steps h3 { margin-bottom: .3rem; }
ol.steps p { margin: 0; color: var(--quiet); font-size: .95rem; }
ol.steps:not(.steps--grid) > li { padding-bottom: 1.2rem; }
/* On the home page the six steps are a field, not a tower. */
ol.steps--grid { display: grid; gap: 1.5rem 1.8rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }

ul.plain { padding-left: 1.15rem; max-width: var(--measure); }
ul.plain li { margin-bottom: .55rem; }
ul.plain li::marker { color: var(--yline); }

hr.rule { border: 0; border-top: 1px solid var(--rule); margin: clamp(2.5rem, 6vw, 4rem) 0; }

/* --------------------------------------------------------- the spec sheet */

/* What is in it and where it lives, set the way a tool prints its own
   specification: label on the left, value on the right, one hairline between
   rows. It replaces six cards and a four-row table, which is most of the length
   that came off the home page. */
.spec { margin: 1.5rem 0 0; display: grid; gap: 0; }
.spec > div {
  display: grid; gap: .15rem 1.5rem; padding: .8rem 0;
  border-top: 1px solid var(--rule-faint);
}
.spec > div:last-child { border-bottom: 1px solid var(--rule-faint); }
@media (min-width: 44rem) { .spec > div { grid-template-columns: 12rem 1fr; } }
.spec dt {
  font-family: var(--f-mono); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--quiet); padding-top: .25em;
}
.spec dd { margin: 0; font-size: .97rem; max-width: 56ch; }

/* ---------------------------------------------------------------- the plate */

/* The price, set like the plate riveted to the side of a machine. */
.plate {
  border: 1px solid var(--rule); border-radius: .25rem; background: var(--raised);
  padding: clamp(1.2rem, 3vw, 1.9rem); display: grid; gap: 1.3rem 2.5rem;
}
@media (min-width: 50rem) { .plate { grid-template-columns: auto 1fr; align-items: start; } }
.plate .fig { font-family: var(--f-mono); font-variant-numeric: tabular-nums; line-height: 1; }
.plate .fig .big { display: block; font-size: clamp(2.6rem, 6vw, 3.5rem); font-weight: 500; color: var(--ink); }
.plate .fig .unit { display: block; font-size: .68rem; letter-spacing: .18em; text-transform: uppercase;
                    color: var(--quiet); margin-top: .55rem; }
.plate .fig .alt { display: block; font-size: .8rem; color: var(--quiet); margin-top: .4rem; }
.plate .split { display: grid; gap: 1rem 2rem; }
@media (min-width: 34rem) { .plate .split { grid-template-columns: 1fr 1fr; } }
.plate h3 {
  font-family: var(--f-mono); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--quiet); font-weight: 500; margin-bottom: .5rem;
}
.plate ul { list-style: none; margin: 0; padding: 0; font-size: .95rem; }
.plate li { padding-left: 1.05rem; position: relative; margin-bottom: .3rem; }
.plate li::before {
  content: ''; position: absolute; left: 0; top: .68em; width: .55rem; height: 1px; background: var(--yline);
}

/* ------------------------------------------------------------ guide layout */

.guide-head { padding: clamp(2rem, 5vw, 3.25rem) 0 0; }
.guide-head h1 { font-size: clamp(2.1rem, 5vw, 3.4rem); }
.meta {
  font-family: var(--f-mono); font-size: .7rem; letter-spacing: .06em; color: var(--quiet);
  display: flex; flex-wrap: wrap; gap: .5rem 1.1rem; margin-top: 1.4rem;
  padding-top: 1rem; border-top: 1px solid var(--rule);
}
.byline { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; align-items: baseline; }

.toc {
  border: 1px solid var(--rule); border-radius: .25rem; padding: 1rem 1.2rem;
  background: var(--sunk); margin: 2rem 0;
}
.toc p { font-family: var(--f-mono); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase;
         color: var(--quiet); margin: 0 0 .5rem; }
.toc ol { margin: 0; padding-left: 1.15rem; font-size: .95rem; }
.toc li { margin-bottom: .3rem; }
.toc li::marker { font-family: var(--f-mono); font-size: .8rem; color: var(--quiet); }

.faq dt { font-family: var(--f-display); font-weight: 600; font-size: 1.2rem; margin-top: 1.6rem; }
.faq dd { margin: .4rem 0 0; color: var(--quiet); max-width: var(--measure); }

.next { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.next a {
  display: block; border: 1px solid var(--rule); border-left: 2px solid var(--rule);
  border-radius: 0 .25rem .25rem 0; padding: 1rem;
  text-decoration: none; color: var(--ink); background: var(--raised);
}
.next a:hover { border-left-color: var(--yellow); }
.next .k { font-family: var(--f-mono); font-size: .62rem; letter-spacing: .14em;
           text-transform: uppercase; color: var(--quiet); display: block; margin-bottom: .4rem; }
.next .t { font-family: var(--f-display); font-weight: 600; font-size: 1.1rem; line-height: 1.15; }

/* ------------------------------------------------------- the guides index */

/* 28 links in one wall is a directory, not a front door. This is the index as
   four shelves: a contents strip that sticks, and for each audience one guide
   held out with its description and the rest as a list with its reading time in
   a column of its own, which is how somebody actually picks one. */
.index-grid { display: grid; gap: 2.5rem; }
@media (min-width: 62rem) {
  .index-grid { grid-template-columns: 13rem 1fr; gap: 3.5rem; align-items: start; }
  .index-nav { position: sticky; top: 5rem; }
}
.index-nav ol { list-style: none; margin: 0; padding: 0; }
.index-nav li { border-top: 1px solid var(--rule-faint); }
.index-nav li:last-child { border-bottom: 1px solid var(--rule-faint); }
.index-nav a {
  display: flex; justify-content: space-between; gap: 1rem; align-items: baseline;
  padding: .6rem 0; text-decoration: none; color: var(--quiet);
  font-family: var(--f-mono); font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
}
.index-nav a:hover { color: var(--ink); }
.index-nav a b { color: var(--ink); font-weight: 500; }

.shelf + .shelf { margin-top: 3.25rem; }
.shelf > h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); margin-bottom: 0; }
.shelf .blurb { color: var(--quiet); margin: .5rem 0 1.4rem; max-width: 52ch; }
.lead {
  display: block; text-decoration: none; color: var(--ink);
  border: 1px solid var(--rule); border-left: 2px solid var(--yellow);
  border-radius: 0 .25rem .25rem 0; background: var(--raised);
  padding: 1.1rem 1.25rem; margin-bottom: 1.2rem;
}
.lead:hover { border-color: var(--quiet); border-left-color: var(--yellow); }
.lead .k { font-family: var(--f-mono); font-size: .62rem; letter-spacing: .14em;
           text-transform: uppercase; color: var(--quiet); display: block; margin-bottom: .45rem; }
.lead .t { font-family: var(--f-display); font-weight: 700; font-size: clamp(1.3rem, 2.4vw, 1.6rem);
           line-height: 1.1; display: block; }
.lead .d { color: var(--quiet); font-size: .95rem; margin: .5rem 0 0; max-width: 56ch; }

ul.rows { list-style: none; margin: 0; padding: 0; }
ul.rows li { border-top: 1px solid var(--rule-faint); }
ul.rows li:last-child { border-bottom: 1px solid var(--rule-faint); }
ul.rows a {
  display: grid; grid-template-columns: 1fr auto; gap: .4rem 1rem; align-items: baseline;
  padding: .75rem .3rem; text-decoration: none; color: var(--ink);
}
ul.rows a:hover { background: var(--sunk); }
ul.rows a:hover .t { text-decoration: underline; text-decoration-color: var(--yline);
                     text-underline-offset: .2em; text-decoration-thickness: 2px; }
ul.rows .t { font-family: var(--f-display); font-weight: 600; font-size: 1.12rem; line-height: 1.2; }
ul.rows .m { font-family: var(--f-mono); font-size: .68rem; letter-spacing: .08em;
             color: var(--quiet); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ------------------------------------------------------------------ signup */

.signup {
  border: 1px solid var(--rule); border-radius: .25rem; padding: clamp(1.3rem, 3.5vw, 2.2rem);
  background: var(--raised);
}
.signup h2 { margin: 0 0 .5rem; }
.signup form { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.2rem; }
.signup input[type=email], .signup input[type=text] {
  flex: 1 1 13rem; min-height: 2.9rem; padding: .5rem .8rem; border-radius: .2rem;
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  font: inherit; font-size: .98rem;
}
/* No dimming: on this form the placeholder IS the visible label, so it has to
   read at the same contrast as any other text. */
.signup input::placeholder { color: var(--quiet); opacity: 1; }
.signup .fine { font-family: var(--f-mono); font-size: .7rem; color: var(--quiet); margin: .8rem 0 0; }

/* ------------------------------------------------------------------ footer */

footer { border-top: 1px solid var(--rule); margin-top: clamp(3rem, 8vw, 5rem); padding: 2.5rem 0 4rem; }
footer .cols { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
/* Not an <h4>. These four label the footer's link lists, and as headings they
   put a skipped level -- h2 straight to h4 -- into the outline of every page on
   the site. As a <p> naming its own <ul> through aria-labelledby, a screen
   reader still announces the list by name and no outline is touched. */
footer .foot-h { font-family: var(--f-mono); font-size: .66rem; letter-spacing: .14em;
            text-transform: uppercase; color: var(--quiet); font-weight: 500; margin: 0 0 .7rem; }
footer ul { list-style: none; margin: 0; padding: 0; font-size: .92rem; }
footer li { margin-bottom: .4rem; }
footer a { color: var(--quiet); text-decoration: none; }
footer a:hover { color: var(--ink); }
footer .fine { font-family: var(--f-mono); font-size: .7rem; color: var(--quiet); margin-top: 2rem; max-width: none; }

/* -------------------------------------------------------------- utilities */

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

/* ------------------------------------------------------------- animation */

/* One thing moves on the way past, and the room moves when you touch it.
   Nothing else — a page animating in six directions is a page that reads as
   generated. */
.rise { opacity: 0; transform: translateY(12px); transition: opacity .5s ease, transform .5s ease; }
.rise.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .rise { opacity: 1; transform: none; } }

/* The ground control, in the footer. Quiet: it is a preference, not a feature. */
.ground {
  margin-top: 1rem;
  min-height: 44px;
  padding: .5rem 1rem;
  font: inherit;
  font-size: .8rem;
  color: var(--quiet);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 4px;
  cursor: pointer;
}
.ground:hover { color: var(--ink); border-color: var(--ink); }
.ground:focus-visible { outline: 2px solid var(--yellow); outline-offset: 2px; }

/* ------------------------------------------------------------ calculators */

/* The instrument, as a control panel: labels in the mono face that every other
   figure on this site uses, boxes that are boxes, and the answer set below the
   form in the same `.spec` table the home page states the app's own
   specification in. Nothing here is a new visual idea — a calculator that
   looked like a different site would read as an embed from somebody else.

   Two controls are `hidden` in the generated HTML and unhidden by `calc.js`:
   the shape switch and the submit button. With no JavaScript the form cannot
   compute, so neither of them can do anything, and a control that does nothing
   is worse than no control. What is left is a plain form, the formula, and a
   worked example — which is still a page worth reading. */

.calc {
  border: 1px solid var(--rule); border-radius: .25rem; background: var(--raised);
  padding: clamp(1rem, 3vw, 1.6rem); margin: 2rem 0;
}
.calc-grid { display: grid; gap: .9rem 1.2rem; }
@media (min-width: 34rem) { .calc-grid { grid-template-columns: 1fr 1fr; } }

.calc-field { display: grid; gap: .3rem; margin-bottom: .9rem; align-content: start; }
/* Without `align-content: start` the two boxes of a side-by-side pair sit at
   different heights whenever one of their hints wraps onto a second line. */
.calc-grid .calc-field { margin-bottom: 0; }
.calc-field label {
  font-family: var(--f-mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--quiet);
}
.calc input[type=text], .calc input[type=number], .calc select {
  min-height: 2.7rem; padding: .45rem .7rem; border-radius: .2rem;
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  font: inherit; font-family: var(--f-mono); font-size: .95rem;
  font-variant-numeric: tabular-nums; width: 100%;
}
.calc input:focus-visible, .calc select:focus-visible {
  outline: 2px solid var(--yellow); outline-offset: 1px;
}
.calc-hint { font-size: .82rem; color: var(--quiet); max-width: 52ch; }

.calc-switch, .calc-openings {
  border: 1px solid var(--rule-faint); border-radius: .25rem;
  padding: .9rem 1rem 1rem; margin: 0 0 1.1rem;
}
.calc-switch[hidden] { display: none; }
.calc-switch legend, .calc-openings legend {
  font-family: var(--f-mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--quiet); padding: 0 .4rem;
}
.calc-switch { display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; align-items: center; }
.calc-switch label, .calc-check {
  display: flex; align-items: center; gap: .5rem; font-size: .95rem; min-height: 2.2rem;
}
.calc-check { margin-bottom: .9rem; }
.calc input[type=radio], .calc input[type=checkbox] { accent-color: var(--yellow); }

.open-row { display: grid; gap: .5rem .9rem; margin-top: .8rem; }
@media (min-width: 34rem) { .open-row { grid-template-columns: 7rem 1fr 1fr; } }

.walk { display: grid; gap: .5rem; margin-top: .7rem; }
.walk-row { display: grid; grid-template-columns: 1.6rem 8rem 1fr; gap: .5rem; align-items: center; }
.walk-n {
  font-family: var(--f-mono); font-size: .7rem; color: var(--quiet);
  font-variant-numeric: tabular-nums; text-align: right;
}

.calc-act { margin: 1.1rem 0 0; }
.calc-act [hidden] { display: none; }
.calc-out { margin-top: 1.2rem; }
.calc-out:empty { display: none; }
/* The answer sits on the sunk ground so it reads as output rather than as more
   form. Its rows are the same `.spec` list the specification uses. */
.calc-out .spec {
  border-top: 1px solid var(--rule); background: var(--sunk);
  padding: .2rem .9rem; border-radius: .2rem;
}
.calc-out .spec dd { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
.calc-out .formula { margin: 1.1rem 0 0; }
.calc-out .formula .eq + .eq { margin-top: .35rem; }
.calc-out .note { margin-top: 1rem; }
.calc-fine {
  font-family: var(--f-mono); font-size: .68rem; color: var(--quiet);
  margin: 1.1rem 0 0; max-width: none;
}

/* The templates page grew four shelves, and the blurb under a shelf heading was
   only ever styled inside `.shelf`. */
.blurb { color: var(--quiet); margin: .5rem 0 1.4rem; max-width: 52ch; }
