/* One station, polished (12 Nov 2026). Quiet type, big product, one idea per section.
   Breaks on purpose (DESIGN.md Tier 2): sentence-case 600 headlines, centred page,
   handwriting on every bottle of the turntable, a second ground colour under the hero. */
h1, h2 { font: 900 1rem/1.02 var(--sans); letter-spacing: -.035em; text-transform: uppercase; text-wrap: balance; }
.lead { text-wrap: balance; }
main { text-align: center; }
/* One measure for the space above and below every section, one size for every section's
   headline, and one width for the lead beside a picture, so the page keeps one rhythm. */
:root { --svh: 100vh; --top: 72px; --pad-y: clamp(56px, min(8vw, calc(var(--svh) * .075)), 116px); --h2: clamp(2.2rem, 5.2vw, 4.4rem); --lead: 36ch; }
/* Every section is at least one screen tall (owner, 13 Nov: "each section should use full view
   port of screen available"). --svh is the screen's height with the browser's bars showing;
   --top is the header's height, which shares the first screen with the hero. A section that
   needs more than a screen keeps its own height. What is spare goes to the picture where the
   picture can grow, and otherwise the words sit in the middle of it. */
@supports (height: 100svh) { :root { --svh: 100svh; } }
[hidden] { display: none !important; }
.fine a { white-space: nowrap; }
/* small links that stand on their own get a finger's worth of height */
.fine .link, .card__group legend a { display: inline-block; padding: 6px 0; }
.close .fine .link { padding: 10px 2px; }
.top__mark { display: inline-flex; align-items: center; min-height: 44px; padding-top: .37em; }   /* the same correction: level with the link opposite */
.skip { position: absolute; left: 12px; top: -64px; z-index: 40; padding: 12px 16px; border-radius: 10px; background: var(--ink); color: var(--warm-white); font: 600 .95rem/1 var(--sans); text-decoration: none; }
.skip:focus { top: 12px; }

/* every buy button says the same thing: "Buy now on Amazon.com" and the flag of that store (owner,
   13 Nov: the flag on every button and wherever the copy names the store, so it is clear which
   Amazon this is; another marketplace later brings its own flag). The verb is its own element
   (data-cta-verb), because the product truth contract sets it from stock: View, Order, Buy, Check. */
.btn { gap: .6em; white-space: nowrap; }
.flag { font: normal 400 1em/1 "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; letter-spacing: 0; }
.btn .flag { font-size: 1.5em; }
p .flag { margin-right: -.24em; }   /* in a sentence: the flag's own white edge would push the full stop away */

/* ------------------------------------------------------------------ hero */
.hero { display: flex; flex-direction: column; min-height: calc(var(--svh) - var(--top)); padding-top: clamp(4px, 1.2vw, 18px); }
.hero::before { content: ""; flex: 2 1 0; }   /* spare height: two parts above the headline, three under the small print, as counter */
.hero__text { padding: 0 var(--gutter); }
.hero h1 { font-size: clamp(2.75rem, 6.4vw, 5.8rem); }
.hero .lead { max-width: 68ch; margin: 14px auto 0; font-size: clamp(1.04rem, 1.3vw, 1.18rem); color: var(--muted); }

/* The turntable: four bottles, one per band size, standing behind the counter. Three show at a
   time: the front one large and exactly in the middle of the page, one smaller on each side.
   Everything is set out from the bands:
     - every band's bottom edge is on one line, the same short strip of bottle above the counter
       (each bottle is scaled about the bottom of its own band, --bb);
     - the space between one band and the next is the same on both sides (--gap), whichever
       bottles stand there (station.js works the places out from the band widths, --bw);
     - the pictures are as large as the screen allows with all three labels whole: --fw is the
       smaller of what the height and the width allow. The stage is --k of a picture's width
       tall, which is as far up as the middle of the tallest bottle's nozzle (Medium: its nozzle
       runs from 3.6% to 27.8% of the picture). The top --fade of the stage fades into the page,
       so at most the top half of a nozzle goes missing, and never at a hard edge.
   --x and --s are a bottle's place: station.js drives them, and the data-pos values are the
   resting places a page without script shows. A bottle can be clicked to bring it to the front
   (station.js adds the hit areas). */
.turn { --sF: .6; --sB: .42; --soft: 2; --wf: 44.2; --gap: clamp(16px, 2.8vw, 42px); --edge: 16px; --vh: 100vh; --room: 440px; --least: 200px; --k: .62;
  --fwH: calc(clamp(var(--least), calc(var(--vh) - var(--room)), 560px) / var(--k));
  --fwW: calc((50vw - var(--gap) - var(--edge)) / (.2735 + .52 * var(--sF)));
  --fw: min(var(--fwH), var(--fwW)); --strip: calc(var(--fw) * .03); --fade: calc(var(--fw) * .042);
  position: relative; height: calc(var(--fw) * var(--k)); overflow: hidden; margin-top: clamp(6px, 1vw, 14px); column-gap: var(--gap); }
@supports (height: 100svh) { .turn { --vh: 100svh; } }
/* a short laptop screen: the button stays on the first screen, the small print may not */
@media (min-width: 761px) and (max-height: 800px) { .turn { --room: 418px; } }
/* the fade at the top of the stage: a mask on the bottles only, so the page's ground is untouched */
.turn__ring { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, .2) calc(var(--fade) * .3), #000 var(--fade));
  mask-image: linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, .2) calc(var(--fade) * .3), #000 var(--fade)); }
.t { --x: 0px; --s: 1; position: absolute; left: 50%; bottom: calc(var(--strip) - (100 - var(--bb)) * var(--fw) / 120); width: var(--fw); margin-left: calc(var(--fw) / -2); aspect-ratio: 6 / 5;
  transform-origin: 50% calc(var(--bb) * 1%); transform: translateX(var(--x)) scale(var(--s)); z-index: 4;
  container-type: inline-size; will-change: transform; pointer-events: none; }
.t[data-pos="1"] { --s: var(--sF); --x: calc(-1 * (var(--gap) + var(--fw) * (var(--sF) * var(--bw) + var(--wf)) / 200)); z-index: 2; }
.t[data-pos="3"] { --s: var(--sF); --x: calc(var(--gap) + var(--fw) * (var(--sF) * var(--bw) + var(--wf)) / 200); z-index: 2; }
.t[data-pos="2"] { --s: var(--sB); z-index: 1; }
.t img { display: block; width: 100%; height: 100%; max-width: none; -webkit-user-drag: none; user-select: none; }
.t .t__next { position: absolute; left: 0; top: 0; opacity: 0; transition: opacity .42s; }   /* the bottle's other colour, faded in at the back */
.t .t__next.is-on { opacity: 1; }
/* the part of a picture that is the bottle: a click there brings that bottle to the front */
.t__hit { position: absolute; left: var(--l); width: var(--w); top: 18%; bottom: 0; pointer-events: auto; cursor: pointer; }
.t.is-front .t__hit { cursor: default; }
.b__word { position: absolute; left: var(--l); top: var(--t); width: var(--w); height: var(--h); display: grid; place-items: center; font: 400 calc(var(--fs) * 1cqw)/1 var(--marker); color: #161616; white-space: nowrap; transform: rotate(-1.5deg); }
.b__ink { position: absolute; left: var(--l); width: var(--w); top: calc(var(--t) - var(--h) * .04); height: calc(var(--h) * 1.08); display: none; pointer-events: none; transition: opacity .18s; }
.is-ink .b__word { visibility: hidden; }
.is-ink .b__ink { display: block; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* the counter the bottles stand behind: a change of ground, not a line. What is on it is one
   block as wide as the size control, and everything in it shares that block's two edges:
     - the four sizes as one small control (S, M, L, XL on a quiet track, the picked one a white
       tile with a dark edge, like the writing box on a band) and, on the same line, the bottle
       widths that size fits. One measurement on screen, not four (owner, 14 Nov);
     - one button as wide as the block.
   The yellow button stays the only loud thing here. */
.counter { flex: 3 0 auto; background: var(--field); padding: clamp(12px, 1.2vw, 16px) var(--gutter) clamp(28px, 4vw, 48px); }
.till { max-width: 560px; margin: 0 auto; text-align: left; }
.till__size { display: flex; align-items: center; justify-content: center; gap: 16px; }
.till__size .pick { flex: none; }
.pick--seg .pick__row { grid-template-columns: repeat(4, 52px); gap: 0; max-width: none; padding: 4px; border-radius: 18px; background: rgba(26, 26, 26, .07); }
/* a size button is never under 44 px either way: it is a thing to tap */
.pick--seg label > span { display: flex; align-items: center; justify-content: center; min-height: 44px; padding: 0; background: none; border-radius: 14px;
  font: 700 1.02rem/1 var(--sans); letter-spacing: .03em; color: rgba(26, 26, 26, .72); transition: color .25s, background .25s, box-shadow .25s; }
.fits { margin: 0; white-space: nowrap; font: 400 1.12rem/1.2 var(--sans); color: rgba(26, 26, 26, .74); }
.fits > b { font-weight: 600; color: var(--ink); }
.fits i { font-style: normal; margin: 0 .24em; }
/* a fraction set from real figures (the ready-made characters for 1/8, 3/8 and 7/8 are too small to tell
   apart). A <b>, not a <span>: base.css styles every span in a size picker as a tile. */
.fr { display: inline-block; margin: 0 .03em 0 .09em; font-size: .68em; font-weight: 600; white-space: nowrap; }
.fr sup, .fr sub { position: relative; font-size: 1em; line-height: 0; vertical-align: baseline; }
.fr sup { top: -.44em; margin-right: .02em; }
.fr sub { top: .04em; margin-left: .02em; }
.pick--seg label:hover > span { color: var(--ink); background: rgba(255, 255, 255, .45); }
.pick--seg input:checked + span { background: #fff; color: var(--ink); box-shadow: inset 0 0 0 2px var(--ink); }
/* the button: what it does and the flag of the Amazon store it opens (no price in it: owner,
   13 Nov). As wide as the block less its own shadow, so the right-hand edges agree.
   .btn__price is the price in the phone buy bar's button. */
.till .btn { display: flex; width: calc(100% - 4px); min-height: 56px; margin-top: 14px; padding: 0 20px; }
.btn__price { margin-right: .3em; font: 900 1.35rem/1 var(--sans); letter-spacing: 0; }
.counter .fine { margin: 14px 0 0; text-align: center; font-size: .86rem; }
/* a large screen: the bottles are at their largest, so the block under them grows a little to keep step */
@media (min-width: 1700px) and (min-height: 1000px) {
  .till { max-width: 640px; }
  .till__size { gap: 20px; }
  .pick--seg .pick__row { grid-template-columns: repeat(4, 60px); }
  .pick--seg label > span { min-height: 50px; font-size: 1.14rem; }
  .fits { font-size: 1.26rem; }
  .till .btn { min-height: 62px; font-size: .92rem; }
  .btn__price { font-size: 1.55rem; }
  .counter .fine { font-size: .92rem; }
}
.price { letter-spacing: .04em; font-size: .86rem; }

/* ------------------------------------------------------------------ sections */
.sec { min-height: var(--svh); align-content: center; padding: var(--pad-y) var(--gutter); }
.sec--field { background: var(--field); }
.sec h2 { font-size: var(--h2); max-width: 15ch; margin: 0 auto; }
.sec .lead { max-width: 44ch; margin: 20px auto 0; font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.sec .gap { margin: 28px auto 0; text-align: left; max-width: 52ch; opacity: .85; }
.sec > .fine { max-width: 52ch; margin-left: auto; margin-right: auto; }

/* tape: a part-used bottle of aioli labelled the old way. The strip peels off as the page
   scrolls (station.js draws the frame the scroll position asks for on the canvas). The bottle
   is cut by the next section's ground, as the hero's bottles are by the counter. It is the
   bottle of the next section, drawn through the same window (tools/render_tape.py: 1500 x 1250,
   the tape where the band is) and shown in the same box with the same crop, so nozzle, cap and
   body are in the same place in both sections (owner, 14 Nov: "copy the exact size of bottle in
   section 3 ... the tape has to reposition to the same location in 3"). Every number in
   .tape__pic and .tape__frame is .write__pic's and .write__frame's: change them together. */
/* The bottle in the tape section and in the next one is one bottle, so one width serves both:
   --pb is the width its picture had before the sections filled the screen (and still has on a
   short one), --pw the width it has now: as wide as puts the picture at 73% of the screen's
   height, but never so wide that the bottle reaches the words. Both pictures grow about the
   bottle's middle (43.98% across the figure), so it stays on the page's one vertical line:
   --c0 is how far that line is from the middle of the screen, 290px wherever the page's
   1160px grid fits (the middle of its right half).
   (On :root, because the fit section sizes its bottle from the same width.) */
:root { --pb: min(600px, 48vw); --c0: calc(2vw + .4398 * var(--pb)); --pw: clamp(var(--pb), calc(var(--svh) * .79), min(860px, calc((var(--c0) - 8px) / .236))); }
@media (min-width: 1256px) { :root { --c0: 290px; } }
.tape { min-height: var(--svh); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; text-align: left; overflow: hidden; }
.tape__text { position: relative; z-index: 1; padding: var(--pad-y) var(--gutter) var(--pad-y) max(var(--gutter), calc(50vw - 580px)); }
.tape h2 { font-size: var(--h2); max-width: 14ch; }
.tape .lead { margin-top: 20px; max-width: var(--lead); font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
/* the band's answer to the tape, said once and plainly, in the lead's own size */
.answer { margin: 14px 0 0; max-width: var(--lead); font-size: clamp(1.06rem, 1.35vw, 1.22rem); font-weight: 600; text-wrap: balance; }
.tape__pic { --y0: 20; --ch: 1230; position: relative; align-self: end; width: var(--pw); margin: clamp(24px, 3vw, 48px) 0 0 calc(var(--c0) - .4398 * var(--pw)); aspect-ratio: 1330 / var(--ch); overflow: hidden; }
.tape__frame { position: absolute; left: -12.41%; top: calc(var(--y0) / var(--ch) * -100%); width: 112.78%; aspect-ratio: 6 / 5; }
.tape__pic img { display: block; width: 100%; height: 100%; max-width: none; }
.tape__pic canvas { position: absolute; display: none; pointer-events: none; }

/* live stages: the still paints first and stays as the fallback */
.live { position: relative; }
.live__still, .live__frame { transition: opacity .6s; }
.live__frame { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
.live__frame iframe { display: block; width: 100%; height: 100%; border: 0; color-scheme: normal; }
.live.is-live .live__frame { opacity: 1; pointer-events: auto; }
.live.is-live .live__still { opacity: 0; }
.cap { font: 500 .66rem/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin: 0; visibility: hidden; }
.is-live ~ .cap { visibility: visible; }

/* writing: the bottle from the tape section again, in the same place on the page, now wearing
   a band. It is the hero's own picture of the aioli bottle (blank band) with the marker drawn on
   the band as the hero does. The writing follows the scroll: written, wiped, written again
   (station.js). Cut by the next section's ground. The words are a headline, one sentence and one
   honest note (owner, 13 Nov: "simplified, remove fluff"), in the middle of the screen's height.
   --y0 and --ch are the top and the height of the part of the 1500 x 1250 picture that shows:
   the whole top of the bottle on a wide screen. */
.write { min-height: var(--svh); background: var(--field); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: 1fr auto auto 1fr; text-align: left; overflow: hidden; }
.write__head, .write__body { position: relative; z-index: 1; grid-column: 1; padding: 0 var(--gutter) 0 max(var(--gutter), calc(50vw - 580px)); }
.write__head { grid-row: 2; padding-top: var(--pad-y); font-size: var(--h2); max-width: calc(12ch + max(var(--gutter), 50vw - 580px)); }
.write__body { grid-row: 3; padding-bottom: var(--pad-y); }
.write .lead { margin-top: 20px; max-width: var(--lead); font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.write .fine { margin-top: 14px; max-width: var(--lead); }
.write__pic { --y0: 20; --ch: 1230; grid-column: 2; grid-row: 1 / -1; position: relative; align-self: end; width: var(--pw); margin: clamp(24px, 3vw, 48px) 0 0 calc(var(--c0) - .4398 * var(--pw)); aspect-ratio: 1330 / var(--ch); overflow: hidden; }
.write__frame { position: absolute; left: -12.41%; top: calc(var(--y0) / var(--ch) * -100%); width: 112.78%; aspect-ratio: 6 / 5; container-type: inline-size; }
.write__frame img { display: block; width: 100%; height: 100%; max-width: none; }

/* fit: one of the hero's bottles, the size the slider asks for, standing on the page's own
   ground (owner, 13 Nov: "bg should be seamless with main bg"; it stood in a card until then)
   and cut by the next section's ground, as the tape and writing bottles are. The bottle grows
   and shrinks with the measurement (gently, as the hero's sizes differ), and a measuring line
   under the band spans it. station.js sets each picture's width and places the line; without
   script the Medium bottle and the list of ranges show.
   The words are the same skeleton as the sections either side: headline and lead on the page's
   left edge, then one block as wide as the slider, everything in it on the block's two edges
   (the width read back with the band that fits it, the slider, its size chart, the price, the
   button). The picture is in the middle of the right half. */
.bench { max-width: 1160px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; text-align: left; }
.bench__text { padding-right: clamp(24px, 5vw, 80px); }
#fit h2 { margin: 0; max-width: 11ch; }
#fit .lead { margin: 20px 0 0; max-width: var(--lead); }
.gauge { display: flex; flex-direction: column; margin: 0 auto; width: 100%; max-width: 580px; }
/* On a wide screen the stage is as wide as the tape and writing pictures (--pw), which makes the
   bottle the slider starts on as wide as theirs: the same bottle, three sections running. It may
   be wider than its half of the grid, since it has no ground of its own, but never so wide that
   the widest bottle (78% of the stage) leaves that half. */
@media (min-width: 761px) {
  .gauge { --col: calc((min(100vw, 1160px + 2 * var(--gutter)) - 2 * var(--gutter)) / 2); --gw: min(var(--pw), calc(1.28 * var(--col) - 20px));
    width: var(--gw); max-width: none; margin: 0 0 0 calc((100% - var(--gw)) / 2); }
}
/* the stage has no ground of its own. Its top fades, so the band that comes down onto the bottle does not appear at an edge */
.gauge__stage { flex: none; position: relative; aspect-ratio: 1 / 1.4; min-height: 300px; max-height: calc(var(--svh) * .78); overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 52px); mask-image: linear-gradient(to bottom, transparent 0, #000 52px); }
.gauge__b > img { -webkit-mask-image: linear-gradient(180deg, transparent calc(100% - var(--see, 9999px)), #000 calc(100% - var(--see, 9999px) + 36px)); mask-image: linear-gradient(180deg, transparent calc(100% - var(--see, 9999px)), #000 calc(100% - var(--see, 9999px) + 36px)); }
.gauge__b { position: absolute; left: 50%; bottom: 0; width: 86%; aspect-ratio: 6 / 5; transform: translateX(-50%); opacity: 0; transition: opacity .22s; container-type: inline-size; }
.gauge__b.is-on { opacity: 1; }
.gauge__b > img { display: block; width: 100%; height: 100%; max-width: none; -webkit-user-drag: none; user-select: none; }
/* the band and its label are one layer over the bottle (which is rendered without a band), so
   station.js can drop the band on: it comes down over the cap a little stretched and settles */
.gauge__on { position: absolute; inset: 0; transform-origin: calc(var(--bx) + var(--bw) / 2) calc(var(--by) + var(--bh) / 2); will-change: transform; }
.gauge__band { position: absolute; left: var(--bx); top: var(--by); width: var(--bw); height: var(--bh); max-width: none; -webkit-user-drag: none; user-select: none; }
.gauge.is-waiting .gauge__on { visibility: hidden; }
/* the measuring line: it shows where to measure. The number is read back beside the slider */
.gauge__rule { display: none; position: absolute; height: 0; border-top: 2px solid var(--ink); }
.js .gauge__rule { display: block; }
.gauge__rule::before, .gauge__rule::after { content: ""; position: absolute; top: -9px; width: 2px; height: 16px; background: var(--ink); }
.gauge__rule::before { left: -1px; }
.gauge__rule::after { right: -1px; }
.gauge__list { order: -1; display: grid; grid-template-columns: repeat(4, 1fr); margin: 0 0 12px; padding: 0; list-style: none; text-align: center; }
.gauge__list li { font: 500 .82rem/1.4 var(--mono); letter-spacing: .02em; color: var(--muted); }
.gauge__list li b { display: block; font: 600 1.15rem/1.2 var(--sans); color: var(--ink); }
.js .gauge__list { display: none; }
:root:not(.js) .gauge__stage { aspect-ratio: 6 / 5; }   /* without script the list of ranges sits just over the bottle */
.measure { text-align: left; max-width: 400px; margin-top: clamp(22px, 3vw, 34px); }
:root:not(.js) .measure > :not(.buy) { display: none; }   /* without script: no slider, but the Medium pack's price and button stay */
:root:not(.js) .buy { margin-top: 0; }
.measure label { display: block; font: 500 .78rem/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.measure__read { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; margin: 8px 0 0; }
.measure output { font: 600 clamp(2.6rem, 5vw, 3.8rem)/1 var(--sans); letter-spacing: -.035em; white-space: nowrap; }
.measure output .fr { margin: 0 .05em 0 .2em; font-size: .58em; letter-spacing: 0; }
.sp { font-size: .34em; font-style: normal; }   /* a real space between the whole number and its fraction, drawn narrow */
.measure__read > span { font-size: 1.15rem; line-height: 1.2; white-space: nowrap; }
.measure__read b { font-weight: 600; }
.measure input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 44px; margin: 8px 0 0; background: transparent; cursor: pointer; }
.measure input[type="range"]::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: rgba(26,26,26,.2); }
.measure input[type="range"]::-moz-range-track { height: 6px; border-radius: 3px; background: rgba(26,26,26,.2); }
.measure input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 30px; height: 30px; margin-top: -12px; border-radius: 50%; background: var(--ink); border: 4px solid var(--cream); box-shadow: 0 0 0 2px var(--ink); }
.measure input[type="range"]::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: var(--ink); border: 4px solid var(--cream); box-shadow: 0 0 0 2px var(--ink); }
/* the slider's track is the size chart: four stretches, the one the thumb is in goes dark */
.zones { display: grid; grid-template-columns: 10fr 15fr 15fr 15fr; gap: 3px; margin: 0 15px 0; }
.zones span { padding-top: 8px; border-top: 3px solid rgba(26,26,26,.16); font: 700 .82rem/1 var(--mono); letter-spacing: .06em; text-align: center; color: var(--muted); transition: color .2s, border-color .2s; }
.zones span.is-on { border-top-color: var(--ink); color: var(--ink); }
/* the price, then one button as wide as the block (less its own shadow), as in the hero */
.buy { margin-top: 28px; }
.measure .price { margin: 0 0 12px; }
.buy .btn { display: flex; width: calc(100% - 4px); }

/* dishwasher: the page's one yellow field. The picture is the inside of a commercial dishwasher
   rack, shot from down among the pegs (a render made for this section, with the live band's own
   camera), so the band sits in it at its true size: about one square of the rack's floor. The
   picture fades into the yellow toward the words, so they stay easy to read. The band is live
   where WebGPU runs (turning slowly, beaded, steaming), and four registered renders elsewhere,
   dry and three stages of wet, that station.js fades in as the page scrolls. A page without
   script, or a reader who asked for less motion, sees the wettest one. */
.pit { min-height: var(--svh); background: #FCE301; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; text-align: left; overflow: hidden; }
.pit__text { position: relative; z-index: 1; padding: var(--pad-y) var(--gutter) var(--pad-y) max(var(--gutter), calc(50vw - 580px)); }
.pit h2 { font-size: var(--h2); max-width: 16ch; }
.pit .lead { margin-top: 20px; max-width: var(--lead); font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.pit__pic { align-self: end; }
/* What shows of the picture: the live frame, the picture above it (--up, a share of the frame's
   height; the render reaches 0.31 above) and not the frame's bottom strip (--cut), which is only
   more rack floor. The view bleeds off the section's right edge and is cut by its bottom. */
.wash__view { --up: .31; --cut: .15; position: relative; width: 122%; max-width: max(1000px, 52vw); margin-left: -18.2%;
  aspect-ratio: 2000 / calc(1644 * (1 + var(--up) - var(--cut))); }
/* On a wide screen the view grows by up to 8% to meet the screen's height (--w0 is the width
   above, --ww the width it has), about the band's middle, which is 47.9% across it, so the band
   stays on the page's line and the rack does not reach the words. Where the section is still
   taller than the picture, the top of the rack fades into the yellow (--tf) and is never an edge. */
@media (min-width: 761px) {
  .wash__view { --w0: min(61vw, max(1000px, 52vw)); --ww: clamp(var(--w0), calc(var(--svh) / .9535), calc(var(--w0) * 1.08));
    --tf: calc(clamp(0px, calc(var(--svh) - var(--ww) * .9535), 1px) * 150);
    --b0: calc(-9.1vw + .479 * var(--w0));
    width: var(--ww); max-width: none; margin-left: calc(var(--b0) - .479 * var(--ww)); }
}
@media (min-width: 1256px) { .wash__view { --b0: 290px; } }   /* the band on the middle of the grid's right half */
.live--wash { position: absolute; left: 0; top: calc(100% * var(--up) / (1 + var(--up) - var(--cut))); width: 100%; aspect-ratio: 2000 / 1644; }
/* the rack picture reaches past the live frame to the left, to the right (so it runs off the screen's edge) and above, as tools/render_dishwasher.py prints it, and fades toward the words */
.wash__rack { position: absolute; left: -16%; top: -31%; width: 151%; height: auto; max-width: none; color: transparent;
  -webkit-mask-image: linear-gradient(to right, transparent 3%, rgba(0,0,0,.06) 8.5%, rgba(0,0,0,.24) 13.8%, rgba(0,0,0,.56) 20%, rgba(0,0,0,.86) 25.3%, #000 30.7%), linear-gradient(to bottom, transparent 0, #000 var(--tf, 0px));
  mask-image: linear-gradient(to right, transparent 3%, rgba(0,0,0,.06) 8.5%, rgba(0,0,0,.24) 13.8%, rgba(0,0,0,.56) 20%, rgba(0,0,0,.86) 25.3%, #000 30.7%), linear-gradient(to bottom, transparent 0, #000 var(--tf, 0px));
  -webkit-mask-composite: source-in; mask-composite: intersect; }
.wash { position: absolute; left: 17.5%; top: 17.5%; width: 76.5%; }   /* as tools/render_wash.py prints it */
.wash img { display: block; width: 100%; height: auto; max-width: none; }
/* behind the still band, one frozen moment of the live scene's steam (tools/render_wash.py makes it) */
.wash__steam { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.wash__steam img { display: block; width: 100%; height: 100%; max-width: none; will-change: opacity; }
.wash img + img { position: absolute; left: 0; top: 0; will-change: opacity; }
/* the live frame is the box itself; the scene's ?px, ?py and ?zoom seat the band, and the rack picture was shot for that seat */
.live--wash .live__frame { inset: 0; }
.live--wash .live__frame, .live--wash .wash { z-index: 2; }

/* the order: the site's full order card (every size, both pack counts and the mixed 32, all
   nine colours; shared/catalog.js is the site's own catalogue) beside what is in the chosen
   pack: its bands, loose and clean, with one line saying what they are. A spot holds one band
   (8-pack), a stack of three (24-pack) or a nested set of the four sizes (32-pack). Where
   WebGPU runs they float and turn (pack-scene/); elsewhere it is a still of that same scene for
   the chosen pack (shared/packs/, one per pack). */
.order { max-width: 1160px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, .93fr) minmax(0, 1.07fr);
  grid-template-areas: "say pack" "card pack"; column-gap: clamp(28px, 5vw, 72px); align-items: start; text-align: left; }
.order__say { grid-area: say; }
.order h2 { margin: 0 0 clamp(24px, 2.4vw, 34px); max-width: 16ch; }   /* the title alone now (owner, 14 Nov: the line under it removed) */
/* The card (owner, 13 Nov: "remove fluff and unnecessary things that clutter the UX/UI. We need
   harmony and alignment"): three rows built the same way, the row's name on the card's left
   edge and the one thing it tells you on its right edge (the bottles the size fits, the price
   per band, the color's name), with one line of plain tiles under it. Then the price and the
   button, which takes the rest of the row, or the whole of it where the card is narrow. */
.card { grid-area: card; background: var(--raised); border: 1px solid rgba(26,26,26,.14); border-radius: 28px; padding: clamp(18px, 2.2vw, 28px); }
.card__group { border: 0; padding: 0; margin: 0 0 18px; min-width: 0; }
.card__group legend { width: 100%; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 0 0 9px;
  font: 500 .78rem/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.card__note { font: 400 .92rem/1.2 var(--sans); letter-spacing: 0; text-transform: none; white-space: nowrap; color: var(--muted); }
.card__note .fr { font-size: .74em; }
.card__sizes, .card__packs { display: grid; gap: 8px; }
.card__sizes { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.card__packs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.card button { -webkit-appearance: none; appearance: none; border: 0; margin: 0; cursor: pointer; color: var(--ink); }
/* URW Geometric draws its capitals 3px above the middle of the line at this size; the top padding puts them back */
.card__sizes button, .card__packs button { min-height: 52px; padding: .37em 4px 0; border-radius: 12px; background: rgba(26,26,26,.07);
  font: 600 1.05rem/1.1 var(--sans); white-space: nowrap; transition: background .12s, color .12s; }
.card button[aria-pressed="true"] { background: var(--ink); color: var(--warm-white); }
.card button:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.card fieldset[disabled] button { cursor: default; }
.card__colours { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 2px; }
.card__colours button { display: grid; place-items: center; min-height: 44px; padding: 5px; border-radius: 50%; background: none; }
.card__colours button span { display: block; width: 100%; max-width: 30px; aspect-ratio: 1; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(26,26,26,.2); }
.card__colours button[aria-pressed="true"] { background: none; }
.card__colours button[aria-pressed="true"] span { box-shadow: inset 0 0 0 1px rgba(26,26,26,.2), 0 0 0 3px var(--raised), 0 0 0 5px var(--ink); }
.card__buy { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; border-top: 1px solid rgba(26,26,26,.14); padding-top: 18px; margin-top: 2px; }
.card__price { margin: 0; white-space: nowrap; }
.card__price b { font: 900 2.1rem/1 var(--sans); letter-spacing: -.03em; }
.card__buy .btn { flex: 1 1 auto; margin-right: 4px; }   /* to the card's right-hand edge, less its own shadow */
.card .fine { margin-top: 14px; }
.order__pack { grid-area: pack; align-self: center; margin: 0; text-align: center; }
.live--pack { aspect-ratio: 5 / 4; }
.live--pack .live__still { display: block; width: 100%; height: 100%; max-width: none; }
.order__pack figcaption { display: grid; gap: 5px; margin-top: 4px; }
.order__pack figcaption b { font: 600 clamp(1.08rem, 1.5vw, 1.32rem)/1.3 var(--sans); text-wrap: balance; }
/* what the bands are made of: two plain facts about the material, on one quiet line */
.order__made { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 2px 0;
  font: 500 .78rem/1.5 var(--mono); letter-spacing: .04em; color: var(--muted); }
.order__made li + li::before { content: "\00B7"; margin: 0 .8em; }
@media (max-width: 760px) { .buybar.is-on.is-dup { display: none; } }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* the founder's note: the page's skeleton again. His words on the left half, as in the sections
   either side, and the man himself on the right half, where they have their picture. He stands on
   the section's bottom edge the way the hero's bottles stand behind the counter, and the picture
   is a cut-out, so the section's own ground is his background.
   --pw is the picture's width: under half the page, and never so tall that he fills the screen. */
.who { --pw: min(52vw, 760px, calc(var(--svh) * .95)); position: relative; overflow: hidden; }
.note { position: relative; z-index: 1; max-width: 1160px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; text-align: left; }
.note h2 { margin: 0 0 clamp(18px, 2.2vw, 30px); max-width: 12ch; }
.note__pic { position: absolute; z-index: 0; bottom: 0; left: calc(50% + (min(580px, 50% - var(--gutter)) - var(--pw)) / 2); width: var(--pw); height: auto; max-width: none; pointer-events: none; }
.note p { max-width: 34em; font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.note p + p { margin-top: 18px; }
.note .note__by { margin-top: 28px; font: 500 .78rem/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }

/* questions: the five answers are written on five bands, in marker, where anyone can read them
   without opening anything (renders made for this section, tools/render_answers.py: a blank band
   and, over it, its writing alone, which is wiped on when the row comes into view). The same
   answer is in type under each band, in full. */
.ans { list-style: none; margin: clamp(28px, 4vw, 52px) auto 0; padding: 0; max-width: 1160px; display: flex; flex-wrap: wrap; justify-content: center;
  gap: clamp(28px, 3.4vw, 44px) clamp(14px, 1.6vw, 22px); text-align: center; }
/* for someone who did not find their answer on the page (owner, 14 Nov): one line under the answers, the address written out */
.ask { margin: clamp(36px, 4.4vw, 60px) auto 0; text-align: center; font-size: clamp(1.06rem, 1.35vw, 1.22rem); text-wrap: balance; }
.ask a { display: inline-block; padding: 9px 0; font-weight: 600; color: var(--ink); text-underline-offset: 4px; overflow-wrap: anywhere; }
.ans li { flex: 0 1 372px; min-width: 0; display: flex; flex-direction: column; }
.ans h3 { margin: 0; min-height: 0; display: flex; align-items: flex-end; justify-content: center; font: 600 1.04rem/1.35 var(--sans); text-wrap: balance; }
.ans__band { position: relative; display: block; margin: 12px 0 12px; filter: drop-shadow(0 9px 9px rgba(26, 26, 26, .13)); }
.ans__band img { display: block; width: 100%; height: auto; }
.ans__ink { position: absolute; left: 0; top: 0; }
.ans p { margin: 0 auto; max-width: 34ch; font-size: .95rem; line-height: 1.5; color: var(--muted); text-wrap: balance; }
/* the writing goes on from left to right, one band after the next */
.ans.is-waiting .ans__ink { -webkit-clip-path: inset(0 100% 0 0); clip-path: inset(0 100% 0 0); }
.ans.is-on .ans__ink { -webkit-clip-path: inset(0 0 0 0); clip-path: inset(0 0 0 0); transition: clip-path .75s cubic-bezier(.4, 0, .5, 1) calc(var(--i) * .32s), -webkit-clip-path .75s cubic-bezier(.4, 0, .5, 1) calc(var(--i) * .32s); }

/* close: the eight colours fall across the whole section, on both sides of the last words and
   the last button, and never over them: the scene keeps a strip down its middle clear
   (falling/, ?lane, asked for by station.js). A band is only ever cut by the section's own
   edges. On phones there is no room beside the words, so the bands fall in a framed window
   above them. Where the scene cannot run, a still of it stands in (tools/close_stills.py). */
.close { min-height: var(--svh); align-content: center; position: relative; overflow: hidden; background: var(--field); padding: clamp(88px, 11vw, 168px) var(--gutter); }
.close__stage { position: absolute; inset: 0; }
.close__stage .live__frame, .close__stage .live__still { position: absolute; inset: -15%; pointer-events: none; }   /* drawn at 130%, so the bands read large */
.close__stage.is-live .live__frame { pointer-events: none; }
.close__stage .live__still img { display: block; width: 100%; height: 100%; max-width: none; object-fit: cover; }
.close__body { position: relative; z-index: 1; max-width: 620px; margin: 0 auto; }
.close h2 { font-size: clamp(2.7rem, 7vw, 6rem); }
.close .lead { margin: 14px auto 22px; font-size: clamp(1.06rem, 1.35vw, 1.22rem); }
.close .price { margin: 0 0 16px; }
.close .fine { margin-top: 18px; }

@media (min-width: 761px) {
  /* the fit bottle stands on the section's bottom edge, so the section's own padding moves to the words */
  #fit { padding-top: 0; padding-bottom: 0; overflow: hidden; }   /* the stage may be wider than its half of the grid; nothing of it may widen the page */
  .bench { min-height: var(--svh); }
  .bench__text { padding-top: var(--pad-y); padding-bottom: var(--pad-y); }
  .gauge { align-self: end; }
}
@media (max-width: 760px) {
  :root { --top: 60px; }
  .top { padding-top: 10px; padding-bottom: 6px; }
  .hero h1 { margin-top: 4px; font-size: min(2.75rem, 12.4vw); }   /* in capitals the headline still takes two lines on the narrowest phone */
  .hero .lead { line-height: 1.4; margin-top: 10px; }
  /* three whole labels across a phone: the screen's width sets the size, so the side bottles are a little smaller to let the front one grow */
  .turn { --sF: .4; --sB: .34; --gap: 2.2vw; --edge: 4px; --room: 370px; --least: 150px; margin-top: 8px; }
  .counter { padding-top: 10px; }
  /* the size line on a phone: "fits 2 1/8 - 2 3/4 wide" beside the four buttons, and on the smallest phones the measurement alone */
  .till__size { gap: 12px; }
  .pick--seg .pick__row { grid-template-columns: repeat(4, 44px); }
  .pick--seg label > span { font-size: .92rem; }
  .fits { font-size: 1rem; }
  .fits__b { display: none; }
  @media (max-width: 380px) { .till__size { gap: 10px; } }
  @media (max-width: 350px) { .till__size { gap: 6px; } .fits { font-size: .9rem; } .fits__a { display: none; } .fits i { margin: 0 .06em; } }   /* the smallest phones */
  .till .btn { min-height: 54px; margin-top: 12px; padding: 0 12px; font-size: .82rem; letter-spacing: .09em; }
  .btn__price { font-size: 1.2rem; }
  @media (max-width: 350px) { .till .btn { font-size: .76rem; letter-spacing: .06em; } .btn__price { font-size: 1.08rem; } }
  .counter .fine { margin-top: 12px; }
  /* a very short phone: the button stays on the first screen */
  @media (max-height: 600px) { .turn { --room: 384px; } }
  /* the words, then the picture, then the controls */
  .bench { display: flex; flex-direction: column; text-align: center; }
  .bench__text { display: contents; }
  #fit h2 { order: 1; margin: 0 auto; }
  #fit .lead { order: 2; margin: 18px auto 0; }
  .gauge { order: 3; max-width: 460px; margin: 26px auto 0; }
  .gauge__stage { height: 250px; aspect-ratio: auto; min-height: 0; max-height: none; }
  /* the controls follow the bottle here, so its foot fades into the page */
  .gauge__b { -webkit-mask-image: linear-gradient(to top, transparent 0, #000 34px); mask-image: linear-gradient(to top, transparent 0, #000 34px); }
  .measure { order: 4; width: 100%; max-width: 460px; margin: 16px auto 0; text-align: left; }
  .measure output { font-size: 2.4rem; }
  .buy { margin-top: 22px; }
  /* the buy buttons say more now ("Buy now on Amazon.com" and the flag): smaller type on a phone, and room made for them */
  .btn { padding: 0 16px; font-size: .74rem; letter-spacing: .05em; }
  /* the bar that follows a phone down the page is the hero's button again: the price, the words, the flag */
  .buybar .btn { flex: 1 1 auto; }
  .buybar .btn__price { display: inline; font-size: 1.15rem; }
  /* words, then the bottle on the section's bottom edge. The bottle keeps its size; a taller screen shows more of it, up to the cap */
  .tape { display: flex; flex-direction: column; text-align: center; }
  .tape__text { margin-top: auto; padding: 60px var(--gutter) 0; }
  .tape h2, .pit h2, .order h2 { max-width: none; }   /* capitals are wider: the screen sets the line, and the browser balances it */
  .tape h2, .tape .lead, .tape .answer { margin-left: auto; margin-right: auto; }
  /* the picture stands on the section's bottom edge; a short screen cuts the nozzle off softly, so the tape is on screen with the headline */
  .tape__pic { align-self: flex-start; flex: 1 0 77.2vw; aspect-ratio: auto; width: 118%; max-height: 109.2vw; margin: 18px 0 0 -7%;
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%); mask-image: linear-gradient(180deg, transparent, #000 12%); }
  .tape__frame { left: -8.06%; top: auto; bottom: 0; }
  /* the same again: words, then the same bottle on the bottom edge, now with its band */
  .write { display: flex; flex-direction: column; text-align: center; }
  .write__head, .write__body { padding-left: var(--gutter); padding-right: var(--gutter); max-width: none; }
  .write__head { margin-top: auto; padding-top: 60px; }
  .write__body { padding-bottom: 0; }
  .write .lead, .write .fine { margin-left: auto; margin-right: auto; }
  .write__pic { order: 3; align-self: flex-start; flex: 1 0 77.2vw; aspect-ratio: auto; width: 118%; max-height: 109.2vw; margin: 18px 0 0 -7%;
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%); mask-image: linear-gradient(180deg, transparent, #000 12%); }
  .write__frame { left: -8.06%; top: auto; bottom: 0; }
  .pit { display: flex; flex-direction: column; text-align: center; }
  /* the words, then the bands, then the card */
  .order { grid-template-columns: minmax(0, 1fr); grid-template-areas: "say" "pack" "card"; text-align: center; max-width: 520px; }
  .order h2 { margin: 0 auto 14px; }
  .order__pack { margin: -6px -8px 24px; }
  .order__made { flex-direction: column; align-items: center; }   /* one fact to a line, so no separator starts a line */
  .order__made li + li::before { content: none; }
  .card { text-align: left; }
  .card__colours { gap: 0; }
  .card__buy { gap: 12px; }
  .card__buy .btn { flex: 1 1 100%; padding: 0 14px; }   /* the price, then the button the width of the card */
  .card__price b { font-size: 1.8rem; }
  /* one answer to a row: the band, and its question and answer beside it */
  /* a phone: the note, then the man at the end of it, still standing on the section's bottom edge */
  .who { --pw: min(100vw - 2 * var(--gutter), 400px); padding-bottom: 0; display: flex; flex-direction: column; }   /* a column, so he is pushed down to the bottom edge when the screen is taller than the note */
  .note { display: block; width: 100%; max-width: 520px; margin: auto auto 30px; }
  .note h2 { max-width: 12ch; margin: 0 auto 22px; text-align: center; }
  .note__pic { position: static; display: block; flex: none; margin: 0 auto; }
  .ans { display: grid; gap: 22px; text-align: left; max-width: 520px; }
  .ans li { display: grid; grid-template-columns: 46% minmax(0, 1fr); grid-template-areas: "band q" "band a"; column-gap: 14px; align-items: center; }
  .ans h3 { grid-area: q; min-height: 0; justify-content: flex-start; align-self: end; font-size: 1rem; }
  .ans__band { grid-area: band; margin: 0 0 0 -6px; }
  .ans p { grid-area: a; align-self: start; margin: 4px 0 0; max-width: none; font-size: .9rem; text-wrap: pretty; }
  .close { display: flex; flex-direction: column; padding: 40px 0 64px; }
  /* no frame round the falling bands (owner, 14 Nov): the stage is as wide as the screen, on the
     section's own ground, and its top and bottom fade out, so the bands thin away before the words */
  .close { padding-top: 0; }
  .close__stage { position: relative; inset: auto; flex: 1 0 260px; margin: 0 0 8px; overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 16%, #000 66%, transparent 100%); mask-image: linear-gradient(to bottom, transparent 0, #000 16%, #000 66%, transparent 100%); }
  .close__stage .live__frame, .close__stage .live__still { inset: 0 auto auto -50%; width: 200%; height: 200%; }   /* drawn at twice the window */
  .close__body { max-width: none; padding: 4px var(--gutter) 0; }
  .pit__text { margin-top: auto; padding: 64px var(--gutter) 0; }
  .pit h2, .pit .lead { margin-left: auto; margin-right: auto; }
  /* The picture stands on the section's bottom edge and takes the height the words leave: at
     least as much of the rack above the band as before (101vw), and on a taller screen more, up
     to all there is (125.2vw). The view is the whole picture; its box cuts it from the top. */
  .pit__pic { align-self: stretch; position: relative; flex: 1 0 101vw; max-height: 125.2vw; margin-top: 8px; overflow: hidden; container-type: size; }
  .wash__view { --up: .31; --cut: .12; position: absolute; left: 0; bottom: 0; width: 128%; max-width: none; margin: 0 0 0 -11.4%; }   /* the band in the middle of the screen */
  /* the words are above the picture here, so it fades upward, from wherever the box cuts it (--d below the rack's top) */
  .wash__rack { --d: calc(125.2vw - 100cqh);
    -webkit-mask-image: linear-gradient(to bottom, transparent calc(var(--d) - .8vw), rgba(0,0,0,.08) calc(var(--d) + 4.8vw), rgba(0,0,0,.34) calc(var(--d) + 11.7vw), rgba(0,0,0,.74) calc(var(--d) + 19.9vw), #000 calc(var(--d) + 28.2vw));
    mask-image: linear-gradient(to bottom, transparent calc(var(--d) - .8vw), rgba(0,0,0,.08) calc(var(--d) + 4.8vw), rgba(0,0,0,.34) calc(var(--d) + 11.7vw), rgba(0,0,0,.74) calc(var(--d) + 19.9vw), #000 calc(var(--d) + 28.2vw)); }
  .sizes li { font-size: .6rem; }
  .sizes li b { font-size: .95rem; }
  /* Room to breathe on a taller phone (owner, 14 Nov: "if we have the screen real estate, let's
     use it"). --air is nothing on a 640 px screen and grows to 20 px by about 810 px; the gaps
     between a section's parts each take a share of it, so spare height is spread through the
     section and no longer left in one lump above the headline or under the small print. */
  :root { --air: clamp(0px, calc((var(--svh) - 640px) * .12), 20px); }
  .hero .lead { margin-top: calc(10px + var(--air) * .5); }
  .turn { margin-top: calc(8px + var(--air) * 1.5); }
  .counter { padding-top: calc(10px + var(--air) * 1.2); }
  .till .btn { margin-top: calc(12px + var(--air)); }
  .counter .fine { margin-top: calc(12px + var(--air) * .6); }
  /* words over a picture on the bottom edge: once the picture is as tall as it gets, what is
     left is shared above the words and between the words and the picture */
  .tape__text, .pit__text { margin-bottom: auto; }
  .write__body { margin-bottom: auto; }
  .tape .lead, .write .lead, .pit .lead { margin-top: calc(20px + var(--air) * .4); }
  .answer, .write .fine { margin-top: calc(14px + var(--air) * .3); }
  #fit .lead { margin-top: calc(18px + var(--air) * .4); }
  .gauge { margin-top: calc(26px + var(--air) * .6); }
  .measure { margin-top: calc(16px + var(--air) * .5); }
  .buy { margin-top: calc(22px + var(--air) * .5); }
  .ans { margin-top: calc(28px + var(--air) * .6); gap: calc(22px + var(--air)); }
}
