/* =====================================================================
   the faucet — the whole visual identity is the :root block below.

   TWO FACES, ONE JOB EACH, AND THEY DO NOT SWAP.
     --mono   figures, labels, addresses, nav, buttons. Furniture.
     --serif  every sentence. Prose is NEVER set in the mono.

   That split is not decoration. A page that sets its prose in a
   monospace face is a typewriter article however good the writing is,
   and this project has thrown six of those away.

   ONE ACCENT, AND IT IS LIT. --flame is the colour of the thing burning
   on the front page, so it is allowed to be the brightest object on
   screen. Nothing else on the page is allowed to be.

   ROUTE B. index.html is the object and almost nothing else. The three
   interior pages carry the mass. That is deliberate: a front page that
   explains is a product page.
   ===================================================================== */

:root {
  --ground:   #06080a;
  --ground-2: #0a0d11;
  --panel:    #0e1319;
  --panel-2:  #0b1015;
  --line:     #1c252d;
  --line-2:   #141b21;

  --ink:   #e2eaf1;
  --mute:  #8a99a6;
  --faint: #57646f;

  --flame:      #ff6a18;
  --flame-hi:   #ffbe6a;
  --flame-core: #fff3d6;
  --flame-wash: rgba(255, 106, 24, 0.10);

  --chrome: #9fb0be;
  --good:   #64d6a4;
  --bad:    #ef6b4d;

  --mono:  "Spline Sans Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --serif: "Newsreader", Georgia, "Times New Roman", serif;

  --pad:  clamp(1.1rem, 4vw, 3rem);
  --wrap: 900px;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

::selection { background: var(--flame); color: #140800; }

/* =====================================================================
   THE FRONT PAGE — layers
   ===================================================================== */

body.is-front { overflow: hidden; }

.bloom, .grain {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* THE STAGE. One fixed, centred column holding the object and the words,
   so the spare height in the viewport is shared between the top and the
   bottom instead of collecting entirely above the tap. */
.stage {
  position: fixed;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1.4rem, 4.5vh, 3.2rem);
  /* the top pad clears the topbar; the bottom pad is smaller because the
     eye wants a little more air above an object than below it */
  padding: clamp(3.5rem, 8vh, 5.5rem) var(--pad) clamp(1.5rem, 4vh, 2.75rem);
}

/* NO BLEND MODE. assets/tap.png carries a real alpha channel, cut by
   brand/cut-matte.mjs with a flood fill from the frame's edge, so the
   background is genuinely transparent and the chrome's own enclosed dark
   bands are left fully opaque.

   It used to be `mix-blend-mode: screen` over a black background. That
   works, but a blend only reaches as far as the nearest isolating
   stacking context, and `position: fixed` creates one. Every restructure
   of the hero put a new fixed ancestor between the image and the page,
   the blend stopped there, and the PNG's black background rendered as a
   visible dark rectangle. It happened twice. An alpha channel cannot be
   broken by a layout change. */
.rig { min-height: 0; pointer-events: none; }
.bloom { z-index: 3; mix-blend-mode: screen; opacity: 0.5; }
.grain { z-index: 4; }

/* The rig sits on the lower half so the flame has the whole upper frame
   to climb into. Below 640px the tap shrinks rather than crops, because
   a cropped handwheel reads as a mistake. */
/* THE STACK. Two copies of the same render, the second one warm.
   The source has generous black margins around the tap, and because black
   screens away to nothing those margins are invisible — which means the
   element is meaningfully wider than the object inside it. The tap spans
   59% of the image's width, so a 900px element draws a 530px tap. Size
   this against that, not against what looks right as a number. */
.rig-img {
  display: block;
  /* height is the binding constraint, so it is capped against vh first;
     `min-height: 0` on .rig lets flex shrink this rather than overflow */
  width: min(42vh, 27vw, 340px);
  max-height: 100%;
  height: auto;
  object-fit: contain;
}

/* THE BACKDROP HAS NO CENTRE.
   This was a pair of radial gradients centred behind the tap. A soft oval
   of warm light on a black ground still reads as an oval: you see the edge
   wherever the falloff lands, and pushing the falloff further out only
   moves the edge to the corners. Measured on the banner, which has the
   same construct: a 0.48 luminance step where the glow ran out, which the
   eye reads as a boundary, and sizing it off the diagonal made it 6.28.

   A straight top-to-bottom wash has no centre, so there is no shape to see
   the edge of. The tap carries its own light in the render. */
.bloom {
  background: linear-gradient(180deg, #0b0d10 0%, #08090c 58%, #06080a 100%);
  mix-blend-mode: normal;
  opacity: 1;
  z-index: 1;
}

/* Decay chrome as an overlay on an otherwise plain document. It goes
   OVER the flat page and never becomes the layout. */
.grain {
  opacity: 0.34;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* ---- furniture: tiny, lowercase, at the edges ---------------------- */

.topbar {
  position: fixed;
  z-index: 10;
  inset: 0 0 auto 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: clamp(0.9rem, 2.4vw, 1.5rem) var(--pad);
  font-family: var(--mono);
  /* it has to fit on one line at 320px: "the faucet" plus four nouns is
     about 44 characters, and at 12.5px that wraps and pushes the mark onto
     two lines. Scale it with the viewport and let the nav shrink first. */
  font-size: clamp(10px, 2.6vw, 12.5px);
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.mark { flex: none; }

.mark {
  color: var(--ink);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.mark::before {
  content: "";
  display: inline-block;
  width: 7px; height: 7px;
  margin-right: 0.55em;
  border-radius: 50%;
  background: var(--flame);
  box-shadow: 0 0 9px var(--flame), 0 0 20px rgba(255, 106, 24, 0.55);
  vertical-align: 0.05em;
}

.nouns { display: flex; gap: clamp(0.55rem, 2.2vw, 1.7rem); min-width: 0; }
.nouns a { color: var(--mute); transition: color 0.18s; }
.nouns a:hover, .nouns a.is-here { color: var(--flame-hi); }

/* ---- the front page's own words: there are eleven of them ---------- */

.front {
  flex: none;
  display: grid;
  justify-items: center;
  gap: clamp(0.7rem, 2vw, 1.15rem);
  text-align: center;
}

.koan {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.15rem, 3.4vw, 1.72rem);
  line-height: 1.3;
  color: var(--ink);
  text-shadow: 0 0 26px rgba(255, 130, 50, 0.35), 0 2px 18px rgba(0, 0, 0, 0.9);
}

/* A GRID WITH A COLUMN COUNT THAT DIVIDES THE CELLS, not auto-fit.
   Four cells under auto-fit wrap to 3+1 or 2+2 depending on the width, and
   the leftover slots in the last row read as stray empty boxes against the
   1px gap. Two explicit breakpoints (2 columns, then 4) always divide
   exactly, and the separators live on the CELLS as box-shadows over a
   panel-coloured container, so even if a cell were ever missing there
   would be nothing to see. */
.readout {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: min(100%, 30rem);
  background: var(--line-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  overflow: hidden;
  font-family: var(--mono);
  backdrop-filter: blur(7px);
}
@media (min-width: 560px) {
  .readout { grid-template-columns: repeat(4, minmax(0, 1fr)); width: auto; }
}
.cell {
  display: grid;
  gap: 0.12rem;
  padding: 0.5rem clamp(0.7rem, 2.4vw, 1.35rem);
  background: rgba(8, 11, 14, 0.82);
  box-shadow: 1px 0 0 var(--line-2), 0 1px 0 var(--line-2);
  min-width: 0;
}
.cell .k {
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cell .v {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* THE HEADLINE NUMBER IS MARKET CAP. Not price. Nobody reads price on
   these. */
.cell-lead .v {
  font-size: clamp(1.05rem, 3.6vw, 1.6rem);
  font-weight: 700;
  color: var(--flame-hi);
  text-shadow: 0 0 18px rgba(255, 150, 60, 0.45);
  line-height: 1.15;
}

/* ---- the CA, at the top of the world and never mentioned again ----- */

.ca {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.42rem 0.75rem;
  background: rgba(8, 11, 14, 0.7);
  border: 1px solid var(--line);
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 11.5px;
  cursor: pointer;
  backdrop-filter: blur(7px);
  transition: border-color 0.18s, background 0.18s;
}
.ca:hover { border-color: var(--flame); background: rgba(20, 11, 4, 0.8); }
.ca-k { color: var(--faint); letter-spacing: 0.14em; text-transform: uppercase; font-size: 9.5px; }
.ca-v { color: var(--mute); }
.ca-copy { color: var(--flame); letter-spacing: 0.08em; }
.ca.is-copied .ca-copy { color: var(--good); }

.state {
  margin: 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--faint);
  max-width: 46ch;
}

/* the front page has no scroll and no room to lose. Below 420px tall the
   readout is the first thing to go: the object is the page. */
/* short or narrow: the object gives way before the numbers do, because a
   readout that has been pushed off the bottom is worse than a small tap. */
/* THE TAP MUST CLEAR THE FIXED BOTTOM BLOCK, and vh alone does not do it.
   .front is a fixed panel whose HEIGHT is set by its contents (roughly
   210px, and it does not shrink), while the rig's clearance was expressed
   purely in vh. Below about 700px tall the two collide: measured at
   812x375 the readout covered the whole tap except the handwheel, and at
   320x568 the koan ran through the spout bend with the readout's top edge
   one pixel above the lip, hiding the pilot flame completely.
   The fix is a floor in px, not a smaller percentage: min() against a
   pixel term means the clearance can never fall below what .front
   actually occupies, whatever the viewport does. */
@media (max-height: 760px) {
  .rig-img { width: min(34vh, 26vw, 340px); }
}
@media (max-height: 620px) {
  .koan { display: none; }
  .rig-img { width: min(29vh, 25vw, 340px); }
}
@media (max-width: 480px) {
  .rig-img { width: min(32vh, 60vw, 340px); }
  .front { gap: 0.55rem; }
}

/* =====================================================================
   THE INTERIOR PAGES — mains, ledger, small print
   ===================================================================== */

body.is-doc {
  overflow-x: hidden;
  overflow-y: auto;
  background:
    radial-gradient(90vmax 60vmax at 50% -20%, rgba(255, 106, 24, 0.055), transparent 70%),
    var(--ground);
}
body.is-doc .topbar {
  position: sticky;
  background: linear-gradient(var(--ground) 62%, transparent);
}

.doc { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad) 7rem; }

/* ---- the page's one big thing ------------------------------------- */
.doc-hero {
  position: relative;
  padding: clamp(2.5rem, 9vw, 5rem) 0 clamp(1.6rem, 4vw, 2.6rem);
  border-bottom: 1px solid var(--line);
}
.doc-hero h1 {
  margin: 0.35rem 0 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.2rem, 7vw, 3.6rem);
  line-height: 1.06;
  letter-spacing: -0.015em;
}
.doc-hero .eyebrow {
  margin: 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--flame);
}
.doc-hero .lede {
  margin: 1.1rem 0 0;
  max-width: 62ch;
  font-size: 1.14rem;
  color: var(--mute);
}

/* the diagram band. This is the "one thing bigger than a paragraph" the
   interior pages are required to have — without it they are printouts. */
.band {
  margin: clamp(1.8rem, 5vw, 3rem) 0;
  padding: clamp(1.2rem, 4vw, 2.2rem) 0;
  background:
    radial-gradient(70% 120% at 50% 118%, rgba(255, 106, 24, 0.14), transparent 66%),
    linear-gradient(var(--panel-2), var(--ground-2));
  border: 1px solid var(--line);
  border-radius: 5px;
  overflow: hidden;
}
/* SCROLL, DO NOT SHRINK. The schematic is a 1000x290 viewBox at
   width:100%, so on a phone it scaled to 283px wide and its 11.5px labels
   rendered at 3.2px: an illegible smudge rather than a diagram. Give it a
   floor and let the container scroll, which is what .tbl-wrap on the same
   page already does. */
.band { overflow-x: auto; }
.band svg { display: block; width: 100%; min-width: 620px; height: auto; }
.band-cap {
  margin: 0.9rem clamp(1rem, 3vw, 1.8rem) 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  color: var(--faint);
}

section.slab { padding: clamp(2rem, 6vw, 3.4rem) 0 0; }
section.slab > h2 {
  margin: 0 0 0.2rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 4.2vw, 2.1rem);
  letter-spacing: -0.01em;
}
section.slab > .sub {
  margin: 0 0 1.6rem;
  max-width: 60ch;
  color: var(--mute);
}
.doc p { max-width: 68ch; }
.doc p + p { margin-top: 1rem; }

/* ---- the numbered rule list, which IS the mechanism ---------------- */
.rules { list-style: none; margin: 0; padding: 0; counter-reset: r; }
.rules li {
  counter-increment: r;
  display: grid;
  grid-template-columns: 3.1rem 1fr;
  gap: 0 1rem;
  padding: 1.05rem 0;
  border-top: 1px solid var(--line-2);
}
/* The number owns column one for BOTH rows. Without the explicit
   placement the h3 takes column two, the p wraps round to column one, and
   every paragraph renders one word per line inside a 3.1rem gutter. */
.rules li::before {
  content: "0" counter(r);
  grid-column: 1;
  grid-row: 1 / span 2;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--flame);
  padding-top: 0.42rem;
}
.rules li > * { grid-column: 2; }
.rules h3 {
  margin: 0 0 0.2rem;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}
.rules p { margin: 0; color: var(--mute); }

/* ---- figures and equations ---------------------------------------- */
.eq {
  margin: 1.5rem 0;
  padding: 1.05rem 1.2rem;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--flame);
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 0.9rem;
  line-height: 1.85;
  color: var(--ink);
  overflow-x: auto;
  white-space: pre;
}
.eq b { color: var(--flame-hi); font-weight: 500; }
.eq-note {
  margin: -0.9rem 0 1.5rem;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--faint);
}

/* ---- the stat grid. Separators on the CELLS over a panel-coloured
   container, so leftover cells in a ragged last row are invisible at
   every width instead of reading as a stray empty block. ------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.stat {
  padding: 0.85rem 1rem;
  box-shadow: 1px 0 0 var(--line-2), 0 1px 0 var(--line-2);
}
.stat .k {
  display: block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.25rem;
}
.stat .v {
  font-family: var(--mono);
  font-size: 1.02rem;
  font-variant-numeric: tabular-nums;
}
.stat.is-lead .v { color: var(--flame-hi); font-size: 1.35rem; font-weight: 700; }
.stat .est { color: var(--faint); font-size: 9.5px; letter-spacing: 0.1em; }

/* ---- tables -------------------------------------------------------- */
.tbl-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 4px; }
table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12.5px; }
thead th {
  text-align: left;
  padding: 0.6rem 0.85rem;
  background: var(--panel);
  color: var(--faint);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  white-space: nowrap;
}
tbody td {
  padding: 0.55rem 0.85rem;
  border-top: 1px solid var(--line-2);
  color: var(--mute);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
tbody tr:hover td { background: rgba(255, 106, 24, 0.045); }
td.num { text-align: right; }
td.hot { color: var(--flame-hi); }
td.sig a { color: var(--faint); border-bottom: 1px solid var(--line); }
td.sig a:hover { color: var(--flame); border-color: var(--flame); }
.kind {
  display: inline-block;
  padding: 0.05rem 0.42rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}
.kind.k-claim { color: var(--chrome); border-color: #2b3a46; }
.kind.k-lot   { color: var(--flame); border-color: #4a2a12; background: var(--flame-wash); }
.kind.k-fail  { color: var(--bad); border-color: #4a231a; }

/* ---- notes, warnings ---------------------------------------------- */
.note {
  margin: 1.5rem 0;
  padding: 0.95rem 1.15rem;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--chrome);
  border-radius: 3px;
  color: var(--mute);
  font-size: 0.96rem;
}
.note.is-hot { border-left-color: var(--flame); }
.note.is-bad { border-left-color: var(--bad); }
.note strong { color: var(--ink); font-weight: 500; }

.empty {
  /* `tbody td` sets white-space: nowrap for the columnar figures, and this
     rule inherited it, so the full-width "the engine is not connected"
     sentence laid out on one unbroken line and forced the table to 864px.
     It was cut mid-word at every viewport. */
  white-space: normal;
  padding: 2.6rem 1rem;
  text-align: center;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--faint);
}

/* ---- links out ----------------------------------------------------- */
.doc a.link { color: var(--flame-hi); border-bottom: 1px solid rgba(255, 190, 106, 0.35); }
.doc a.link:hover { border-bottom-color: var(--flame-hi); }

.foot {
  margin-top: 4rem;
  padding-top: 1.3rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--faint);
}
.foot a { color: var(--mute); }
.foot a:hover { color: var(--flame-hi); }

/* ---- the live pip -------------------------------------------------- */
.pip {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
}
.pip::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--faint);
}
.pip.is-live { color: var(--good); }
.pip.is-live::before { background: var(--good); box-shadow: 0 0 8px var(--good); }
.pip.is-alarm { color: var(--bad); }
.pip.is-alarm::before { background: var(--bad); box-shadow: 0 0 8px var(--bad); }
