/* ============================================================
   Datafluvia landing — single hero.

   The multi-section landing (hero · ecosystem · pillars · agents ·
   integrations · analytics · reports · governance · use cases · CTA) is
   parked, not deleted: its markup still lives in
   `templates/Components/Landing/` and its stylesheet in `Pages/Landing.css`.
   `Pages/Home.html` simply stopped including them. Nothing below assumes they
   are gone — this file is self-contained under the `.lh` prefix, so bringing a
   section back is a one-line change to Home.html and nothing here moves.

   Rules kept from the parked sheet, because they are the house rules:
   - every colour resolves through a --df-* token from Datafluvia/Tokens.css;
     there is no hex, rgb or oklch below. Alpha is made with `color-mix` ON a
     token, which is still the token doing the talking;
   - custom properties declared here are LENGTHS, INDICES and DELAYS only
     (--lh-i, --lh-h, --lh-max) plus three CTA aliases that point at tokens;
   - motion is decoration and never information: the wires' travelling dash is
     the one continuous animation on the page, and it stops dead under
     `prefers-reduced-motion`.

   Dark is not a second design. The same structure resolves through the same
   semantic tokens; only three things are restated for it — the atmosphere
   behind the core, the glass mix, and the CTA fill (navy is the page's
   darkest ink in light, so in dark it would sink into the canvas).
   ============================================================ */

/* ============================================================
   Section shell
   ============================================================ */

/* The composition is wider than the 1200px marketing column: the flow diagram
   needs a source rail, two wire gaps, the core and an output rail side by
   side, and at 1200 the wires collapse to nothing. A length, not a colour. */
.lh {
  /* Wider than it was. At 1440 on a 2000px display the whole composition sat
     in the middle of the screen with a band of empty canvas above and below
     it — the hero is a full viewport, so the content has to be sized for one.
     Everything inside scales with it through the `vw` clamps below rather
     than being pinned, so the diagram grows with the column instead of
     floating in a bigger one. */
  --lh-max: 1680px;


  /* The filled CTA. The brief asks for deep midnight navy rather than the
     product's indigo — on this page the button is the only near-black object
     and that is what makes it read as the single action. It stays an alias
     onto the navy ramp, never a new colour. */
  --lh-cta-bg: var(--df-navy-900);
  --lh-cta-bg-hover: var(--df-navy-800);
  --lh-cta-ink: var(--df-action-ink);

  /* One glass recipe, three surfaces (nav pill excepted — that one is
     Public.css's). Declared once so a source card, the core and an output
     panel can never drift into three different materials. */
  --lh-glass: color-mix(in srgb, var(--df-surface) 74%, transparent);
  --lh-glass-strong: color-mix(in srgb, var(--df-surface) 88%, transparent);
  --lh-glass-edge: color-mix(in srgb, var(--df-border) 80%, transparent);
  /* The highlight along a glass surface's top edge — see `.lh-src`. */
  --lh-sheen: color-mix(in srgb, var(--df-surface) 90%, transparent);

  position: relative;
  /* The nav pill is sticky and therefore still in the flow: it costs its own
     height plus its top offset, and the hero has to give that back or the
     page scrolls by exactly one navbar. `svh` so a mobile browser's
     retracting URL bar does not do the same thing. */
  /* The pill costs its own height plus its top offset, and the hero gives
     that back so the page is exactly one viewport with nothing under it.
     `svh` so a mobile browser's retracting URL bar does not add a second
     screen's worth of scroll. */
  flex: 1;
  min-height: calc(100vh - 5rem);
  min-height: calc(100svh - 5rem);
  display: flex;
  align-items: center;
  padding-block: clamp(2rem, 5vw, 4.5rem);
}

/* The atmosphere.

   Drawn on the SHELL, not on the section. The nav pill is sticky and
   therefore sits in the flow above `.lh`; with the field inside the section
   it began below the pill, and the ~80px strip behind the pill stayed bare
   `--df-canvas` — a visibly harder, flatter colour than the hero directly
   under it, in both themes. Painted here it runs from the first pixel of the
   document and the seam has nowhere to be.

   Two wide, low-opacity fields — icy blue behind the diagram, barely-there
   violet at the top left — plus a hairline lattice. No blobs: every stop runs
   to transparent well before its edge, so there is no shape to see. */
.pub-shell--hero {
  position: relative;
  /* Contains the -1 layer below: without it, `z-index: -1` escapes to the
     root stacking context and paints behind the page background instead of
     behind the page content. */
  isolation: isolate;
  background: var(--df-canvas);
}

.pub-shell--hero::before,
.pub-shell--hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.pub-shell--hero::before {
  background:
    radial-gradient(58% 52% at 74% 34%,
      color-mix(in srgb, var(--df-indigo-500) 16%, transparent), transparent 72%),
    radial-gradient(46% 44% at 8% 8%,
      color-mix(in srgb, var(--df-violet-600) 7%, transparent), transparent 70%),
    radial-gradient(70% 60% at 50% 108%,
      color-mix(in srgb, var(--df-indigo-100) 60%, transparent), transparent 68%);
}

/* Second layer, over the fields: a 72px lattice at grid-line alpha. Masked to
   a soft ellipse behind the diagram so it never reaches the typography, where
   it would fight the text for the same fine detail. */
.pub-shell--hero::after {
  background-image:
    linear-gradient(to right, var(--df-grid-line) var(--df-rule), transparent var(--df-rule)),
    linear-gradient(to bottom, var(--df-grid-line) var(--df-rule), transparent var(--df-rule));
  background-size: 72px 72px;
  -webkit-mask-image: radial-gradient(58% 60% at 72% 45%, #000 0%, transparent 75%);
  mask-image: radial-gradient(58% 60% at 72% 45%, #000 0%, transparent 75%);
}

/* No dark background rule here any more. This page used to reach past
   `--df-canvas` for navy-990, because the app's dark canvas was navy-950 and
   the core's light had nothing dark enough to bloom out of. Navy-990 IS the
   dark canvas now (Tokens.css), so `.pub-shell--hero`'s own
   `background: var(--df-canvas)` already resolves to it and an override here
   would only be a second copy of the same value — the kind that stops matching
   the first one six months later. The fields below still restate themselves
   for dark; the ground does not. */

[data-theme="dark"] .lh {
  --lh-glass: color-mix(in srgb, var(--df-surface) 62%, transparent);
  --lh-glass-strong: color-mix(in srgb, var(--df-surface) 82%, transparent);
  --lh-glass-edge: color-mix(in srgb, var(--df-navy-700) 90%, transparent);
  --lh-sheen: color-mix(in srgb, var(--df-indigo-300) 16%, transparent);
  /* Navy IS the canvas here, so the light theme's fill would make the button
     disappear. Indigo-600 is the one rung that clears AA with white ink on
     navy (Tokens.css says so where --df-action-fill is declared) — and
     deliberately not indigo-700, which the dark theme repoints to a light
     tint for status pills. */
  --lh-cta-bg: var(--df-indigo-600);
  --lh-cta-bg-hover: var(--df-indigo-500);
}

/* Dark gets its light from behind the core rather than from the whole page:
   one warmer, tighter field where the intelligence layer sits, so the eye is
   pulled to the thing the section is about. Never flat black — the canvas is
   navy-990 and the fields sit on top of it. */
/* Four navy fields, deepest first, so the page reads as one light source in
   a dark room rather than as a colour wash. The two wide ones lift the whole
   right half off `--df-navy-990`; the tight one at 64%/46% is the core's own
   halo and is the brightest thing in the stack; violet stays a trace at the
   far corner, never a second light. Every stop runs to transparent, so there
   is no edge anywhere. */
[data-theme="dark"] .pub-shell--hero::before {
  background:
    radial-gradient(38% 42% at 64% 46%,
      color-mix(in srgb, var(--df-indigo-600) 26%, transparent), transparent 72%),
    radial-gradient(58% 54% at 72% 38%,
      color-mix(in srgb, var(--df-indigo-800) 40%, transparent), transparent 74%),
    radial-gradient(92% 82% at 60% 44%,
      color-mix(in srgb, var(--df-navy-800) 62%, transparent), transparent 78%),
    radial-gradient(48% 44% at 4% 4%,
      color-mix(in srgb, var(--df-violet-700) 14%, transparent), transparent 72%);
}

.lh__grid {
  position: relative;
  width: 100%;
  max-width: var(--lh-max);
  margin-inline: auto;
  padding-inline: var(--df-gutter);
  display: grid;
  /* 32rem is not a taste call: it is the width at which the headline's
     longest line fits without wrapping at the size below. The break between
     the two lines is a design decision, and a third line put there by the
     measure undoes it. */
  grid-template-columns: minmax(0, 38rem) minmax(0, 1fr);
  gap: clamp(2rem, 2.6vw, 4rem);
  align-items: center;
}

/* The pill's action, on this page only. `.df-btn--primary` is the product's
   indigo on every other public surface and stays that way; here it would be a
   second filled colour six inches from the hero's, and the eye reads two
   filled buttons in two colours as two different kinds of action. Light only —
   in dark the hero's own CTA is already indigo, so there is nothing to
   reconcile. The variables are the hero's, declared on `.lh`, so this is a
   third consumer of one decision rather than a fourth colour. */
.pub-shell--hero .df-nav__pill .df-btn--primary {
  --lh-cta-bg: var(--df-navy-900);
  --lh-cta-bg-hover: var(--df-navy-800);
  background: var(--lh-cta-bg);
}
.pub-shell--hero .df-nav__pill .df-btn--primary:hover,
.pub-shell--hero .df-nav__pill .df-btn--primary:active { background: var(--lh-cta-bg-hover); }
[data-theme="dark"] .pub-shell--hero .df-nav__pill .df-btn--primary {
  --lh-cta-bg: var(--df-indigo-600);
  --lh-cta-bg-hover: var(--df-indigo-500);
}

/* ============================================================
   Left column — the claim

   The vertical rhythm below is driven by `vh` as well as `vw`, and that is
   the whole trick of this page. Sized on width alone the composition came out
   the same height on a 1080px-tall screen as on a 700px one, so a tall
   viewport got a hero two thirds empty. A `vh` term in each clamp lets the
   gaps and the charts take the room the screen actually has, and the clamp
   ceilings stop it turning into a poster on a 4K panel.
   ============================================================ */
.lh__body { min-width: 0; }

/* The one all-caps string on the page. Caps are legible at this length and
   this weight and nowhere else, which is exactly why the eyebrow gets them
   and no heading does. */
.lh__eyebrow {
  font-size: var(--df-text-small);
  font-weight: var(--df-weight-strong);
  letter-spacing: 0.16em;
  color: var(--df-ink-muted);
}

.lh__title {
  margin-top: clamp(1rem, 0.4rem + 1.1vh, 1.75rem);
  font-family: var(--df-font-display);
  /* Ceiling paired with the 38rem column above — raise one and the headline
     wraps, so they move together or not at all. At 3.875rem the longest line
     measures ~36rem, which leaves the column two rem of slack for a longer
     word than the current copy has. */
  font-size: clamp(2.375rem, 1.35rem + 3.4vw, 3.875rem);
  font-weight: var(--df-weight-display);
  line-height: 1.06;
  letter-spacing: -0.035em;
  color: var(--df-ink-strong);
}

/* The second line, and the only gradient on the site.

   `test_landing.py` guards it: none in the HTML, and exactly one rule in this
   file. The restraint is the point — a gradient that appears twice stops
   being emphasis and becomes a texture. Two adjacent hues, not a spectrum,
   and the fallback below is a flat indigo that says the same thing. */
.lh__title-accent {
  display: block;
  color: var(--df-indigo-600);
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .lh__title-accent {
    background-image: linear-gradient(97deg,
      var(--df-indigo-600) 4%, var(--df-indigo-500) 46%, var(--df-violet-600) 96%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.lh__lede {
  margin-top: clamp(1rem, 0.4rem + 1.3vh, 1.875rem);
  max-width: 40rem;
  font-size: clamp(0.9375rem, 0.86rem + 0.26vw, 1.0625rem);
  line-height: var(--df-leading-relaxed);
  color: var(--df-ink-body);
}

/* ---------------- Actions ---------------- */
.lh__actions {
  margin-top: clamp(1.75rem, 0.4rem + 2.8vh, 3.25rem);
  display: flex;
  align-items: center;
  gap: var(--df-space-5);
  flex-wrap: wrap;
}

/* Not `.df-btn--primary`: that one is the product's indigo and it is used on
   every other public page. This is the same geometry with the page's own
   fill, so the two never have to be reconciled. */
.lh-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-3);
  height: clamp(48px, 2.4vw + 2rem, 60px);
  padding-inline: clamp(1.5rem, 0.9rem + 1vw, 2.25rem);
  border-radius: var(--df-radius-pill);
  background: var(--lh-cta-bg);
  color: var(--lh-cta-ink);
  font-size: clamp(0.9375rem, 0.88rem + 0.2vw, 1.0625rem);
  font-weight: var(--df-weight-strong);
  white-space: nowrap;
  box-shadow: var(--df-shadow);
  transition: background-color var(--df-dur-micro) var(--df-ease),
              transform var(--df-dur-micro) var(--df-ease);
}
.lh-cta:hover { background: var(--lh-cta-bg-hover); transform: translateY(-1px); }
.lh-cta:active { transform: translateY(1px); }
/* An inline box would sit on the label's baseline and ride a pixel or two
   above its optical centre — visible on a 60px pill with a 16px glyph. A flex
   box has no baseline to sit on. */
.lh-cta__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  transition: transform var(--df-dur-micro) var(--df-ease);
}
.lh-cta:hover .lh-cta__arrow { transform: translateX(4px); }

/* The play affordance. A disc and two lines of text, not a button-shaped
   thing: the primary action is already filled, and a second filled control
   would make the visitor choose between two equals. */
.lh-play {
  display: inline-flex;
  align-items: center;
  gap: var(--df-space-3);
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--df-ink-strong);
}
.lh-play__disc {
  display: grid;
  place-items: center;
  /* Matched to the CTA's clamp so the two controls share a baseline row at
     every width. */
  width: clamp(48px, 2.4vw + 2rem, 60px);
  height: clamp(48px, 2.4vw + 2rem, 60px);
  flex: none;
  border-radius: var(--df-radius-pill);
  border: var(--df-rule) solid var(--df-border-strong);
  background: var(--lh-glass-strong);
  color: var(--df-ink-strong);
  transition: border-color var(--df-dur-micro) var(--df-ease),
              background-color var(--df-dur-micro) var(--df-ease);
}
.lh-play:hover .lh-play__disc {
  border-color: var(--df-border-hover);
  background: var(--df-surface);
}
.lh-play__title {
  display: block;
  font-size: clamp(0.875rem, 0.82rem + 0.18vw, 1rem);
  font-weight: var(--df-weight-strong);
}
.lh-play__caption {
  display: block;
  margin-top: 2px;
  font-size: clamp(0.75rem, 0.71rem + 0.13vw, 0.875rem);
  color: var(--df-ink-muted);
}

/* ---------------- Micro benefits ---------------- */
.lh-benefits {
  margin: clamp(1.75rem, 0.2rem + 3.4vh, 3.75rem) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  /* Tight, because three of these have to sit on one line inside the 32rem
     column: at space-5 the third wrapped and the row stopped reading as one
     statement in three parts. */
  gap: var(--df-space-4);
}
.lh-benefit {
  display: flex;
  align-items: center;
  gap: var(--df-space-3);
  padding-left: clamp(1rem, 0.6rem + 0.6vw, 1.5rem);
  border-left: var(--df-rule) solid var(--df-border);
  font-size: clamp(0.75rem, 0.7rem + 0.14vw, 0.8125rem);
  line-height: 1.4;
  color: var(--df-ink-body);
}
/* The first item opens the row, so it has nothing to be divided from. */
.lh-benefit:first-child { padding-left: 0; border-left: 0; }
.lh-benefit__icon {
  display: grid;
  place-items: center;
  width: clamp(30px, 1.2vw + 1.25rem, 38px);
  height: clamp(30px, 1.2vw + 1.25rem, 38px);
  flex: none;
  border-radius: var(--df-radius-control);
  background: var(--df-action-soft);
  color: var(--df-action-link);
}
.lh-benefit__title { display: block; font-weight: var(--df-weight-strong); color: var(--df-ink-strong); }

/* ============================================================
   Right column — sources → intelligence core → outputs
   ============================================================ */
.lh-flow {
  position: relative;
  margin: 0;
  min-width: 0;
  display: grid;
  /* Five tracks: the source rail, the inbound wires, the core, the outbound
     wires, the output rail. The wire columns are `1fr` and therefore the
     first thing to give way at narrow widths — which is right, since a wire
     carries no words. */
  grid-template-columns:
    minmax(8.5rem, 13rem)
    minmax(2.5rem, 1fr)
    minmax(6.5rem, 11rem)
    minmax(2.5rem, 1fr)
    minmax(14rem, 23rem);
  align-items: center;
  gap: 0;
}

/* ---------------- Source rail ---------------- */
.lh-sources {
  grid-column: 1;
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: clamp(0.625rem, 0.1rem + 3.7vh, 2.875rem);
}
.lh-src {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--df-space-3);
  padding: clamp(0.5rem, 0.1rem + 1.1vh, 1.0625rem) clamp(0.75rem, 0.45rem + 0.5vw, 1.25rem);
  border: var(--df-rule) solid var(--lh-glass-edge);
  border-radius: var(--df-radius-control);
  background: linear-gradient(152deg,
    color-mix(in srgb, var(--df-surface) 92%, transparent),
    color-mix(in srgb, var(--df-surface) 58%, transparent));
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  font-size: clamp(0.75rem, 0.66rem + 0.22vw, 0.9375rem);
  font-weight: var(--df-weight-medium);
  color: var(--df-ink-strong);
  /* The lit top edge. `--lh-sheen` is white in dark and a pale indigo wash in
     light, because "where the light comes from" is the one thing that has to
     invert between the two themes for a glass surface to keep reading as
     glass. */
  box-shadow: var(--df-shadow), inset 0 var(--df-rule) 0 var(--lh-sheen);
  transition: border-color var(--df-dur-micro) var(--df-ease),
              transform var(--df-dur-micro) var(--df-ease);
}
/* The node where the card meets its wire. Sits on the card, not in the SVG:
   the SVG is stretched with `preserveAspectRatio: none` and a circle in there
   would come out an ellipse. */
.lh-src::after {
  content: "";
  position: absolute;
  right: calc(var(--df-space-1) * -1.5);
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: var(--df-radius-pill);
  background: var(--df-action);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--df-action) 16%, transparent);
}
.lh-src__icon {
  display: grid;
  place-items: center;
  width: clamp(28px, 0.6vw + 1.9vh, 42px);
  height: clamp(28px, 0.6vw + 1.9vh, 42px);
  flex: none;
  border-radius: 9px;
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--df-action) 22%, transparent),
    color-mix(in srgb, var(--df-action) 9%, transparent));
  border: var(--df-rule) solid color-mix(in srgb, var(--df-action) 20%, transparent);
  color: var(--df-action-link);
}

/* ---------------- Wires ---------------- */
/* Stretched to the gap column, so the geometry is written once in a 0–100
   space and the browser maps it to whatever width is left over.
   `preserveAspectRatio: none` distorts the curve — which is fine, it is a
   curve — but it would also distort the stroke, hence `non-scaling-stroke` on
   every path. `pathLength="100"` normalises the dash pattern the same way, so
   the travelling pulse is the same length on a 40px gap and a 200px one. */
.lh-wires {
  width: 100%;
  height: 100%;
  min-height: 1px;
  overflow: visible;
}
.lh-wires--in { grid-column: 2; }
.lh-wires--out { grid-column: 4; }

.lh-wire {
  fill: none;
  stroke: color-mix(in srgb, var(--df-action) 34%, transparent);
  stroke-width: 1;
  stroke-linecap: round;
}

/* Motion: one short lit segment travelling the length of each wire. A dash
   pattern, not a moving element — nothing is laid out, nothing reflows, and
   the whole effect is two properties. Staggered off the path's index so the
   six inbound signals never arrive in lockstep. */
.lh-wire--pulse {
  stroke: var(--df-action);
  stroke-width: 1.6;
  stroke-dasharray: 7 93;
  animation: lhPulse 3.2s linear infinite;
  animation-delay: calc(var(--lh-i) * -0.42s);
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--df-action) 55%, transparent));
}
@keyframes lhPulse {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

/* ---------------- The intelligence core ---------------- */
.lh-core {
  position: relative;
  grid-column: 3;
  justify-self: center;
  display: grid;
  place-items: center;
  width: 100%;
  max-width: clamp(7rem, 1rem + 3vw + 6vh, 13.5rem);
  aspect-ratio: 1;
  border-radius: clamp(24px, 1.2vw + 1rem, 34px);
  border: var(--df-rule) solid color-mix(in srgb, var(--df-action) 30%, transparent);
  background:
    linear-gradient(150deg,
      color-mix(in srgb, var(--df-surface) 92%, transparent),
      color-mix(in srgb, var(--df-action-soft) 78%, transparent));
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  backdrop-filter: blur(14px) saturate(130%);
  box-shadow: var(--df-shadow-lift);
}
/* Depth, made of two things only: a second pane inset behind the first, and a
   single highlight along the top edge. No bevels, no reflections, no floor. */
.lh-core::before {
  content: "";
  position: absolute;
  inset: 9px;
  border-radius: 20px;
  border: var(--df-rule) solid color-mix(in srgb, var(--df-action) 16%, transparent);
  background: color-mix(in srgb, var(--df-surface) 34%, transparent);
}
.lh-core::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(60% 50% at 50% 0%,
    color-mix(in srgb, var(--df-surface) 70%, transparent), transparent 70%);
  pointer-events: none;
}
.lh-core__mark {
  position: relative;
  z-index: var(--df-z-base);
  display: grid;
  place-items: center;
}
.lh-core__mark .df-mark {
  width: clamp(52px, 1.2vw + 3.4vh, 92px);
  height: clamp(52px, 1.2vw + 3.4vh, 92px);
}

[data-theme="dark"] .lh-src {
  background: linear-gradient(152deg,
    color-mix(in srgb, var(--df-navy-800) 94%, transparent),
    color-mix(in srgb, var(--df-navy-950) 66%, transparent));
}
[data-theme="dark"] .lh-out {
  background: linear-gradient(152deg,
    color-mix(in srgb, var(--df-navy-800) 88%, transparent),
    color-mix(in srgb, var(--df-navy-950) 74%, transparent));
}
[data-theme="dark"] .lh-src__icon {
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--df-indigo-600) 42%, transparent),
    color-mix(in srgb, var(--df-indigo-800) 26%, transparent));
  border-color: color-mix(in srgb, var(--df-indigo-500) 34%, transparent);
  color: var(--df-indigo-300);
}

[data-theme="dark"] .lh-core {
  border-color: color-mix(in srgb, var(--df-indigo-500) 42%, transparent);
  background:
    linear-gradient(150deg,
      color-mix(in srgb, var(--df-navy-800) 88%, transparent),
      color-mix(in srgb, var(--df-indigo-800) 62%, transparent));
  box-shadow:
    var(--df-shadow-lift),
    0 0 42px color-mix(in srgb, var(--df-indigo-500) 26%, transparent);
}

/* ---------------- Output panels ---------------- */
/* Stretched and spread, rather than centred with a gap of its own.

   The source rail is six cards and the output rail is three panels, so the
   two columns are never the same height — centred, the outputs sat as a short
   block in the middle while the sources ran past them top and bottom, and the
   three outbound wires (which leave at 16% / 50% / 84% of the row) pointed at
   nothing in particular. `space-between` hands the panels the height the rail
   already has and puts them where the wires arrive. It is also self-balancing:
   the gap follows the taller column instead of being a second number to keep
   in sync with it. */
.lh-outs {
  grid-column: 5;
  align-self: stretch;
  display: grid;
  grid-auto-rows: max-content;
  align-content: space-between;
  gap: clamp(0.625rem, 0.1rem + 2.6vh, 2rem);
}
/* A small, fixed stagger rather than a random one: the three panels should
   read as floating in the same system, not scattered. */
.lh-outs > :nth-child(2) { margin-left: var(--df-space-6); }
.lh-outs > :nth-child(3) { margin-left: var(--df-space-3); }

.lh-out {
  padding: clamp(0.75rem, 0.2rem + 1.5vh, 1.75rem) clamp(1rem, 0.7rem + 0.5vw, 1.5rem);
  border: var(--df-rule) solid var(--lh-glass-edge);
  border-radius: var(--df-radius-card);
  background: linear-gradient(152deg,
    color-mix(in srgb, var(--df-surface) 94%, transparent),
    color-mix(in srgb, var(--df-surface) 72%, transparent));
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: var(--df-shadow), inset 0 var(--df-rule) 0 var(--lh-sheen);
}
.lh-out__title {
  font-size: clamp(0.75rem, 0.66rem + 0.22vw, 0.9375rem);
  font-weight: var(--df-weight-strong);
  color: var(--df-ink-strong);
}
.lh-out__row {
  margin-top: clamp(0.625rem, 0.2rem + 0.9vh, 1.125rem);
  display: flex;
  align-items: center;
  gap: var(--df-space-4);
}
/* Named rather than `:first-child`, so the donut can lead its row (it does)
   without becoming the elastic one. Each panel has exactly one thing that
   takes the leftover width; the chip and the donut never do. */
.lh-bars,
.lh-spark,
.lh-legend { flex: 1 1 auto; min-width: 0; }

/* The delta chip. Green means "up" and the sign says so too, so the colour is
   never carrying the meaning on its own. */
.lh-delta {
  flex: none;
  padding: var(--df-space-2) var(--df-space-3);
  border-radius: 10px;
  background: var(--df-success-100);
  color: var(--df-success-700);
  text-align: right;
}
.lh-delta__value {
  display: block;
  font-family: var(--df-font-mono);
  font-size: clamp(0.9375rem, 0.82rem + 0.3vw, 1.25rem);
  font-weight: var(--df-weight-strong);
  font-variant-numeric: tabular-nums;
}
.lh-delta__label {
  display: block;
  margin-top: 1px;
  font-size: clamp(10px, 0.4vw + 0.4rem, 12px);
  line-height: 1.3;
  color: var(--df-ink-muted);
}

/* Bars — shape only. Heights come from `--lh-h` in the markup, which is a
   length, and the group carries no axis because there is no scale to read. */
.lh-bars {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: clamp(42px, 0.5vw + 5.4vh, 104px);
}
.lh-bars__bar {
  flex: 1 1 0;
  height: var(--lh-h);
  min-width: 2px;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(to top, var(--df-indigo-600), var(--df-indigo-500));
}
.lh-bars__bar:nth-child(n + 10) {
  background: linear-gradient(to top, var(--df-indigo-500), var(--df-violet-600));
}

/* Donut + legend */
.lh-donut {
  flex: none;
  width: clamp(62px, 0.5vw + 6.4vh, 124px);
  height: clamp(62px, 0.5vw + 6.4vh, 124px);
}
.lh-donut__track { stroke: var(--df-surface-sunk); }
.lh-legend {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: clamp(3px, 0.3vw, 6px);
  font-size: clamp(10px, 0.35vw + 0.4rem, 12px);
  color: var(--df-ink-body);
}
.lh-legend li {
  display: grid;
  grid-template-columns: 7px 1fr auto;
  align-items: center;
  gap: var(--df-space-2);
}
.lh-legend__dot {
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--lh-swatch);
}
.lh-legend__value {
  font-family: var(--df-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--df-ink-strong);
}

/* The four segment colours, named once and consumed by both the arc and its
   legend dot, so the two can never disagree. Indigo-700/100 are deliberately
   absent: the dark theme repoints both for status pills. */
.lh-seg--1 { --lh-swatch: var(--df-indigo-800); }
.lh-seg--2 { --lh-swatch: var(--df-indigo-600); }
.lh-seg--3 { --lh-swatch: var(--df-indigo-500); }
.lh-seg--4 { --lh-swatch: var(--df-teal-600); }
[data-theme="dark"] .lh-seg--1 { --lh-swatch: var(--df-indigo-500); }
[data-theme="dark"] .lh-seg--4 { --lh-swatch: var(--df-teal-400); }
.lh-donut__arc { stroke: var(--lh-swatch); }

/* Forecast sparkline — a solid past and a dashed projection, which is the
   whole reason this panel is not another bar chart. */
.lh-spark { width: 100%; height: clamp(44px, 0.5vw + 5.4vh, 104px); overflow: visible; }
.lh-spark__area { fill: color-mix(in srgb, var(--df-action) 14%, transparent); stroke: none; }
.lh-spark__line { fill: none; stroke: var(--df-action); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lh-spark__proj { fill: none; stroke: var(--df-violet-600); stroke-width: 1.6; stroke-dasharray: 3 3; stroke-linecap: round; }
[data-theme="dark"] .lh-spark__proj { stroke: var(--df-violet-300); }

/* The honesty line. The panels above carry figures, and a figure on a
   marketing page has to say where it came from — this one says it came from
   nowhere. Small, muted, and never removed. */
.lh-flow__note {
  grid-column: 1 / -1;
  margin-top: var(--df-space-6);
  font-size: clamp(0.75rem, 0.71rem + 0.12vw, 0.8125rem);
  color: var(--df-ink-muted);
  text-align: right;
}

/* ============================================================
   Responsive ladder
   ============================================================ */

/* Below the pill's own collapse width the five-track diagram has no room for
   two wire gaps. The wires go first — they are the decoration — and the three
   remaining rails stack into a single column that still reads top to bottom
   in the order the story runs: sources, core, outputs. */
@media (max-width: 78rem) {
  .lh__grid { grid-template-columns: minmax(0, 24rem) minmax(0, 1fr); gap: var(--df-space-8); }
  .lh-flow { grid-template-columns: minmax(7.5rem, 9rem) minmax(1.5rem, 1fr) minmax(5.5rem, 7rem) minmax(1.5rem, 1fr) minmax(11rem, 15rem); }
  .lh-outs > :nth-child(2),
  .lh-outs > :nth-child(3) { margin-left: 0; }
}

@media (max-width: 62rem) {
  .lh {
    min-height: 0;
    padding-block: var(--df-space-10) var(--df-space-16);
  }
  .lh__grid { grid-template-columns: minmax(0, 1fr); gap: var(--df-space-12); }
  .lh__lede { max-width: none; }

  .lh-flow {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: var(--df-space-6);
  }
  .lh-wires { display: none; }
  .lh-sources,
  .lh-core,
  .lh-outs { grid-column: 1; }
  /* Stacked there is no second column to be the taller one, so the panels go
     back to sitting on their own gap. */
  .lh-outs { align-self: auto; align-content: start; }
  /* Capped, not stretched. Left to fill the column these panels ran to 900px
     and the fourteen-bar sparkline turned into a full-width bar chart — a
     shape that now looks like it means something. The diagram is an
     illustration at every width. */
  .lh-sources,
  .lh-outs {
    width: 100%;
    max-width: 34rem;
    margin-inline: auto;
  }
  .lh-sources { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* With no wire to meet, the node has nothing to connect to. */
  .lh-src::after { display: none; }
  .lh-flow__note { text-align: center; }
}

@media (max-width: 40rem) {
  .lh__actions { gap: var(--df-space-4); }
  .lh-benefits { gap: var(--df-space-4); }
  .lh-benefit { padding-left: var(--df-space-4); }
  .lh-sources { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================
   Reduced motion — the travelling pulse is the only thing that runs on its
   own here, so it is the only thing to stop. The wires stay drawn; the
   diagram loses nothing it was using to say something.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .lh-wire--pulse { animation: none; stroke-dasharray: none; opacity: .55; }
  .lh-cta:hover,
  .lh-cta:active { transform: none; }
  .lh-cta:hover .lh-cta__arrow { transform: none; }
}
