/* ============================================================================
   THE HORIZON SUITE — counterplan.com
   Hand-written. No build step, no framework, no dependencies. One stylesheet.

   THE COLOUR RULE
   ---------------
   Three systems, kept separate, so no colour on this site means two things.

     1. --signal (near-white) is interactive chrome and ONLY interactive chrome.
        It belongs to no tool, so a button is never mistaken for a product.

     2. --horizon (terracotta, carried across from the printed brochure) means
        exactly one thing: THIS IS HORIZON'S OWN MODELLED FIGURE. It appears in
        the charts and in the numerals read off them. Nowhere else. The council's
        own published figure is always --bone beside it. A reader who learns that
        pairing in the hero can read every chart on the page without a legend.

     3. The four tool hues are identity only — name, rule, rail node. They never
        carry data and they never decorate.

   LocalPlanHorizon has no hue of its own. It is included with the Full Suite
   rather than sold, and it is built out of the other four tools' output, so it
   is rendered in paper tones and set inside the suite rather than beside it.
   The structure states the commercial fact; no badge has to.

   TYPE
   ----
   The suite's own, unchanged: Instrument Sans for display, Source Sans 3 for
   body, IBM Plex Mono for the technical register. All four tools enforce these
   in their test suites — a marketing site in another face would be the first
   thing to give the game away. Display is set heavy and tight to match the
   brochure's headline block.

   MOTION
   ------
   One orchestrated moment: the hero chart draws itself once, on load. Everything
   else is a quiet reveal. Transform and opacity only — never width, height, top
   or left. Every animated element carries its final state in its base rule, so
   the page is complete with JavaScript blocked and complete again under
   prefers-reduced-motion.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600;700&family=Source+Sans+3:ital,wght@0,400;0,600;1,400&display=swap');

:root {
  --ground:      #0D1210;
  --paper:       #141A18;
  --paper-2:     #1B2321;
  --text:        #E4EAE7;
  --muted:       #96A29C;   /* >=4.5:1 on all three surfaces */
  --rule:        #242E2A;
  --rule-soft:   #1A2220;
  --rule-strong: #69736E;   /* >=3:1 on all three — interactive borders */

  /* 1. Interactive chrome. Belongs to no tool. */
  --signal:      #E4EAE7;
  --signal-deep: #FFFFFF;
  --on-signal:   #0D1210;

  /* 2. Data. --horizon is Horizon's modelled figure; --bone is the council's
        own published figure it is set against. Never used for anything else. */
  --horizon:      #D4763A;  /* 5.8:1 on ground — safe for numerals and labels */
  --horizon-deep: #C4642A;  /* chart fills, where 3:1 is the bar */
  --horizon-dim:  #7A4322;  /* the subsidy-recovered portion of a bar */
  --bone:         #9A968E;  /* the published figure, and displaced quantities */

  /* 3. Tool identity. Name, rule, rail node — never data, never decoration. */
  --fiveyear: #DE7355;
  --taspend:  #D9A441;
  --eia:      #9B87D4;
  --capacity: #6FC79A;

  --display: 'Instrument Sans', 'Helvetica Neue', Arial, sans-serif;
  --body:    'Source Sans 3', Calibri, 'Helvetica Neue', Arial, sans-serif;
  --mono:    'IBM Plex Mono', 'SF Mono', Menlo, Consolas, monospace;

  --shell: 1180px;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --radius: 2px;

  --s-1: .5rem; --s-2: 1rem; --s-3: 1.5rem; --s-4: 2.5rem;
  --s-5: 4rem;  --s-6: 6rem; --s-7: 9rem;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur-fast: 160ms;
  --dur: 260ms;
  --dur-slow: 620ms;
  --dur-draw: 1100ms;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  margin: 0;
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.3rem, 5.6vw, 4.1rem); }
h2 { font-size: clamp(1.85rem, 4vw, 2.9rem); }
h3 { font-size: clamp(1.3rem, 2.2vw, 1.7rem); letter-spacing: -0.028em; }
h4 { font-size: 1.02rem; font-weight: 600; letter-spacing: -0.012em; }
p  { margin: 0 0 var(--s-2); }
p:last-child { margin-bottom: 0; }

a { color: var(--signal); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--signal-deep); }

::selection { background: var(--horizon); color: var(--ground); }

:focus-visible {
  outline: 3px solid var(--signal);
  outline-offset: 3px;
  border-radius: 1px;
}

.shell { max-width: var(--shell); margin: 0 auto; padding: 0 var(--gutter); }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden;
      clip: rect(0 0 0 0); white-space: nowrap; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.dim  { color: var(--muted); }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus {
  left: var(--gutter); top: .6rem; z-index: 100; background: var(--paper);
  color: var(--text); padding: .85rem 1.1rem; border: 1px solid var(--signal);
  min-height: 44px; display: inline-flex; align-items: center;
}

/* The eyebrow is the brochure's running head, kept verbatim: mono, tracked
   wide, small. It is the one place the printed document shows through. */
.eyebrow {
  display: block;
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s-3);
}
.eyebrow.tool { color: var(--tool, var(--muted)); }

/* ---------------------------------------------------------------- header */
.topbar {
  position: sticky; top: 0; z-index: 50;
  background: rgba(13, 18, 16, .82);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.topbar.is-stuck { border-bottom-color: var(--rule); background: rgba(13, 18, 16, .95); }
.topbar-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-2); padding: .95rem 0;
}
.wordmark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--display); font-weight: 700; font-size: 1.08rem;
  letter-spacing: -0.03em; color: var(--text); text-decoration: none;
}
.topnav { display: flex; align-items: center; gap: clamp(.9rem, 2.2vw, 1.9rem); }
.topnav a {
  font-size: .93rem; color: var(--muted); text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}
.topnav a:hover { color: var(--text); }
.topnav a.btn { color: var(--on-signal); }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; gap: .55rem;
  min-height: 46px; padding: .72rem 1.35rem;
  background: var(--signal); color: var(--on-signal);
  font-family: var(--display); font-weight: 600; font-size: .97rem;
  letter-spacing: -0.012em; text-decoration: none; border: 1px solid var(--signal);
  border-radius: var(--radius); cursor: pointer;
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--signal-deep); color: var(--on-signal); transform: translateY(-1px); }
.btn .arrow { width: 17px; height: 17px; transition: transform var(--dur) var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }
.btn.small { min-height: 40px; padding: .5rem 1rem; font-size: .9rem; }
.btn.ghost {
  background: transparent; color: var(--text); border-color: var(--rule-strong);
}
.btn.ghost:hover { background: var(--paper-2); color: var(--signal-deep); border-color: var(--signal); }

/* ---------------------------------------------------------------- sections */
.section { padding: var(--s-6) 0; border-top: 1px solid var(--rule-soft); }
.section-head { max-width: 46rem; margin-bottom: var(--s-5); }
.section-head p { color: var(--muted); font-size: 1.08rem; margin-top: var(--s-3); }

/* A single heavy rule under a section heading, as the brochure sets it: it runs
   the full measure, not the width of the text column above it. */
.section-head.tight { margin-bottom: var(--s-3); }
.rule-heavy { height: 2px; background: var(--text); margin: 0 0 var(--s-5); }

/* =============================================================== HERO ==== */
.hero { padding: clamp(3.5rem, 9vw, 6.5rem) 0 var(--s-6); }
.hero h1 { max-width: 15ch; }
.hero-sub {
  max-width: 44rem; margin-top: var(--s-3);
  font-size: clamp(1.05rem, 1.6vw, 1.25rem); color: var(--muted);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }

/* ------------------------------------------------- the gap (signature) --- */
/* The hero chart is the product's actual output, not an illustration of it:
   one authority's published five-year supply position set against the position
   the same evidence supports, with the statutory line neither reaches. */
.gap {
  margin-top: var(--s-6);
  border-top: 2px solid var(--text);
  padding-top: var(--s-3);
}
.gap-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--s-2); margin-bottom: var(--s-4);
}
.gap-title {
  font-family: var(--mono); font-size: .74rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text);
}
.gap-src { font-family: var(--mono); font-size: .78rem; color: var(--muted); }

/* The label column is declared once here. The rows, the five-year line and the
   scale all measure from it, so the axis can never drift off the bars. */
.gap-plot { position: relative; --label-col: 13.5rem; --col-gap: var(--s-2); }

/* An overlay covering the track column only — not the labels. */
.gap-field {
  position: absolute; top: -.35rem; bottom: 3.4rem;
  left: calc(var(--label-col) + var(--col-gap)); right: 0;
  pointer-events: none;
}
/* The five-year threshold. Sits at 5.0 on a 0–5.5 scale = 90.909%. */
.gap-threshold {
  position: absolute; top: 0; bottom: 0; left: 90.909%;
  border-left: 1px dashed var(--rule-strong);
}
.gap-threshold span {
  position: absolute; top: 0; left: .6rem;
  font-family: var(--mono); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.gap-axis { margin-left: calc(var(--label-col) + var(--col-gap)); }

.gap-row { display: grid; grid-template-columns: var(--label-col) 1fr; align-items: center;
           gap: var(--col-gap); margin-bottom: var(--s-2); }
.gap-label { font-size: .97rem; color: var(--muted); }
.gap-row.is-horizon .gap-label { color: var(--text); font-weight: 600; }

.gap-track { position: relative; height: 2.6rem; }
.gap-bar {
  position: absolute; inset: 0 auto 0 0; height: 100%;
  width: var(--w); transform-origin: left center;
  border-radius: 0 1px 1px 0;
}
.gap-row.is-published .gap-bar { background: var(--bone); opacity: .34; }
.gap-row.is-horizon   .gap-bar { background: var(--horizon-deep); }

.gap-value {
  position: absolute; top: 50%; left: var(--label-at, var(--w));
  transform: translate(.85rem, -50%);
  /* The figure knocks the threshold hairline out behind itself rather than
     letting the two overprint — at narrow widths the label reaches the line. */
  background: var(--ground); padding: 0 .3rem; margin-left: -.3rem;
  font-family: var(--mono); font-size: 1.15rem; font-weight: 500;
  white-space: nowrap;
}
.gap-row.is-published .gap-value { color: var(--muted); }
.gap-row.is-horizon   .gap-value { color: var(--horizon); }
.gap-range-label { color: var(--muted); font-size: .78rem; letter-spacing: 0; }

/* The confidence range, drawn on the modelled bar because the modelled figure
   is the only one on this chart that has one. */
.gap-range {
  position: absolute; top: 50%; height: 1px; background: var(--text);
  left: var(--from); width: calc(var(--to) - var(--from));
  transform: translateY(-50%);
}
.gap-range::before, .gap-range::after {
  content: ""; position: absolute; top: -5px; width: 1px; height: 11px; background: var(--text);
}
.gap-range::before { left: 0; }
.gap-range::after  { right: 0; }

.gap-scale {
  position: relative; height: 1.5rem;
  border-top: 1px solid var(--rule); margin-top: .35rem; padding-top: .5rem;
  font-family: var(--mono); font-size: .72rem; color: var(--muted);
}
.gap-scale span {
  position: absolute; top: .5rem; left: var(--at); transform: translateX(-50%);
}
.gap-foot {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s-3) var(--s-4); margin-top: var(--s-4);
  border-top: 1px solid var(--rule); padding-top: var(--s-3);
}
.gap-foot .n {
  display: block; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.9rem, 3.4vw, 2.5rem); letter-spacing: -0.04em;
  line-height: 1; color: var(--horizon);
}
.gap-foot .l { display: block; margin-top: .5rem; font-size: .94rem; color: var(--muted); }

/* =========================================================== the problem = */
.problem-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: var(--s-4); margin-bottom: var(--s-5);
}
.problem-cols p { color: var(--muted); }

.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
           gap: var(--s-4); }
.figure { border-top: 2px solid var(--text); padding-top: var(--s-2); }
.figure .n {
  display: block; font-family: var(--display); font-weight: 700;
  font-size: clamp(2.4rem, 5vw, 3.4rem); letter-spacing: -0.045em; line-height: 1;
  color: var(--horizon);
}
.figure .l { display: block; margin-top: var(--s-2); font-size: .97rem; color: var(--muted); }

.closing {
  margin-top: var(--s-5); border-top: 2px solid var(--text); padding-top: var(--s-3);
  font-family: var(--display); font-weight: 600; font-size: clamp(1.2rem, 2.3vw, 1.6rem);
  line-height: 1.3; letter-spacing: -0.025em; max-width: 52rem;
}

/* ================================================================ index == */
/* The numbering is the brochure's own index and the suite has a canonical
   order, so 01–04 carries real information rather than decorating a list. */
.index-row {
  display: grid; grid-template-columns: 15rem 1fr; gap: var(--s-4);
  padding: var(--s-4) 0; border-top: 1px solid var(--rule);
  text-decoration: none; color: inherit;
  transition: background var(--dur) var(--ease);
}
a.index-row:hover { background: var(--paper); }
a.index-row:hover .index-q { color: var(--tool); }
.index-row:last-of-type { border-bottom: 1px solid var(--rule); }
.index-num {
  font-family: var(--mono); font-size: .8rem; color: var(--tool);
  letter-spacing: .1em; display: block; margin-bottom: .4rem;
}
.index-name {
  font-family: var(--display); font-weight: 700; font-size: 1.32rem;
  letter-spacing: -0.03em;
}
.index-q {
  font-family: var(--display); font-weight: 700; font-size: 1.16rem;
  letter-spacing: -0.025em; color: var(--tool); margin-bottom: .6rem;
  transition: color var(--dur-fast) var(--ease);
}
.index-row p { color: var(--muted); max-width: 46rem; }
.built-on {
  display: block; margin-top: var(--s-2);
  font-family: var(--mono); font-size: .72rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--rule-strong);
}

/* The bundled fifth. Set inside the index rather than beside it, in paper
   tones with no hue of its own — it is included, not sold. */
.index-bundled {
  display: grid; grid-template-columns: 15rem 1fr; gap: var(--s-4);
  padding: var(--s-4); margin-top: var(--s-3);
  background: var(--paper); border-left: 2px solid var(--rule-strong);
}
.index-bundled .index-num { color: var(--muted); }
.index-bundled p { color: var(--muted); }
.index-visit {
  display: inline-flex; align-items: center; gap: .45rem;
  margin: var(--s-2) 0 0 var(--s-2); min-height: 44px;
  font-family: var(--display); font-weight: 600; font-size: .95rem;
  letter-spacing: -0.012em; color: var(--signal); text-decoration: none;
  border-bottom: 1px solid var(--rule-strong); padding-bottom: .1rem;
  transition: border-color var(--dur-fast) var(--ease);
}
.index-visit:hover { border-bottom-color: var(--signal); }
.index-visit svg { width: 15px; height: 15px; transition: transform var(--dur) var(--ease); }
.index-visit:hover svg { transform: translateX(3px); }

.badge {
  display: inline-block; margin-top: var(--s-2);
  font-family: var(--mono); font-size: .7rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text);
  border: 1px solid var(--rule-strong); padding: .3rem .6rem;
}

/* ================================================================ tools === */
.tool-section { border-top: 1px solid var(--rule-soft); padding: var(--s-6) 0; }
.tool-head { display: flex; flex-wrap: wrap; justify-content: space-between;
             gap: var(--s-2); align-items: baseline; margin-bottom: var(--s-3); }
.tool-head .name {
  font-family: var(--mono); font-size: .74rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--tool);
}
.tool-head .role {
  font-family: var(--mono); font-size: .74rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
}
.tool-section h2 { max-width: 20ch; }
.tool-lede {
  margin-top: var(--s-3); font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  color: var(--text); max-width: 48rem;
}

.tool-body {
  display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--s-5); margin-top: var(--s-4);
  border-top: 2px solid var(--text); padding-top: var(--s-4);
}
.tool-body p { color: var(--muted); }
.tool-body h4 {
  font-family: var(--mono); font-size: .74rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text);
  margin: var(--s-4) 0 var(--s-2); padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}

/* "In practice" — every tool is validated against a real published outcome,
   so the box is a standing part of each tool's argument, not a testimonial. */
.practice {
  background: var(--paper); border-top: 2px solid var(--tool);
  padding: var(--s-3); margin-bottom: var(--s-4);
}
.practice h4 { margin: 0 0 var(--s-2); padding: 0; border: 0;
               font-family: var(--display); font-size: 1.02rem; letter-spacing: -0.015em;
               text-transform: none; color: var(--text); }
.practice p { font-size: .96rem; }

.runs h4 {
  margin: 0 0 var(--s-2); padding: 0; border: 0; border-bottom: 2px solid var(--text);
  padding-bottom: .5rem;
}
.runs ul { list-style: none; margin: 0; padding: 0; }
.runs li { padding: .62rem 0; border-bottom: 1px solid var(--rule); font-size: .97rem; }

/* ------------------------------------------------------------- charts ---- */
.chart {
  margin-top: var(--s-5); border-top: 2px solid var(--text); padding-top: var(--s-3);
}
.chart-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--s-2); margin-bottom: var(--s-3);
}
.chart-title {
  font-family: var(--mono); font-size: .74rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text);
}
.chart-src { font-family: var(--mono); font-size: .76rem; color: var(--muted); }
.chart-grid {
  display: grid; grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr);
  gap: var(--s-4) var(--s-5); align-items: start;
}
.chart-figs { display: grid; gap: var(--s-3); }
.chart-fig { border-top: 1px solid var(--rule); padding-top: var(--s-2); }
.chart-fig:first-child { border-top: 0; padding-top: 0; }
.chart-fig .n {
  display: block; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.7rem, 3vw, 2.3rem); letter-spacing: -0.04em; line-height: 1;
  color: var(--horizon);
}
.chart-fig .n.plain { color: var(--text); }
.chart-fig .l { display: block; margin-top: .45rem; font-size: .92rem; color: var(--muted); }

.legend { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-bottom: var(--s-3); }
.legend span {
  display: inline-flex; align-items: center; gap: .45rem;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.legend i { width: 12px; height: 12px; display: block; }
.sw-horizon { background: var(--horizon-deep); }
.sw-dim     { background: var(--horizon-dim); }
.sw-bone    { background: var(--bone); opacity: .5; }

/* Horizontal bars — EIAHorizon's supported / displaced / additional. */
.hbars { display: grid; gap: .8rem; }
.hbar { display: grid; grid-template-columns: 10rem 1fr; align-items: center; gap: var(--s-2); }
.hbar .k { font-size: .95rem; color: var(--muted); }
.hbar.is-net .k { color: var(--text); font-weight: 600; }
.hbar-track { position: relative; height: 1.9rem; }
.hbar-fill {
  position: absolute; inset: 0 auto 0 0; width: var(--w); height: 100%;
  transform-origin: left center; background: var(--horizon-dim);
}
.hbar.is-displaced .hbar-fill { background: var(--bone); opacity: .45; }
.hbar.is-net .hbar-fill { background: var(--horizon-deep); }
.hbar .v {
  position: absolute; top: 50%; left: var(--w); transform: translate(.65rem, -50%);
  font-family: var(--mono); font-size: 1rem; color: var(--text); white-space: nowrap;
}

/* Stacked columns — TASpendHorizon's gross / subsidy / net over five years. */
/* The columns are measured against the plot box alone. The total sits above
   each stack as an overlay, so a tall column is never shrunk by its own label
   and the five bars stay in true proportion to one another. */
.cols { display: grid; grid-template-columns: repeat(5, 1fr); gap: clamp(.4rem, 1.4vw, 1rem);
        align-items: end; height: 16rem; padding-top: 1.6rem; }
.col { position: relative; height: 100%; }
.col-total {
  position: absolute; left: 0; right: 0; bottom: calc(var(--h) + .4rem);
  font-family: var(--mono); font-size: .88rem; color: var(--text);
  text-align: center; white-space: nowrap;
}
.col-stack {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--h);
  display: flex; flex-direction: column; transform-origin: bottom center;
}
.col-sub { height: var(--sub); background: var(--horizon-dim); }
.col-net { flex: 1; background: var(--horizon-deep); }
.col-k {
  margin-top: .55rem; padding-top: .5rem; border-top: 1px solid var(--rule);
  text-align: center; font-size: .84rem; color: var(--muted);
}
.col-k b { display: block; color: var(--text); font-weight: 600; font-size: .9rem; }
.col-k .pc { font-family: var(--mono); font-size: .74rem; }

/* Waterfall — CapacityHorizon's land budget, need stepped down to residual. */
.fall { display: grid; grid-template-columns: repeat(5, 1fr); gap: clamp(.4rem, 1.4vw, .9rem);
        height: 15rem; align-items: end; }
.fall-col { position: relative; height: 100%; }
.fall-bar {
  position: absolute; left: 0; right: 0;
  bottom: var(--base); height: var(--h);
  transform-origin: bottom center;
  background: var(--horizon-dim);
}
.fall-col.is-need .fall-bar { background: var(--paper-2); border: 1px solid var(--rule-strong); }
.fall-col.is-gap  .fall-bar { background: var(--horizon-deep); }
.fall-col.is-nil  .fall-bar { background: var(--bone); opacity: .5; }
.fall-v {
  position: absolute; left: 0; right: 0; bottom: calc(var(--base) + var(--h) + .4rem);
  text-align: center; font-family: var(--mono); font-size: .84rem; color: var(--text);
  white-space: nowrap;
}
.fall-k {
  margin-top: .55rem; padding-top: .5rem; border-top: 1px solid var(--rule);
  text-align: center; font-size: .84rem; color: var(--muted); line-height: 1.35;
}
.fall-col.is-gap + .fall-k, .fall-k.is-gap { color: var(--text); font-weight: 600; }
.fall-keys { display: grid; grid-template-columns: repeat(5, 1fr); gap: clamp(.4rem, 1.4vw, .9rem); }

/* ============================================================= assembled = */
.assembly {
  display: grid; grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: center; gap: var(--s-3); margin-top: var(--s-4);
}
.assembly-stack { display: grid; gap: .5rem; }
.assembly-in {
  background: var(--paper-2); padding: .7rem .9rem; font-size: .93rem; color: var(--muted);
}
.assembly-mid {
  background: var(--horizon-deep); color: #fff; padding: var(--s-3);
}
.assembly-mid b { font-family: var(--display); font-weight: 700; font-size: 1.15rem;
                  letter-spacing: -0.028em; display: block; margin-bottom: .4rem; }
.assembly-mid span { font-size: .93rem; opacity: .92; }
.assembly-out { display: grid; gap: .5rem; }
.assembly-out span {
  border-left: 2px solid var(--text); padding-left: .8rem; font-size: .95rem;
}
.assembly-arrow { color: var(--horizon); }

/* ================================================================ flow ==== */
.flow-row {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--s-3); padding: var(--s-3) 0; border-top: 1px solid var(--rule);
}
.flow-row:last-of-type { border-bottom: 1px solid var(--rule); }
.flow-row.is-all { background: var(--paper); padding-left: var(--s-3); padding-right: var(--s-3); }
.flow-name { font-family: var(--display); font-weight: 700; font-size: 1.1rem;
             letter-spacing: -0.025em; }
.flow-what { display: block; color: var(--muted); font-size: .93rem; margin-top: .15rem; }
.flow-arrow { color: var(--horizon); }

.disciplines {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--s-4); margin-top: var(--s-5);
}
.discipline { border-top: 2px solid var(--horizon-deep); padding-top: var(--s-2); }
.discipline h4 { margin-bottom: .6rem; }
.discipline p { color: var(--muted); font-size: .97rem; }

/* ================================================================= cta ==== */
.cta { background: var(--paper); border-top: 1px solid var(--rule); padding: var(--s-7) 0; }
.cta h2 { max-width: 16ch; font-size: clamp(2.1rem, 5.2vw, 3.6rem); }
.cta .stroke { width: 5.5rem; height: 2px; background: var(--text); margin: var(--s-3) 0; }
.cta p { max-width: 42rem; color: var(--muted); font-size: 1.1rem; }
.cta-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }

/* ============================================================== footer ==== */
.foot { border-top: 1px solid var(--rule); padding: var(--s-4) 0 var(--s-5); }
.foot-tools {
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-4);
  padding-bottom: var(--s-3); border-bottom: 1px solid var(--rule);
}
.foot-tools a {
  font-family: var(--display); font-weight: 700; font-size: 1rem;
  letter-spacing: -0.025em; color: var(--text); text-decoration: none;
  border-bottom: 2px solid var(--tool); padding-bottom: .15rem;
  transition: color var(--dur-fast) var(--ease);
}
.foot-tools a:hover { color: var(--tool); }
.foot-tools .sep { width: 1px; background: var(--rule); align-self: stretch; }
.foot-tools a.bundled { border-bottom-color: var(--rule-strong); }
.foot-meta {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s-2);
  margin-top: var(--s-3); font-family: var(--mono); font-size: .74rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}

/* ============================================================== motion ==== */
/* Every animated element is written in its FINAL state above. The classes below
   only take it away again, and only while the script is present and running. */
.js-anim .reveal { opacity: 0; transform: translateY(14px); }
.js-anim .reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-slow) var(--ease) var(--reveal-delay, 0ms),
              transform var(--dur-slow) var(--ease) var(--reveal-delay, 0ms);
}

/* The one orchestrated moment: the hero chart draws itself once. */
.js-anim .gap .gap-bar   { transform: scaleX(0); }
.js-anim .gap .gap-value,
.js-anim .gap .gap-range,
.js-anim .gap .gap-threshold { opacity: 0; }
.js-anim .gap.is-in .gap-bar {
  transform: none;
  transition: transform var(--dur-draw) var(--ease) var(--draw-delay, 0ms);
}
.js-anim .gap.is-in .gap-value,
.js-anim .gap.is-in .gap-range {
  opacity: 1;
  transition: opacity var(--dur) var(--ease) calc(var(--draw-delay, 0ms) + var(--dur-draw) - 120ms);
}
.js-anim .gap.is-in .gap-threshold {
  opacity: 1;
  transition: opacity var(--dur-slow) var(--ease) 260ms;
}

/* The other charts draw on scroll, in their own bar direction. */
.js-anim .chart .hbar-fill { transform: scaleX(0); }
.js-anim .chart.is-in .hbar-fill {
  transform: none;
  transition: transform var(--dur-draw) var(--ease) var(--draw-delay, 0ms);
}
.js-anim .chart .col-stack,
.js-anim .chart .fall-bar { transform: scaleY(0); }
.js-anim .chart.is-in .col-stack,
.js-anim .chart.is-in .fall-bar {
  transform: none;
  transition: transform var(--dur-draw) var(--ease) var(--draw-delay, 0ms);
}
.js-anim .chart .hbar .v,
.js-anim .chart .col-total,
.js-anim .chart .fall-v { opacity: 0; }
.js-anim .chart.is-in .hbar .v,
.js-anim .chart.is-in .col-total,
.js-anim .chart.is-in .fall-v {
  opacity: 1;
  transition: opacity var(--dur) var(--ease) calc(var(--draw-delay, 0ms) + var(--dur-draw) - 200ms);
}

/* ============================================================ responsive == */
@media (max-width: 900px) {
  .tool-body { grid-template-columns: 1fr; gap: var(--s-4); }
  .chart-grid { grid-template-columns: 1fr; }
  .index-row, .index-bundled { grid-template-columns: 1fr; gap: var(--s-2); }
  .assembly { grid-template-columns: 1fr; }
  .assembly-arrow { transform: rotate(90deg); justify-self: start; }
}
@media (max-width: 640px) {
  body { font-size: 16px; }
  .section, .tool-section { padding: var(--s-5) 0; }
  .gap-plot { --label-col: 0rem; --col-gap: 0rem; }
  .gap-row { grid-template-columns: 1fr; gap: .35rem; }
  .gap-track { height: 2.2rem; }
  .gap-field { bottom: 3rem; }
  .gap-range-label { font-size: .7rem; }
  .hbar { grid-template-columns: 1fr; gap: .3rem; }
  .cols { height: 12rem; }
  .fall { height: 11rem; }
  .col-k b { font-size: .8rem; }
  .fall-k, .col-k { font-size: .72rem; }
  .fall-v, .col-total { font-size: .7rem; }
  .topnav a:not(.btn) { display: none; }
  .flow-row { grid-template-columns: 1fr; }
  .flow-arrow { transform: rotate(90deg); justify-self: start; }
}

/* A visitor who has asked for no motion gets the finished page, not a faster
   version of the animation. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js-anim .reveal,
  .js-anim .gap .gap-bar, .js-anim .gap .gap-value,
  .js-anim .gap .gap-range, .js-anim .gap .gap-threshold,
  .js-anim .chart .hbar-fill, .js-anim .chart .col-stack, .js-anim .chart .fall-bar,
  .js-anim .chart .hbar .v, .js-anim .chart .col-total, .js-anim .chart .fall-v {
    opacity: 1; transform: none;
  }
}
