/* TerraScope, the site.
   =========================================================================
   The page is not one green field. It runs as bands, the way a printed
   report does: a dark cinematic hero, then cream and white for everything
   that has to be read, then deep forest again for the closing and the
   footer. Green is the brand, not the background.

   Display type is Fraunces, a serif with real weight and an optical axis —
   the editorial voice. Archivo carries the interface. JetBrains Mono is
   reserved for measured quantities, because every number here is one.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700&family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700&family=JetBrains+Mono:wght@300;400;500&display=swap');

:root{
  /* light bands */
  --canvas:#f3f1ea;
  --canvas-warm:#e9e5da;
  --surface:#ffffff;
  --ink:#15241c;
  --ink-soft:#3c4a41;    /* body on cream: was #4c5c51, too light to read */
  --ink-faint:#5d6b62;   /* captions: was #7d8a80, under 4.5:1 on cream */
  --rule:rgba(21,36,28,.14);
  --rule-soft:rgba(21,36,28,.08);

  /* dark bands */
  --forest:#143024;
  --forest-deep:#0c1f18;
  --bone:#f4f6ef;
  --bone-soft:rgba(244,246,239,.86);
  --bone-faint:rgba(244,246,239,.68);
  --rule-dark:rgba(244,246,239,.16);

  /* brand */
  --brand:#1f6b47;
  --brand-dark:#144e33;
  --moss:#a9cb87;
  --gold:#eccd7d;
  /* A lighter bottle green for header bands: --forest reads as black at small
     sizes, which is what made the table headings look like a bar of ink. */
  --bottle:#1d4a35;
  /* One warm tone, reserved for the loss/warning state so that green never
     has to mean both "good" and "bad" on the same page. */
  --amber:#b4761f;
  --amber-wash:rgba(180,118,31,.09);

  --sans:'Archivo',-apple-system,BlinkMacSystemFont,sans-serif;
  --serif:'Fraunces','Iowan Old Style',Georgia,serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;
  --gutter:clamp(20px,5vw,72px);
  /* One vertical rhythm for the whole site. Blocks were previously spaced by
     whatever each component happened to declare, which is why headings and
     the content under them sometimes read as one run-on column. */
  --flow-s:clamp(14px,1.7vh,22px);
  --flow-head:clamp(17px,2.3vh,29px);   /* under a display heading */
  --flow-m:clamp(34px,4.6vh,58px);
  --flow-l:clamp(56px,7.4vh,92px);
  --measure:1240px;
  --ease:cubic-bezier(.16,1,.3,1);

  /* what the nav writes on; each band sets its own */
  --nav-ink:var(--bone);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--canvas);color:var(--ink);font-family:var(--sans);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:clip}
a{color:inherit;text-decoration:none}
.wrap{max-width:var(--measure);margin:0 auto;padding:0 var(--gutter)}

::selection{background:var(--brand);color:#fff}
:root{accent-color:var(--brand);caret-color:var(--brand)}
::-webkit-scrollbar{width:12px;height:12px}
::-webkit-scrollbar-track{background:var(--canvas-warm)}
::-webkit-scrollbar-thumb{background:#b9c2b4;border:3px solid var(--canvas-warm);border-radius:99px}
::-webkit-scrollbar-thumb:hover{background:var(--brand)}
:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:3px}
:focus:not(:focus-visible){outline:none}

/* ================================================================ type === */
.display{font-family:var(--serif);font-weight:600;font-size:clamp(2.7rem,6.2vw,5.2rem);
  line-height:.98;letter-spacing:-.028em;margin:0 0 var(--flow-head);text-wrap:balance}
h2.h{font-family:var(--serif);font-weight:600;font-size:clamp(1.95rem,4vw,3.25rem);
  line-height:1.06;letter-spacing:-.024em;margin:0 0 var(--flow-head);max-width:20ch;
  text-wrap:balance}
h3.h3{font-family:var(--sans);font-size:1.1rem;font-weight:600;letter-spacing:-.014em;
  line-height:1.3;margin:0 0 .7rem}
p.lede{font-size:clamp(1.02rem,1.15vw,1.16rem);line-height:1.62;max-width:60ch;margin:0;
  color:var(--ink-soft);text-wrap:pretty}
/* A lede carries no margin of its own, so that a single one sits flush under
   its heading. Two in a row are two paragraphs, and need the gap. */
p.lede + p.lede{margin-top:var(--flow-s)}
p.note{font-size:.88rem;line-height:1.6;color:var(--ink-faint);margin:var(--flow-s) 0 0}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
em.stress{font-style:normal;font-family:var(--serif);font-weight:600;color:var(--brand)}

/* a dark band inverts the whole reading palette */
.dark{background:var(--forest);color:var(--bone);--nav-ink:var(--bone)}
.dark .lede,.dark p{color:var(--bone-soft)}
.dark .note{color:var(--bone-faint)}
.dark em.stress{color:var(--moss)}

/* ================================================================= nav === */
/* Over the hero the bar is glass with nothing behind it: the footage runs
   straight through. The moment the page scrolls it takes the cream of the
   band below and flips its own ink to match. */
.nav{position:fixed;top:0;left:0;right:0;z-index:100;
  display:flex;align-items:center;justify-content:space-between;gap:1.6rem;
  padding:0 var(--gutter);height:82px;color:var(--nav-ink);
  background:transparent;border-bottom:1px solid transparent;
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
  transition:height .35s var(--ease),background .35s ease,color .35s ease,
             border-color .35s ease,backdrop-filter .35s ease}
.nav.tight{height:66px;color:var(--ink);
  background:rgba(243,241,234,.78);
  backdrop-filter:blur(22px) saturate(180%);-webkit-backdrop-filter:blur(22px) saturate(180%);
  border-bottom-color:var(--rule)}
/* pages with no hero behind the bar start solid */
body.lit .nav{color:var(--ink);background:rgba(243,241,234,.78);
  backdrop-filter:blur(22px) saturate(180%);-webkit-backdrop-filter:blur(22px) saturate(180%);
  border-bottom-color:var(--rule)}
.nav-prog{position:absolute;left:0;bottom:-1px;height:2px;width:100%;
  transform:scaleX(var(--sp,0));transform-origin:left;background:var(--brand);
  transition:transform .3s var(--ease);opacity:0}
.nav.tight .nav-prog,body.lit .nav-prog{opacity:1}

.brand{display:inline-flex;align-items:center;gap:.6rem;font-family:var(--serif);
  font-size:1.1rem;font-weight:600;letter-spacing:-.02em;position:relative;z-index:2}
.brand .mark{width:28px;height:22px;overflow:visible;flex:none}
.brand .mark path{fill:none;stroke:currentColor;stroke-width:1.3;stroke-linecap:round;
  opacity:.55;transition:opacity .3s ease}
.brand .mark .pin{fill:var(--moss);stroke:none;transition:transform .5s var(--ease)}
.nav.tight .brand .mark .pin,body.lit .brand .mark .pin{fill:var(--brand)}
.brand:hover .mark path{opacity:1}
.brand:hover .mark .pin{transform:translateY(-2px)}

.nav-links{position:relative;display:flex;align-items:center;gap:.15rem;z-index:2}
.nav-links a{position:relative;z-index:2;font-size:1.02rem;font-weight:500;
  padding:.5rem .95rem;border-radius:99px;opacity:.74;
  transition:opacity .2s ease,color .2s ease}
.nav-links a:hover{opacity:1}
.nav-links a.here{opacity:1;font-weight:600}
.nav-pill{position:absolute;z-index:1;top:50%;left:var(--ix,0);width:var(--iw,0);
  height:2.3rem;margin-top:-1.15rem;border-radius:99px;opacity:0;
  background:currentColor;transition:left .42s var(--ease),width .42s var(--ease),
  opacity .25s ease}
.nav-links:hover .nav-pill{opacity:.1}

.nav-right{display:flex;align-items:center;gap:1.1rem;position:relative;z-index:2}
.readout{display:none;align-items:baseline;gap:.5rem;font-size:.84rem}
.readout em{font-style:normal;opacity:.62}
.readout b{font-family:var(--mono);font-weight:500;font-variant-numeric:tabular-nums}
@media(min-width:1120px){.readout{display:inline-flex}}

.btn{display:inline-block;font-family:var(--sans);font-size:.88rem;font-weight:600;
  padding:.72rem 1.35rem;border-radius:99px;cursor:pointer;border:1px solid transparent;
  transition:background .2s ease,transform .12s ease,border-color .2s ease,
             color .2s ease,box-shadow .2s ease;white-space:nowrap}
/* Deep bottle green rather than the mid brand green: this is the one button
   on the page that asks for a click, and at this depth it reads as the darkest
   thing in the navbar instead of competing with the footage behind it. */
.btn-primary{background:var(--bottle);color:#fff;border-color:var(--bottle);
  box-shadow:0 1px 2px rgba(20,48,36,.2),0 8px 20px -8px rgba(20,48,36,.45)}
.btn-primary:hover{background:var(--forest);border-color:var(--forest);
  box-shadow:0 2px 4px rgba(20,48,36,.24),0 14px 28px -10px rgba(20,48,36,.5)}
/* One primary button, one look, wherever it sits. It used to pick up a pale
   ring and a deep shadow over the footage, which read as a different, glowing
   button rather than the same one on a darker ground. */
.btn-ghost{border-color:currentColor;opacity:.75;background:transparent}
.btn-ghost:hover{opacity:1;background:rgba(127,127,127,.09)}
.btn:active{transform:translateY(1px)}
.btn:disabled{opacity:.4;cursor:not-allowed}

@media(max-width:900px){
  .nav{height:64px;gap:.7rem}.nav.tight{height:58px}
  .nav-links{min-width:0;overflow-x:auto;scrollbar-width:none}
  .nav-links::-webkit-scrollbar{display:none}
  .nav-links a{padding:.45rem .6rem;font-size:.95rem}
  .nav-pill{display:none}
  .brand{font-size:1.05rem}
  .nav-right .btn{padding:.6rem 1rem;font-size:.86rem}
}
@media(max-width:620px){.brand span{display:none}.nav-right .btn{display:none}}

/* ============================================================ sections === */
.page{padding-top:82px}
body.lit{--nav-ink:var(--ink)}
@media(max-width:900px){.page{padding-top:64px}}
/* Space is doing a job or it is waste. Sections get generous air between
   ideas, but the first block under the bar does not need a second full
   section's worth on top of the bar's own height, and the last block before
   the footer does not need to trail off. */
section{padding:clamp(64px,8.5vh,116px) 0}
section + section{padding-top:clamp(72px,9.5vh,128px)}
body.lit main > section:first-child{padding-top:clamp(40px,5vh,64px)}
main > section:last-of-type{padding-bottom:clamp(72px,9vh,120px)}
.warm{background:var(--canvas-warm)}

/* Word reveal + block rise */
.reveal span{display:inline-block;opacity:.18;filter:blur(3px);
  transition:opacity .55s ease,filter .55s ease}
.reveal.on span{opacity:1;filter:none}
.rise{opacity:0;transform:translateY(26px);
  transition:opacity .8s var(--ease),transform .8s var(--ease)}
.rise.on{opacity:1;transform:none}
.scrub span{display:inline-block;opacity:.18;filter:blur(4px);transition:none;
  will-change:opacity,filter}
@media(prefers-reduced-motion:reduce){.scrub span{opacity:1;filter:none}}

/* ================================================================ lede === */
/* The opening statement of a light band: oversized serif, a rule, and the
   supporting prose set beside it rather than under it. */
/* Heading and its supporting line share a top edge, with the prose nudged
   down to sit optically on the heading's first baseline rather than above
   it. Bottom-aligning them, as this did before, left the lede floating at a
   different height in every section depending on how many lines it ran to. */
.statement{display:grid;grid-template-columns:1.24fr .76fr;gap:clamp(1.6rem,4vw,4.4rem);
  align-items:start}
.statement .h{margin-bottom:0;max-width:27ch}
.statement .lede{padding-top:clamp(.25rem,.7vw,.7rem)}
@media(max-width:900px){.statement{grid-template-columns:1fr;gap:1.6rem}}

/* A single-column opener, for sections whose supporting line is short enough
   that setting it beside the heading would leave a hole rather than a
   composition. */
.lead-in{max-width:60ch}
.lead-in .h{max-width:16ch}
.lead-in .lede{max-width:52ch}

/* ================================================================ stats == */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:0;
  border-top:1px solid var(--rule);margin-top:var(--flow-l)}
.stat{padding:2rem 1.6rem 0 0;border-right:1px solid var(--rule)}
.stat:last-child{border-right:none}
.stat:not(:first-child){padding-left:1.8rem}
.stat b{display:block;font-family:var(--mono);font-weight:300;font-variant-numeric:tabular-nums;
  font-size:clamp(1.9rem,3.2vw,2.7rem);letter-spacing:-.045em;line-height:1;margin-bottom:.6rem;
  color:var(--brand)}
.dark .stat b{color:var(--moss)}
.dark .stat,.dark .stats{border-color:var(--rule-dark)}
.stat span{font-size:.88rem;color:var(--ink-soft);display:block;max-width:20ch}
.dark .stat span{color:var(--bone-soft)}
@media(max-width:820px){.stats{grid-template-columns:1fr 1fr}
  .stat{border-bottom:1px solid var(--rule);padding-bottom:1.6rem}
  .stat:nth-child(2n){border-right:none}
  .stat:not(:first-child){padding-left:0}
  .stat:nth-child(2n){padding-left:1.8rem}}

/* ============================================================== versus === */
/* A spec sheet, not a row of floating multipliers. Four measured quantities,
   both configurations named, and the difference in its own column — including
   the one difference that goes the other way. */
.versus{margin-top:var(--flow-l);background:var(--surface);border-radius:16px;
  border:1px solid var(--rule-soft);padding:clamp(1.4rem,2.4vw,2.4rem);
  box-shadow:0 1px 2px rgba(21,36,28,.04),0 18px 44px -26px rgba(21,36,28,.32)}
table.vs{width:100%;border-collapse:collapse}
table.vs th,table.vs td{text-align:right;padding:1rem 0 1rem 1.6rem;vertical-align:baseline}
table.vs .rowhead,table.vs tbody th{text-align:left;padding-left:0;font-weight:500;
  color:var(--ink-soft);font-size:.95rem}
table.vs thead th{border-bottom:1px solid var(--rule);padding-bottom:.9rem;
  font-weight:600;font-size:.95rem;white-space:nowrap}
table.vs thead th b{display:block;font-weight:600;font-size:1rem;color:var(--ink)}
table.vs thead th span{display:block;font-weight:400;font-size:.82rem;
  color:var(--ink-faint);margin-top:.15rem}
.vs-cap{display:block;font-weight:400;font-size:.82rem;color:var(--ink-faint);
  max-width:18ch;text-align:left}
table.vs tbody tr th,table.vs tbody tr td{border-top:1px solid var(--rule-soft)}
table.vs tbody tr:hover th,table.vs tbody tr:hover td{background:rgba(31,107,71,.045)}
table.vs tbody th:first-child{border-radius:8px 0 0 8px}
table.vs tbody td:last-child{border-radius:0 8px 8px 0}
table.vs .num{font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:1.02rem;color:var(--ink-soft);white-space:nowrap}
table.vs .win{color:var(--ink);font-weight:500}
table.vs .delta-col{color:var(--brand)}
table.vs .delta{color:var(--brand);font-weight:500}
/* The accuracy row is the one place the cheap model loses; it says so. */
table.vs .delta.cost{color:#a8442f}
.vs-foot{margin:1.3rem 0 0;font-size:.82rem;color:var(--ink-faint)}
@media(max-width:820px){
  .versus{padding:1.2rem;overflow-x:auto}
  table.vs{min-width:34rem}
  table.vs th,table.vs td{padding-left:1rem}
}

/* =============================================================== bento === */
/* Four results of unequal weight, laid out as unequal cards on white. */
.bento{display:grid;grid-template-columns:repeat(6,1fr);gap:14px;
  margin-top:var(--flow-m)}
.bento .cell{background:var(--surface);border:1px solid var(--rule-soft);border-radius:14px;
  padding:2.1rem 2.1rem 2.3rem;display:flex;flex-direction:column;justify-content:flex-end;
  min-height:14rem;box-shadow:0 1px 2px rgba(21,36,28,.04),0 12px 28px -18px rgba(21,36,28,.3);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease)}
.bento .cell:hover{transform:translateY(-3px);
  box-shadow:0 2px 4px rgba(21,36,28,.06),0 22px 44px -22px rgba(21,36,28,.4)}
.bento .cell.lead{grid-column:span 4;min-height:19rem;background:var(--forest);color:var(--bone);
  border-color:transparent}
.bento .cell.lead p{color:var(--bone-soft)}
.bento .cell.tall{grid-column:span 2;min-height:19rem}
.bento .cell.half{grid-column:span 3}
.bento .cell p{margin:0;font-size:.95rem;line-height:1.58;color:var(--ink-soft);max-width:50ch}
.bento .big{font-family:var(--mono);font-weight:300;font-variant-numeric:tabular-nums;
  font-size:clamp(2.7rem,5vw,4.2rem);letter-spacing:-.05em;line-height:.92;
  color:var(--moss);margin-bottom:.9rem}
.bento .mid{font-family:var(--mono);font-weight:300;font-variant-numeric:tabular-nums;
  font-size:clamp(1.75rem,2.8vw,2.25rem);letter-spacing:-.04em;line-height:1;
  color:var(--brand);margin-bottom:.6rem}
@media(max-width:900px){
  .bento{grid-template-columns:1fr}
  .bento .cell,.bento .cell.lead,.bento .cell.tall,.bento .cell.half{
    grid-column:span 1;min-height:0}}

/* ================================================================ grid === */
.cards{display:grid;grid-template-columns:1fr 1fr;gap:var(--flow-m) 3rem;
  margin-top:var(--flow-l)}
.card{padding-top:1.5rem;border-top:2px solid var(--ink)}
.dark .card{border-top-color:var(--bone)}
.card p{margin:0;font-size:.95rem;line-height:1.6;color:var(--ink-soft)}
.dark .card p{color:var(--bone-soft)}
@media(max-width:820px){.cards{grid-template-columns:1fr}}

/* ============================================================== tables === */
/* Rows were separated by a hairline so faint the eye could not track across
   them. The structure now comes from a banded row, a firm rule under the
   header, and numerals that line up because they are tabular. */
.tscroll{overflow-x:auto;max-width:100%;
  border:1px solid var(--rule);border-radius:12px;background:var(--surface)}
table.data{width:100%;border-collapse:collapse}
table.data caption{caption-side:top;text-align:left;padding:1rem 1.15rem .4rem;
  font-size:.88rem;color:var(--ink-faint)}
/* A forest header band: it separates the data from the page, gives every
   table a definite top edge, and puts the brand colour somewhere structural
   rather than decorative. */
table.data th{font-size:.8rem;font-weight:600;letter-spacing:.02em;color:var(--bone);
  text-align:left;padding:.9rem 1.15rem;background:var(--bottle);
  white-space:nowrap;position:sticky;top:0}
table.data thead th:first-child{border-radius:11px 0 0 0}
table.data thead th:last-child{border-radius:0 11px 0 0}
table.data td{padding:.82rem 1.15rem;font-size:.95rem;vertical-align:baseline;
  border-bottom:1px solid var(--rule-soft)}
table.data tbody tr:nth-child(even) td{background:rgba(21,36,28,.022)}
table.data tbody tr:hover td{background:var(--accent-row,rgba(31,107,71,.055))}
table.data tbody tr:last-child td{border-bottom:none}
table.data .num{text-align:right;font-family:var(--mono);font-size:.9rem;
  white-space:nowrap;font-variant-numeric:tabular-nums}
table.data th.num{text-align:right}
table.data .model{font-family:var(--mono);font-size:.86rem;color:var(--ink)}
table.data .model .prec{display:block;font-size:.74rem;color:var(--ink-faint);letter-spacing:.02em}
table.data .dim{color:var(--ink-faint)}
.verdict{font-size:.88rem;font-weight:600}
.verdict.hit{color:var(--brand)}
.verdict.miss{color:var(--ink-faint);text-decoration:line-through}
.verdict.none{color:var(--ink-faint)}

/* ============================================================== console == */
.console{border:1px solid var(--rule);background:var(--surface);border-radius:14px;
  box-shadow:0 1px 2px rgba(21,36,28,.04),0 18px 40px -26px rgba(21,36,28,.35)}
.console-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:1rem 1.4rem;border-bottom:1px solid var(--rule-soft);
  background:var(--canvas);border-radius:14px 14px 0 0}
.label{font-size:.92rem;font-weight:600;color:var(--ink-soft)}
.live{display:inline-flex;align-items:center;gap:.55rem;font-size:.9rem;color:var(--ink-soft)}
.live::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--brand)}
.console-pad{padding:1.8rem 1.6rem 2rem}

.field{display:flex;flex-direction:column;gap:.55rem}
.field > label{font-size:.9rem;font-weight:600;color:var(--ink-soft)}
select,input[type=file]{background:var(--surface);border:1px solid var(--rule);
  border-radius:9px;color:var(--ink);font-family:var(--mono);font-size:.92rem;
  padding:.7rem .8rem;width:100%}
select:hover{border-color:var(--ink-faint)}

/* One model per line. Wrapping put resnet50 alongside mobilevit_s, which
   read as a pair rather than as two entries in a list. */
.chips{display:flex;flex-direction:column;align-items:stretch;gap:.4rem}
.chip{display:inline-flex;align-items:center;gap:.5rem;font-family:var(--mono);
  font-size:.83rem;padding:.5rem .8rem;border-radius:99px;cursor:pointer;
  border:1px solid var(--rule);color:var(--ink-soft);background:var(--surface);
  transition:border-color .2s ease,color .2s ease,background .2s ease}
.chip:hover{border-color:var(--ink-faint);color:var(--ink)}
.chip.on{background:var(--forest);border-color:var(--forest);color:var(--bone)}
.chip .x{opacity:.6}
.chip[disabled]{opacity:.4;cursor:not-allowed}

.tile{border:1px solid var(--rule);background:var(--surface);border-radius:12px;overflow:hidden}
.tile img{width:100%;display:block;aspect-ratio:1;object-fit:cover;image-rendering:pixelated}
.tile-meta{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.15rem .8rem;
  padding:.7rem .9rem;border-top:1px solid var(--rule-soft);font-size:.86rem;
  color:var(--ink-faint)}
.tile-meta .truth{color:var(--ink);font-weight:600}
.empty{display:flex;align-items:center;justify-content:center;min-height:12rem;
  border:1px dashed var(--rule);border-radius:12px;font-size:.95rem;
  color:var(--ink-faint);text-align:center;padding:1.2rem}

/* ============================================================ quant pair = */
.quant{display:grid;grid-template-columns:1fr 1.15fr;border:1px solid var(--rule);
  border-radius:14px;overflow:hidden;background:var(--surface)}
.qpanel{padding:2.1rem 2rem}
.qpanel + .qpanel{border-left:1px solid var(--rule)}
.qpanel.loss{background:var(--canvas)}
.delta{font-family:var(--mono);font-size:clamp(2rem,3.6vw,2.9rem);font-weight:300;
  letter-spacing:-.04em;display:block;margin-bottom:.5rem;font-variant-numeric:tabular-nums}
.delta.ok{color:var(--brand)}
.delta.bad{color:#a8442f}
.pair{display:flex;align-items:flex-end;gap:1.5rem;height:132px;margin-top:1.6rem;max-width:21rem}
.pcol{flex:1;display:flex;flex-direction:column;justify-content:flex-end;height:100%}
.stem{width:100%;height:100%;background:var(--rule);transform-origin:bottom;
  transform:scaleY(var(--v,0));transition:transform 1s cubic-bezier(.16,.8,.3,1);
  border-radius:4px 4px 0 0}
.pcol.q .stem{background:var(--brand)}
.qpanel.loss .pcol.q .stem{background:repeating-linear-gradient(135deg,
  #d3b3aa 0 5px,transparent 5px 10px);border-top:2px solid #a8442f}
.tick{font-family:var(--mono);font-size:.82rem;color:var(--ink-faint);margin-top:.6rem}
@media(max-width:860px){.quant{grid-template-columns:1fr}
  .qpanel + .qpanel{border-left:none;border-top:1px solid var(--rule)}}

/* =============================================================== footer == */
/* Compact: one row of links, one line of fine print. It is a footer, not a
   second homepage. */
/* The footer is a utility zone, not a feature band: cream, one row, and out
   of the way. A deep-green slab down here competed with the closing section
   directly above it and doubled the page's dark weight for no reason. */
footer{background:var(--canvas-warm);color:var(--ink);
  border-top:1px solid var(--rule);padding:.95rem 0}
.foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:.5rem 2rem}
.foot .brand{font-size:.95rem}
.flinks{display:flex;flex-wrap:wrap;gap:.3rem 1.4rem}
.flinks a{font-size:.82rem;color:var(--ink-soft);transition:color .2s ease}
.flinks a:hover{color:var(--brand)}
.fine{margin-top:.85rem;padding-top:.75rem;border-top:1px solid var(--rule-soft);
  font-size:.75rem;line-height:1.5;color:var(--ink-faint);max-width:100ch}

/* The mark sits on cream down here, so it takes the ink and brand colours
   rather than the light-on-dark pair. */
footer .brand .mark path{stroke:var(--ink-faint);opacity:1}
footer .brand .mark .pin{fill:var(--brand)}

/* =============================================================== range === */
/* The default range control is a grey OS artefact. This is a measured track
   with a filled portion showing how far the constraint has been pushed, and a
   thumb that responds to press. --fill is set by tradeoffs.js. */
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:34px;
  background:transparent;cursor:pointer;display:block}
input[type=range]::-webkit-slider-runnable-track{height:6px;border-radius:99px;
  background:linear-gradient(to right,var(--brand) 0 var(--fill,50%),
             var(--rule) var(--fill,50%) 100%)}
input[type=range]::-moz-range-track{height:6px;border-radius:99px;background:var(--rule)}
input[type=range]::-moz-range-progress{height:6px;border-radius:99px;background:var(--brand)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:22px;height:22px;margin-top:-8px;border-radius:50%;background:var(--surface);
  border:1px solid var(--rule);
  box-shadow:0 1px 2px rgba(21,36,28,.16),0 4px 12px -2px rgba(21,36,28,.28);
  transition:transform .14s ease,box-shadow .14s ease}
input[type=range]::-moz-range-thumb{width:22px;height:22px;border-radius:50%;
  background:var(--surface);border:1px solid var(--rule);
  box-shadow:0 1px 2px rgba(21,36,28,.16),0 4px 12px -2px rgba(21,36,28,.28)}
input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.06)}
/* Emil Kowalski's press rule: a control that does not compress on press feels
   dead. Under 300ms, transform only. */
input[type=range]:active::-webkit-slider-thumb{transform:scale(.97);
  box-shadow:0 1px 2px rgba(21,36,28,.2),0 2px 6px -1px rgba(21,36,28,.3)}
input[type=range]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--brand);
  outline-offset:2px}
.btn:active{transform:scale(.97)}

/* ---- where the colour goes ------------------------------------------------
   .band  one forest-green moment per page, for the sentence that matters
   .tint  a pale green wash to group a working area out of the cream
   .warn  the amber state, only ever for a measured loss
   -------------------------------------------------------------------------- */
.tint{background:linear-gradient(180deg,rgba(31,107,71,.055),rgba(31,107,71,.02))}
.warn{color:var(--amber)}
.delta.bad,.qpanel.loss .delta{color:var(--amber)}
.qpanel.loss{background:var(--amber-wash)}
.qpanel.loss .pcol.q .stem{background:repeating-linear-gradient(135deg,
  rgba(180,118,31,.45) 0 5px,transparent 5px 10px);
  border-top:2px solid var(--amber)}
table.vs .delta.cost{color:var(--amber)}

/* A quiet forest-green band, for the one moment on an inner page that should
   carry weight rather than another cream section. */
.band{background:var(--bottle);color:var(--bone);border-radius:16px;
  padding:clamp(1.6rem,3vw,2.6rem);--nav-ink:var(--bone)}
.band h3,.band .h{color:var(--bone)}
.band p{color:var(--bone-soft)}
.band .mono{color:var(--moss)}

/* ============================================================== a11y ===== */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{transition-duration:.01ms!important;animation-duration:.01ms!important}
  .reveal span,.rise{opacity:1;transform:none;filter:none}
}

/* The tile mosaic. It was carrying its spacing in an inline style, which is
   why it sat on a different rhythm from every other block on the page. */
.mosaic{display:grid;grid-template-columns:repeat(12,1fr);gap:4px;
  margin-top:var(--flow-m);border-radius:10px;overflow:hidden}
@media(max-width:900px){.mosaic{grid-template-columns:repeat(6,1fr)}}
@media(max-width:560px){.mosaic{grid-template-columns:repeat(4,1fr)}}

/* ============================================================== closing == */
/* The photograph is the argument: this is the land the models classify and
   the reason the joules matter. It is graded to be looked at, and the copy
   gets its ground from a veil that clears the right of the frame. */
.closing{position:relative;overflow:hidden;isolation:isolate;
  min-height:clamp(30rem,58vh,42rem);display:flex;align-items:center;
  padding:clamp(84px,12vh,150px) 0;color:var(--bone);--nav-ink:var(--bone)}
.closing-art{position:absolute;inset:0;z-index:-2;
  background:url('valley.jpg') center 46%/cover no-repeat;
  filter:saturate(1.08) contrast(1.04)}
.closing-veil{position:absolute;inset:0;z-index:-1;background:
  linear-gradient(102deg,rgba(9,26,19,.93) 0%,rgba(9,26,19,.8) 36%,
                  rgba(9,26,19,.34) 64%,rgba(9,26,19,.06) 100%)}
.closing-copy{position:relative;width:100%}
.closing-copy .h{max-width:16ch;color:var(--bone)}
.closing-copy .lede{max-width:48ch;color:var(--bone-soft)}
.closing-actions{display:flex;flex-wrap:wrap;gap:.8rem;margin:2.4rem 0 0}
.closing .btn-primary{background:var(--moss);color:#12220c;border-color:var(--moss)}
.closing .btn-primary:hover{background:#bcd89f;border-color:#bcd89f}
@media(max-width:820px){
  .closing-art{background-position:center}
  .closing-veil{background:linear-gradient(to bottom,rgba(9,26,19,.84),rgba(9,26,19,.94))}
}

/* The bento settles cell by cell, weightiest first. */
.bento .cell.rise{transform:translateY(22px) scale(.995)}
.bento .cell.rise.on{transform:none}
.bento .cell:nth-child(2).rise{transition-delay:.09s}
.bento .cell:nth-child(3).rise{transition-delay:.18s}
.bento .cell:nth-child(4).rise{transition-delay:.27s}

/* Cards in a row stagger the same way rather than arriving as one block. */
.cards .card:nth-child(2).rise{transition-delay:.07s}
.cards .card:nth-child(3).rise{transition-delay:.14s}
.cards .card:nth-child(4).rise{transition-delay:.21s}

/* ========================================================== provenance === */
/* Three guarantees, each stated in words, with its fingerprint as supporting
   evidence rather than as the thing the reader has to decode. */
.provenance{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;
  margin-top:var(--flow-m)}
.provenance .seal{background:var(--bottle);color:var(--bone);border:0;
  border-radius:14px;padding:1.6rem 1.6rem 1.3rem;display:flex;flex-direction:column;
  box-shadow:0 14px 34px -22px rgba(12,31,24,.55)}
.provenance .seal h3{color:var(--bone)}
.provenance p{margin:0 0 1.2rem;font-size:.95rem;line-height:1.6;color:var(--bone-soft)}
.seal-id{margin-top:auto;padding-top:.9rem;border-top:1px solid var(--rule-dark)}
.seal-id span{display:block;font-size:.76rem;color:var(--bone-faint);margin-bottom:.32rem}
.seal-id code{font-family:var(--mono);font-size:.78rem;color:var(--moss);
  word-break:break-all;line-height:1.5}
@media(max-width:900px){.provenance{grid-template-columns:1fr}}

/* A section that opens a working area is marked by a short green rule, so
   the eye can find the start of each part of a long page. */
.opens{position:relative;padding-top:1.3rem}
.opens::before{content:"";position:absolute;left:0;top:0;width:44px;height:3px;
  border-radius:99px;background:var(--brand)}
.dark .opens::before{background:var(--moss)}

/* ================================================================= lab === */
/* The classifier needs more measure than an article does: the results table
   has eight columns and side-scrolling it hides the comparison that is the
   whole point of the page. */
.wrap.wide{max-width:1460px}
.lab .console{overflow:hidden}

/* A select that belongs to the design rather than to the operating system.
   The native control still does the work; only its skin changes. */
.pick{position:relative;display:block}
.pick select{-webkit-appearance:none;appearance:none;width:100%;cursor:pointer;
  padding:.78rem 2.4rem .78rem .9rem;border-radius:10px;
  background:var(--surface);border:1px solid var(--rule);color:var(--ink);
  font-family:var(--mono);font-size:.9rem;
  transition:border-color .18s ease,box-shadow .18s ease,background .18s ease}
.pick select:hover{border-color:var(--brand);background:rgba(31,107,71,.03)}
.pick select:focus-visible{border-color:var(--brand);
  box-shadow:0 0 0 3px rgba(31,107,71,.16);outline:none}
.pick svg{position:absolute;right:.95rem;top:50%;width:12px;height:8px;
  margin-top:-4px;pointer-events:none;fill:none;stroke:var(--ink-faint);
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;
  transition:stroke .18s ease,transform .18s ease}
.pick:hover svg{stroke:var(--brand);transform:translateY(1px)}

.field > label .count{color:var(--ink-faint);font-weight:400}

/* Model chips: adding one is a positive act, so it reads as filled and
   carries a tick; removing is the quiet × that appears on hover. */
.chip{position:relative;justify-content:space-between;padding:.6rem .85rem;
  font-size:.86rem;font-weight:500;
  border-radius:10px;transition:border-color .18s ease,color .18s ease,
  background .18s ease,transform .12s ease}
.chip:hover{transform:translateY(-1px)}
.chip:active{transform:scale(.97)}
.chip.on{background:var(--brand);border-color:var(--brand);color:#fff}
.chip.on:hover{background:var(--brand-dark);border-color:var(--brand-dark)}
.chip .x{opacity:.55;transition:opacity .18s ease}
.chip:hover .x{opacity:1}

/* The run bar reads as an instrument: a live state and a measured progress
   line rather than a grey stripe. */
.runbar{align-items:center}
.status{display:inline-flex;align-items:center;gap:.5rem}
.status::before{content:"";width:7px;height:7px;border-radius:50%;
  background:var(--ink-faint);transition:background .2s ease}
.status.busy::before{background:var(--brand);
  animation:pulse 1.1s ease-in-out infinite}
@keyframes pulse{50%{opacity:.35}}

/* Rows arrive as their model finishes, rather than the table appearing whole. */
@keyframes rowIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
table.data tbody tr{animation:rowIn .34s cubic-bezier(.16,1,.3,1) both}
table.data tbody tr:nth-child(2){animation-delay:.05s}
table.data tbody tr:nth-child(3){animation-delay:.1s}
table.data tbody tr:nth-child(4){animation-delay:.15s}
table.data tbody tr:nth-child(5){animation-delay:.2s}
@media(prefers-reduced-motion:reduce){table.data tbody tr{animation:none}}

/* Upload: a real target, not a naked file input. The native control still
   opens the picker; the label is what the visitor sees. */
.drop{display:flex;align-items:center;gap:.6rem;cursor:pointer;
  padding:.78rem .9rem;border:1px dashed var(--rule);border-radius:10px;
  background:var(--surface);font-size:.9rem;color:var(--ink-soft);
  transition:border-color .18s ease,background .18s ease,color .18s ease}
.drop:hover{border-color:var(--brand);color:var(--ink);background:rgba(31,107,71,.04)}
.drop:active{transform:scale(.99)}
.drop svg{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.drop input[type=file]{position:absolute;width:1px;height:1px;opacity:0;
  padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0)}
.drop:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px rgba(31,107,71,.16)}
.linkish{background:none;border:0;padding:.35rem 0 0;cursor:pointer;
  font-family:var(--sans);font-size:.84rem;color:var(--brand);text-align:left;
  text-decoration:underline;text-underline-offset:3px}
.linkish:hover{color:var(--brand-dark)}

/* A tile the zoo cannot agree on is marked, because that disagreement is the
   reason it was chosen. */
.tile.contested{box-shadow:0 0 0 2px var(--amber)}
.tile.contested .tile-meta{background:var(--amber);color:#fff;
  border-top-color:transparent}
.tile.contested .tile-meta .truth{color:#fff;font-weight:600}

/* Download size on an unselected model chip: the visitor is about to pay for
   these bytes, so the price is on the button rather than discovered after. */
.chip .mb{opacity:.55;font-variant-numeric:tabular-nums;margin-left:.35rem}
