/* ===========================================================================
   Sections — the large one-off compositions.
   Each block here appears once or twice in the site; the reusable kit is in
   components.css.
   =========================================================================== */

/* ============================================================ 1. hero ==== */

.hero {
  position: relative;
  /* Just enough to clear the fixed header — the hero art carries its own
     breathing room, so a second large pad only pushed the headline down. */
  padding-top: calc(var(--header-h) + clamp(0.75rem, 2vw, 1.75rem));
  padding-bottom: clamp(1.25rem, 2.2vw, 2.25rem);
  overflow: hidden;
  isolation: isolate;
}

.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-behind);
  pointer-events: none;
  background:
    radial-gradient(ellipse 52% 46% at 18% 42%, rgba(10, 178, 151, 0.18), transparent 68%),
    radial-gradient(ellipse 42% 40% at 77% 52%, rgba(10, 178, 151, 0.12), transparent 70%),
    linear-gradient(180deg, rgba(4, 16, 14, 0) 0%, rgba(4, 16, 14, 0.32) 78%, var(--brand-ink) 100%);
}

.hero::after {
  content: '';
  position: absolute;
  inset: auto 0 0;
  z-index: calc(var(--z-content) - 1);
  height: clamp(8rem, 18vh, 13rem);
  pointer-events: none;
  background: linear-gradient(180deg, transparent 0%, rgba(4, 16, 14, 0.78) 72%, var(--brand-ink) 100%);
}

.hero > .ambient::before {
  opacity: 0.78;
  scale: 1.12;
}

.hero > .ambient::after {
  opacity: 0.58;
  scale: 1.08;
}

.hero > .dot-field {
  opacity: 0.46;
  -webkit-mask-image: radial-gradient(ellipse 84% 64% at 52% 42%, #000 18%, transparent 72%);
  mask-image: radial-gradient(ellipse 84% 64% at 52% 42%, #000 18%, transparent 72%);
}

/* The backdrop: an ambient wash and the city line-art along the base. The
   story is told by the flow diagram in the right-hand column, so the backdrop
   only has to set a mood — a photographic render behind the copy fought it. */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: var(--z-behind);
  overflow: hidden;
  pointer-events: none;
}

/* The Mumbai waterfront line drawing, covering the whole hero with the arch
   sitting a little above centre — object-position, not a bottom anchor, is what
   keeps the landmark in the frame at any hero height.

   The artwork is black line work on WHITE paper, and that paper is the whole
   problem: any treatment that leaves it partly opaque lays a grey wash over the
   fold. So it is fully inverted (white strokes on black), tinted teal, and
   composited with screen — screen takes black to nothing, so the paper drops
   out completely and only the strokes lighten the page. The shared
   --lineart-filter only inverts to 74%, which is what left the haze.

   It is NOT blurred. A blur turns the etching into haze: the arch's lattice,
   the railing posts and the strokes on the water are the whole character of the
   drawing, and they are the first thing to go. Keeping it sharp and dropping
   the level instead is what reads as fine line work rather than fog.

   The mask is two layers intersected: the linear one clears the header and
   dissolves the base into the fold, the radial one takes a gentle edge off the
   corners. Gentle is the point — pulled down hard it strips the drawing back to
   a centre vignette and the fold loses its width. */
.hero__skyline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center 42%;
  opacity: 0.14;
  mix-blend-mode: screen;
  filter: invert(1) sepia(1) saturate(420%) hue-rotate(118deg) brightness(0.72);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 72%, transparent 100%),
    radial-gradient(ellipse 94% 78% at 54% 50%, #000 36%, rgba(0, 0, 0, 0.42) 100%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 72%, transparent 100%),
    radial-gradient(ellipse 94% 78% at 54% 50%, #000 36%, rgba(0, 0, 0, 0.42) 100%);
  mask-composite: intersect;
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.78fr);
  grid-template-rows: 1fr auto;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  min-height: min(58vh, 560px);
}

/* Centred in the grid, then lifted: an optically centred column sits slightly
   above the true middle, and it keeps the copy clear of the trust row. */
.hero__copy {
  position: relative;
  z-index: var(--z-content);
  max-width: 640px;
  margin-bottom: clamp(1.75rem, 6vh, 4rem);
}

/* ---------------------------------------------------- hero flow diagram --
   A square-ish stage with the nodes placed as percentages and the connectors
   drawn in an SVG that shares those coordinates — the same approach as the
   reach map, so a label never drifts off its wire. */

.hero__visual {
  position: relative;
  z-index: var(--z-content);
  display: grid;
  place-items: center;
}

/* The stage carries the wires' coordinate system: 915 x 1085, which is where
   every percentage below comes from. Keep the two in step if either moves. */
.hero-flow {
  position: relative;
  width: min(100%, 470px);
  aspect-ratio: 915 / 1085;
  font-size: clamp(0.75rem, 0.6vw + 0.48rem, 0.875rem);
  opacity: 0.92;
}

.hero-flow__links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Bright enough to hold their own over the skyline behind them — at the
   border-brand weight they were being swallowed by the line art. */
.hero-flow__wire path {
  fill: none;
  stroke: color-mix(in srgb, var(--brand-teal) 44%, transparent);
  stroke-width: 1.25;
  filter: drop-shadow(0 0 2px rgba(10, 178, 151, 0.26));
}

/* A short segment travelling each wire, so the diagram reads as a live route
   rather than a static org chart. Slow: this sits under a headline, and at the
   speed it first ran the eye kept being pulled off the words. */
.hero-flow__pulse path {
  fill: none;
  stroke: var(--brand-teal-bright);
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-dasharray: 6 340;
  animation: net-travel 7.5s linear infinite;
  animation-delay: calc(var(--n) * -1.2s);
  filter: drop-shadow(0 0 4px rgba(22, 217, 180, 0.62));
}

/* The centre: Vitrak itself. Three concentric layers — a dashed orbit with a
   gold satellite, a solid disc, and a bright arc sweeping the disc's edge — all
   sized off the stage width so they stay put in the wire coordinates (the orbit
   is 487 of 915 across). */
.hero-flow__core {
  position: absolute;
  left: 49.3%;
  top: 42.4%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 53.2%;
  aspect-ratio: 1;
}

.hero-flow__orbit {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--brand-teal) 32%, transparent);
  animation: spin 90s linear infinite;
}

/* The satellite rides the orbit rather than sitting beside it. */
.hero-flow__orbit::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -4px;
  width: 8px;
  height: 8px;
  translate: 50% -50%;
  border-radius: 50%;
  background: var(--brand-gold);
  box-shadow: 0 0 14px 3px rgba(255, 198, 46, 0.5);
}

/* The disc that reads as the platform itself. */
.hero-flow__ring {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--brand-teal) 45%, transparent);
  background: radial-gradient(circle at 50% 58%, rgba(10, 178, 151, 0.12) 0%, transparent 70%);
  box-shadow: inset 0 0 82px -32px rgba(10, 178, 151, 0.72), 0 0 70px -34px rgba(10, 178, 151, 0.72);
}

/* A lit arc travelling the disc's edge. Painted as a conic gradient masked to a
   2px annulus — a border can't be partially lit, and an SVG arc would need its
   own viewBox to stay circular. */
.hero-flow__sweep {
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  padding: 2px;
  background: conic-gradient(
    from 150deg,
    transparent 0deg,
    color-mix(in srgb, var(--brand-teal-bright) 35%, transparent) 26deg,
    var(--brand-teal-bright) 62deg,
    transparent 104deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  filter: drop-shadow(0 0 6px rgba(22, 217, 180, 0.6));
  animation: spin 16s linear infinite;
}

/* A second, tighter dashed ring inside the disc — the detail that stops the
   centre reading as a flat circle. */
.hero-flow__ring::before {
  content: '';
  position: absolute;
  inset: 9%;
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--brand-teal) 22%, transparent);
}

.hero-flow__mark {
  position: relative;
  width: 52%;
  height: auto;
  fill: var(--brand-teal-bright);
  filter: drop-shadow(0 0 14px rgba(10, 178, 151, 0.5));
}

.hero-flow__mark .is-gold {
  fill: var(--brand-gold);
}

/* --- the labelled nodes ------------------------------------------------- */

.hero-flow__node,
.hero-flow__chip {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.6em 0.85em;
  border-radius: var(--radius-md);
  border: 1px solid rgba(150, 220, 208, 0.16);
  background: rgba(10, 28, 25, 0.58);
  -webkit-backdrop-filter: blur(12px) saturate(125%);
  backdrop-filter: blur(12px) saturate(125%);
  box-shadow: 0 16px 36px -24px rgba(0, 0, 0, 0.85), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  white-space: nowrap;
  animation: hero-in 800ms var(--ease-out) backwards;
  animation-delay: calc(var(--n) * 110ms + 420ms);
}

.hero-flow__node b {
  display: block;
  font-size: 1em;
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
  line-height: 1.25;
}

.hero-flow__node small {
  display: block;
  font-size: 0.85em;
  color: var(--text-muted);
}

.hero-flow__icon {
  display: grid;
  place-items: center;
  width: 2.1em;
  height: 2.1em;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
}

.hero-flow__icon svg {
  width: 1.15em;
  height: 1.15em;
  color: var(--color-primary);
}

.hero-flow__chip {
  border-radius: var(--radius-pill);
  padding: 0.5em 0.9em;
  font-size: 0.95em;
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}

.hero-flow__chip svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
  color: var(--color-primary);
}

/* The closing node of the loop, so it carries a little more weight than the
   status chip above it — and a live bar chart rather than a static glyph. */
.hero-flow__chip--growth {
  padding: 0.6em 1.1em;
  font-size: 1.08em;
}

.hero-flow__bars {
  display: flex;
  align-items: flex-end;
  gap: 2.5px;
  height: 1.35em;
  flex: none;
}

.hero-flow__bars i {
  width: 3.5px;
  height: var(--h);
  border-radius: 1px;
  background: var(--brand-teal-bright);
  transform-origin: bottom;
  animation: bar-grow 2.8s var(--ease-in-out) infinite;
  animation-delay: calc(var(--n) * 220ms);
}

.hero-flow__bars .is-gold {
  background: var(--brand-gold);
}

/* Placed against the wire coordinates in .hero-flow__links — every one of
   these sits on the spine of the loop. */
.hero-flow__node--brand {
  top: 0;
  left: 49.3%;
  translate: -50% 0;
}


.hero-flow__node--a {
  top: 69.6%;
  left: 0;
}

.hero-flow__node--b {
  top: 78.3%;
  left: 49.3%;
  translate: -50% 0;
}

.hero-flow__node--c {
  top: 69.6%;
  right: 0;
}

.hero-flow__chip--growth {
  top: 94%;
  left: 49.3%;
  translate: -50% 0;
}

.hero__title {
  margin-top: var(--sp-6);
  font-size: var(--fs-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
  /* wipes up from the baseline on load; see animations.css */
  animation: headline-in 1000ms var(--ease-out) 260ms backwards;
}

/* The gradient falls on "trusted distributors" — the promise the whole site
   is built on — and the line breaks are left to text-wrap: balance rather
   than being forced, so the block stays even at every width. */
.hero__title .gradient-text {
  display: inline;
}

/* Hand-drawn gold underline, as an inline SVG under the final word only.
   Scoping it to the last word is what lets the wrapper be inline-block: the
   headline still wraps freely between words, and "distributors" alone fits
   even at 320px, where "trusted distributors" as one unbreakable box would
   overflow.

   It is a STROKED centreline with round caps, not a filled ribbon: a filled
   taper comes to a sharp point at each end, which reads as a wedge rather than
   a marker stroke. preserveAspectRatio="none" would squash the stroke into an
   ellipse, so non-scaling-stroke keeps it an even weight — and the width is in
   em, so it tracks the headline down to mobile. The old reason for filling it
   (stroke-dasharray resolves in screen px under non-scaling-stroke, which broke
   the draw-in) no longer applies: the reveal is a clip-path on the svg. */
.hero__lead {
  margin-top: var(--sp-6);
  font-size: var(--fs-lead);
  color: color-mix(in srgb, var(--text-secondary) 86%, #ffffff);
  max-width: 54ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
}

/* The tab-panel copy column: a lead paragraph directly under a sub-heading. */
.audience__lead {
  margin-top: var(--sp-4);
  font-size: var(--fs-lead);
  color: var(--text-secondary);
  max-width: 54ch;
}

/* Glass chips rather than a row of plain labels. They sit directly on the
   hero artwork, so a translucent surface both lifts them off the render and
   keeps them readable wherever the image happens to be busy. */
.hero__trust {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  max-width: min(100%, 720px);
}

.hero__trust li {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.36rem 0.85rem 0.36rem 0.36rem;
  border-radius: var(--radius-pill);
  /* The chips sit on photography, where a 16%-alpha hairline disappeared.
     A teal-tinted border at full strength keeps the pill shape readable
     against both the dark sky and the lit buildings behind it. */
  border: 1px solid rgba(150, 220, 208, 0.42);
  background: rgba(8, 31, 28, 0.62);
  -webkit-backdrop-filter: blur(12px) saturate(130%);
  backdrop-filter: blur(12px) saturate(130%);
  box-shadow: 0 10px 24px -18px rgba(0, 0, 0, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
  white-space: nowrap;
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.hero__trust li:hover {
  border-color: var(--border-brand);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md), inset 0 1px 0 color-mix(in srgb, var(--text-primary) 12%, transparent);
}

/* The glyph sits in its own tinted disc — box-sizing is border-box globally,
   so padding on the svg makes the badge without an extra wrapper element. */
.hero__trust svg {
  width: 26px;
  height: 26px;
  padding: 5px;
  border-radius: 50%;
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
  color: var(--color-primary);
  flex: none;
}

/* ========================================================= 2. pillars ==== */

.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  border-top: 1px solid var(--border-color);
  border-left: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-surface);
}

.pillar {
  position: relative;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-right: 1px solid var(--border-color);
  border-bottom: 1px solid var(--border-color);
  transition: background-color var(--dur) var(--ease-out);
}

.pillar:hover {
  background: var(--bg-brand-subtle);
}

/* The rule slides in from the left on hover — a small, cheap reward. */
.pillar::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--grad-brand);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform var(--dur) var(--ease-out);
}

.pillar:hover::before {
  transform: scaleY(1);
}

.pillar__num {
  font-family: var(--font-display);
  font-size: 0.875rem;
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  color: var(--color-accent-text);
}

.pillar__title {
  margin-top: var(--sp-4);
  font-size: var(--fs-h4);
}

.pillar__text {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

.pillars-section {
  padding-bottom: clamp(2rem, 3.6vw, 3rem);
}

.pillars-section .section-head {
  margin-bottom: clamp(2rem, 3.4vw, 3.5rem);
}

.pillars-section .pillars {
  background: #ffffff;
  border-color: #dbe9e6;
  box-shadow: 0 20px 55px -34px rgba(6, 32, 28, 0.24);
}

.pillars-section .pillar {
  background: #ffffff;
  border-color: #dbe9e6;
}

.pillars-section .pillar:hover {
  background: #f6fbfa;
}

.category-strip {
  padding-top: 0;
  padding-bottom: clamp(2.5rem, 4vw, 4.25rem);
}

.category-chip-rail {
  overflow: hidden;
  scrollbar-width: none;
  -webkit-mask-image: none;
  mask-image: none;
}

.category-chip-rail::-webkit-scrollbar {
  display: none;
}

.category-chip-track {
  gap: clamp(0.65rem, 1.2vw, 1rem);
  padding: 0.25rem 0 0.9rem;
}

.category-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65em;
  min-width: clamp(170px, 15vw, 232px);
  padding: 0.95rem 1.55rem;
  border-radius: var(--radius-pill);
  border: 1px solid color-mix(in srgb, var(--brand-teal) 78%, #ffffff);
  background: var(--brand-teal);
  box-shadow: 0 12px 30px -18px rgba(10, 178, 151, 0.7);
  color: var(--brand-ink);
  font-size: clamp(0.9375rem, 1vw, 1.0625rem);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.category-chip::before {
  content: '';
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand-ink) 82%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, #ffffff 28%, transparent);
}

/* ======================================================= 3. ecosystem ==== */

/* Stretch, not centre: the panel matches the ladder's height so the two
   columns start and end on the same lines. It also pins the panel height —
   every step's copy fits inside the ladder's height, so switching tabs no
   longer resizes the block. */
.eco {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: stretch;
}

.eco__stage {
  position: relative;
  display: grid;
  gap: var(--sp-4);
}

/* Each rung of the ladder is a button so the whole thing is keyboard-driven. */
.eco__node {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  padding: clamp(1rem, 2vw, 1.4rem) clamp(1.1rem, 2.2vw, 1.6rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  text-align: left;
  transition: all var(--dur) var(--ease-out);
}

.eco__node::after {
  /* connector down to the next rung */
  content: '';
  position: absolute;
  left: calc(clamp(1.1rem, 2.2vw, 1.6rem) + 23px);
  top: 100%;
  width: 2px;
  height: var(--sp-4);
  background: var(--border-strong);
}

.eco__node:last-of-type::after {
  display: none;
}

.eco__node[aria-selected='true'] {
  border-color: var(--brand-teal);
  background: var(--bg-brand-subtle);
  box-shadow: var(--shadow-brand);
  transform: translateX(6px);
}

.eco__node:hover:not([aria-selected='true']) {
  border-color: var(--border-strong);
  transform: translateX(3px);
}

.eco__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--bg-page-alt);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  transition: all var(--dur) var(--ease-out);
}

.eco__icon svg {
  width: 22px;
  height: 22px;
}

.eco__node[aria-selected='true'] .eco__icon {
  background: var(--brand-teal);
  border-color: var(--brand-teal);
  color: var(--brand-ink);
}

.eco__name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-heading);
  color: var(--text-primary);
}

.eco__role {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-top: 2px;
}

/* The quotation glyph reused from the existing site's icon set. */
.quote-mark {
  width: 44px;
  height: auto;
  margin-bottom: var(--sp-6);
  opacity: 0.9;
}

.eco__panel {
  position: relative;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.eco__panel::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 60% at 80% 0%, var(--glow-a), transparent 62%);
  pointer-events: none;
}

.eco__panel-body > * {
  position: relative;
}

.eco__panel-body[hidden] {
  display: none;
}

.eco__panel-title {
  font-size: var(--fs-h3);
  margin-top: var(--sp-4);
}

.eco__panel-text {
  margin-top: var(--sp-4);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
}

.eco__panel-list {
  display: grid;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--border-color);
}

.eco__panel-list li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

.eco__panel-list li::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-primary-fill);
  flex: none;
  margin-top: 0.55em;
}

/* ======================================================== 4. audience ==== */

.audience__switch {
  display: flex;
  justify-content: center;
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

.audience__panel[hidden] {
  display: none;
}

.audience__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}

.audience__art {
  position: relative;
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--border-color);
  background: var(--bg-page-alt);
  box-shadow: var(--shadow-md);
}

.audience__art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 4 / 3;
}

.audience__art figcaption {
  position: absolute;
  left: var(--sp-4);
  right: var(--sp-4);
  bottom: var(--sp-4);
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-md);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}

.audience__benefits {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}

.benefit {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
}

.benefit__mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
  color: var(--color-primary);
  font-size: 0.75rem;
  font-weight: var(--fw-bold);
}

.benefit__mark svg {
  width: 17px;
  height: 17px;
}

.benefit h3 {
  font-size: 1rem;
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
}

.benefit p {
  margin-top: 3px;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* =========================================================== 5. steps ==== */

.steps {
  --sgap: var(--sp-5);
  --scols: 5;
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--scols), minmax(0, 1fr));
  gap: var(--sgap);
}

/* The rail sits behind the markers; --p (0→1) is driven by an
   IntersectionObserver so the line draws itself as the section arrives. */
/* Inset to the first and last marker centres — see .journey::before. */
.steps__rail {
  position: absolute;
  left: calc((100% - (var(--scols) - 1) * var(--sgap)) / (var(--scols) * 2));
  right: calc((100% - (var(--scols) - 1) * var(--sgap)) / (var(--scols) * 2));
  top: 26px;
  height: 2px;
  background: var(--border-color);
  border-radius: 2px;
  overflow: hidden;
}

.steps__rail::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grad-brand-gold);
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  transition: transform 1.6s var(--ease-out);
}

.step {
  position: relative;
  text-align: center;
}

.step__marker {
  position: relative;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin-inline: auto;
  border-radius: 50%;
  border: 2px solid var(--border-color);
  /* opaque: the rail runs behind this and must not show through */
  background: var(--band-bg, var(--bg-page));
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: var(--fw-bold);
  color: var(--text-muted);
  transition: all var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--n) * 240ms);
}

/* The tint is layered OVER the opaque band colour rather than replacing it —
   --bg-brand-subtle is translucent on dark, and on its own it let the rail
   draw straight through the middle of every circle. */
.steps.is-active .step__marker {
  border-color: var(--brand-teal);
  background: linear-gradient(var(--bg-brand-subtle), var(--bg-brand-subtle)),
    var(--band-bg, var(--bg-page));
  color: var(--color-primary);
}

.steps.is-active .step:last-child .step__marker {
  border-color: var(--brand-gold);
  background: linear-gradient(var(--bg-gold-subtle), var(--bg-gold-subtle)),
    var(--band-bg, var(--bg-page));
  color: var(--color-accent-text);
}

.step__title {
  margin-top: var(--sp-5);
  font-size: var(--fs-h4);
}

.step__text {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
  max-width: 24ch;
  margin-inline: auto;
}

/* =========================================================== 6. bento ==== */

.bento {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.85rem, 1.6vw, 1.25rem);
}

.bento > * {
  position: relative;
  /* Tighter than a plain card: the lead tile's height is set by the two tiles
     stacked beside it, so every pixel of padding there becomes dead space
     inside the lead. */
  padding: clamp(1.15rem, 1.9vw, 1.55rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.bento > *:hover {
  transform: translateY(-3px);
  border-color: var(--border-brand);
  box-shadow: var(--shadow-md);
}

/*  ┌───────────────────┬─────────┐
    │ discovery (lead)  │ verify  │
    │                   ├─────────┤
    │                   │ campaign│
    ├──────────┬────────┴─────────┤
    │ insights │ secure comms     │
    └──────────┴──────────────────┘                                          */
.bento__lead {
  grid-column: span 4;
  grid-row: span 2;
  display: flex;
  flex-direction: column;
  min-height: 340px;
}

.bento__sm {
  grid-column: span 2;
}

.bento__mid {
  grid-column: span 2;
}

.bento__wide {
  grid-column: span 4;
}

.bento__eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-primary);
}

.bento h3 {
  margin-top: var(--sp-3);
  font-size: var(--fs-h4);
}

.bento__lead h3 {
  font-size: var(--fs-h3);
}

.bento__lead--static,
.bento__lead--static .mock-row {
  transition: none;
}

.bento p {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* The row of plain cards that continues the bento below it — same gutter, so
   the two read as one block. */
.bento-tail {
  margin-top: clamp(0.85rem, 1.6vw, 1.25rem);
}

/* A search-result mock built from real product vocabulary. */
.bento__mock {
  margin-top: auto;
  padding-top: var(--sp-4);
  display: grid;
  gap: var(--sp-2);
}

.mock-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-color);
  background: var(--bg-page-alt);
  font-size: var(--fs-xs);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

.bento__lead:hover .mock-row {
  border-color: var(--border-brand);
}

.bento__lead--static:hover .mock-row {
  border-color: var(--border-color);
  transform: none;
}

.bento__lead:hover .mock-row:nth-child(1) {
  transform: translateX(4px);
}
.bento__lead:hover .mock-row:nth-child(2) {
  transform: translateX(7px);
}
.bento__lead:hover .mock-row:nth-child(3) {
  transform: translateX(4px);
}

.bento__lead--static:hover .mock-row:nth-child(1),
.bento__lead--static:hover .mock-row:nth-child(2),
.bento__lead--static:hover .mock-row:nth-child(3) {
  transform: none;
}

.mock-row__avatar {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
  flex: none;
}

.mock-row b {
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}

.mock-row span {
  color: var(--text-muted);
}

.mock-row .pill {
  margin-left: auto;
  padding: 0.25em 0.6em;
  font-size: 0.6875rem;
}

/* Verification shield art in the small tile. */
.bento__shield {
  width: 74px;
  margin: var(--sp-5) auto 0;
  animation: float-y 5.5s var(--ease-in-out) infinite;
}

/* A search-field mock heading the result rows. */
.mock-search {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-brand);
  background: var(--bg-surface);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-bottom: var(--sp-2);
}

.mock-search svg {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--color-primary);
}

.mock-search em {
  margin-left: auto;
  font-style: normal;
  font-weight: var(--fw-semibold);
  color: var(--color-primary);
}

/* Ring gauge for the campaign tile. The centre marker is what stops it
   reading as a statistic whose number has gone missing. */
.gauge-wrap {
  position: relative;
  width: 92px;
  margin: var(--sp-5) auto 0;
}

.gauge__mark {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 26px;
  height: 26px;
  color: var(--color-accent-text);
}

.gauge {
  width: 92px;
  height: 92px;
  display: block;
}

.gauge__track {
  fill: none;
  stroke: var(--border-color);
  stroke-width: 8;
}

.gauge__value {
  fill: none;
  stroke: var(--brand-gold);
  stroke-width: 8;
  stroke-linecap: round;
  stroke-dasharray: 226;
  stroke-dashoffset: 226;
  transform: rotate(-90deg);
  transform-origin: center;
  transition: stroke-dashoffset 1.6s var(--ease-out);
}

.is-revealed .gauge__value {
  stroke-dashoffset: 70;
}

/* Mini bar chart for the insights tile. */
.minibars {
  display: flex;
  align-items: flex-end;
  gap: 7px;
  height: 82px;
  margin-top: var(--sp-6);
}

.minibars i {
  flex: 1;
  border-radius: 4px 4px 2px 2px;
  background: linear-gradient(180deg, var(--brand-teal), color-mix(in srgb, var(--brand-teal) 30%, transparent));
  height: 12%;
  transition: height 1s var(--ease-out);
  transition-delay: calc(var(--n) * 90ms);
}

.is-revealed .minibars i {
  height: var(--h);
}

.minibars i:last-child {
  background: linear-gradient(180deg, var(--brand-gold), color-mix(in srgb, var(--brand-gold) 30%, transparent));
}

/* Masked-call visual for the secure-comms tile. */
.masked-call {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
  padding: var(--sp-4);
  border-radius: var(--radius-md);
  background: var(--bg-page-alt);
  border: 1px solid var(--border-color);
}

.masked-call__dial {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--brand-teal);
  color: var(--brand-ink);
  position: relative;
}

.masked-call__dial svg {
  width: 20px;
  height: 20px;
}

.masked-call__dial::after {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1.5px solid var(--brand-teal);
  animation: ping 2.6s var(--ease-out) infinite;
}

.masked-call__num {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

.masked-call__note {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-top: 2px;
}

.masked-points {
  display: grid;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

.masked-points li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}

.masked-points svg {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--color-primary);
}

/* ======================================================== 7. showcase ==== */
/* The distributor app, on the dark band. */

.showcase {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: center;
}

.showcase__device {
  position: relative;
  display: grid;
  place-items: center;
}

.showcase__device img {
  width: min(100%, 280px);
  filter: drop-shadow(0 40px 60px rgba(0, 0, 0, 0.55));
  transform: translateY(var(--shift, 0));
  will-change: transform;
}

/* Halo behind the phone. */
.showcase__device::before {
  content: '';
  position: absolute;
  width: 108%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(10, 178, 151, 0.28), transparent 62%);
  pointer-events: none;
}

/* Side by side, the phone takes its height from the copy column rather than a
   fixed width, so the two halves start and finish on the same lines whatever
   the feature list holds — four items here, six on the distributors page.
   The img is taken out of flow so it contributes nothing to the row height:
   the copy sets that, and the phone then fills it. */
@media (min-width: 1025px) {
  .showcase__device {
    align-self: stretch;
  }

  .showcase__device img {
    position: absolute;
    inset: 0;
    margin: auto;
    width: auto;
    height: 100%;
    max-width: 100%;
  }
}

.showcase__features {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
}

.showcase__feature {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  transition: all var(--dur) var(--ease-out);
}

.showcase__feature:hover {
  border-color: var(--border-color);
  background: var(--bg-surface);
}

.showcase__feature svg {
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 2px;
  color: var(--brand-teal-bright);
}

.showcase__feature h3 {
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: var(--fw-semibold);
}

.showcase__feature p {
  margin-top: 3px;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* ========================================================== 8. reach ===== */
/* India map with city nodes. Percentages are eyeballed against the artwork —
   this is an illustration of geographic spread, not a data map. */

.reach {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}

.reach__map {
  position: relative;
  width: min(100%, 460px);
  margin-inline: auto;
}

#reach .reach__map {
  padding: 0;
}

#reach .reach__map::before {
  content: '';
  position: absolute;
  inset: clamp(-1rem, -2.4vw, -1.75rem);
  border: 1px solid #d9e8e4;
  border-radius: var(--radius-xl);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0%, rgba(248, 252, 251, 0.96) 100%),
    radial-gradient(ellipse 80% 64% at 50% 45%, rgba(10, 178, 151, 0.1), transparent 68%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 18px 48px -34px rgba(6, 32, 28, 0.24);
  pointer-events: none;
}

/* The artwork is a teal silhouette at ~10% alpha on transparency. Colour
   filters can't rescue that on either theme because the problem is opacity,
   not hue — so the alpha itself is multiplied up (values above 1 are legal
   and clamp at fully opaque). */
.reach__map > img {
  width: 100%;
  filter: var(--map-filter);
  transition: filter var(--dur) var(--ease-out);
}

/* Arcs radiating from the HQ. They draw themselves in as the block reveals. */
.reach__web {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.reach__arc {
  fill: none;
  stroke: color-mix(in srgb, var(--brand-teal) 50%, transparent);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1.4s var(--ease-out);
  transition-delay: calc(var(--n) * 110ms + 200ms);
}

.reach__map.is-revealed .reach__arc {
  stroke-dashoffset: 0;
}

.reach__pin {
  position: absolute;
  width: 11px;
  height: 11px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--brand-teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-teal) 22%, transparent);
}

.reach__pin::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1.5px solid var(--brand-teal);
  animation: ping 3s var(--ease-out) infinite;
  animation-delay: calc(var(--n) * 400ms);
}

.reach__pin--dot {
  width: 9px;
  height: 9px;
  background: var(--brand-teal);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--n) * 110ms + 900ms);
}

.reach__map.is-revealed .reach__pin--dot {
  opacity: 1;
}

.reach__pin--hq {
  background: var(--brand-gold);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand-gold) 26%, transparent);
  width: 14px;
  height: 14px;
}

.reach__pin--hq::after {
  border-color: var(--brand-gold);
}

.reach__pin span {
  position: absolute;
  left: 50%;
  top: calc(100% + 7px);
  transform: translateX(-50%);
  font-size: 0.6875rem;
  font-weight: var(--fw-semibold);
  color: var(--text-secondary);
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}

.reach__pin:hover span,
.reach__pin--hq span {
  opacity: 1;
}

/* ========================================================== 9. flow ====== */
/* Campaign lifecycle — a horizontal chain of stages. */

.flow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: var(--sp-4);
}

.flow__stage {
  position: relative;
  padding: clamp(1.1rem, 2vw, 1.5rem);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  transition: all var(--dur) var(--ease-out);
}

.flow__stage:hover {
  border-color: var(--border-brand);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

/* Chevron linking one stage to the next. Hidden on the last, and on wrap. */
.flow__stage:not(:last-child)::after {
  content: '';
  position: absolute;
  right: calc(var(--sp-4) * -1);
  top: 50%;
  width: var(--sp-4);
  height: 1px;
  background: var(--border-strong);
}

.flow__n {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--brand-teal-deep);
  border: 1px solid var(--brand-teal-deep);
  font-size: 0.75rem;
  font-weight: var(--fw-bold);
  color: #ffffff;
  /* Grows from its left edge on hover rather than its centre, so the disc
     never creeps back into the card's padding. */
  transform-origin: left center;
  transition: transform var(--dur) var(--ease-spring), background var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.flow__stage:hover .flow__n {
  transform: scale(1.22);
  background: var(--brand-teal);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--brand-teal) 15%, transparent);
}

.flow__stage h3 {
  margin-top: var(--sp-4);
  font-size: 1rem;
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
}

.flow__stage p {
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* ========================================================= 9b. track ===== */
/* Campaign lifecycle. Deliberately NOT .flow — that component is used two
   sections later for "From enquiry to live listing", and a boxed row of five
   numbered cards twice in a row read as the same diagram repeated. No card
   chrome here: markers on a rail, with the step number as an oversized ghost
   numeral, so this reads as a campaign running its course rather than a
   checklist. */

.track {
  --track-gap: clamp(1.25rem, 2.4vw, 2rem);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 165px), 1fr));
  gap: var(--track-gap);
  list-style: none;
  padding: 0;
}

.track__step {
  position: relative;
  padding-top: var(--sp-6);
}

/* The rail segment bridging one marker to the next. Drawn per step rather than
   as one line across the whole track so it survives the grid wrapping — and
   hidden outright below 760px, where the steps stack. */
.track__step:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 13px;
  right: calc(var(--track-gap) * -1);
  top: 5px;
  height: 2px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand-teal) 45%, transparent),
    color-mix(in srgb, var(--brand-teal) 18%, transparent)
  );
}

.track__marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--brand-teal-deep);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand-teal) 15%, transparent);
  transition: transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease-out);
}

/* Sized to sit behind the title as a watermark, not to be read as a number —
   the marker and the reading order already carry the sequence. */
.track__index {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.2vw, 2.6rem);
  font-weight: var(--fw-extrabold);
  line-height: 0.9;
  letter-spacing: var(--ls-heading);
  color: color-mix(in srgb, var(--brand-teal) 30%, transparent);
  transition: color var(--dur) var(--ease-out);
}

.track__step h3 {
  margin-top: var(--sp-3);
  font-size: 1rem;
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
}

.track__step p {
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* No lift and no border to light up — the step responds by strengthening its
   own two marks instead. */
.track__step:hover .track__marker {
  transform: scale(1.35);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--brand-teal) 20%, transparent);
}

.track__step:hover .track__index {
  color: color-mix(in srgb, var(--brand-teal) 62%, transparent);
}

/* ==================================================== 10. credibility ==== */

.cred {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: var(--sp-6);
}

.cred__item {
  padding: var(--sp-6) 0;
  border-top: 2px solid var(--border-strong);
}

.cred__item strong {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: var(--fw-bold);
  letter-spacing: -0.03em;
  color: var(--text-primary);
  line-height: 1.1;
}

/* Direct child only. An unscoped `.cred__item span` also caught the
   <span data-count> that sits inside the <strong>, rendering "12" at 14px on
   its own line above a 40px "categories". */
.cred__item > span {
  display: block;
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* ============================================================ 11. CTA ==== */

.cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.cta__inner {
  position: relative;
  padding: clamp(2.25rem, 4.5vw, 4.25rem) clamp(1.5rem, 5vw, 5rem);
  border-radius: var(--radius-2xl);
  border: 1px solid rgba(150, 220, 208, 0.16);
  background: var(--brand-ink);
  overflow: hidden;
  text-align: center;
  isolation: isolate;
}

.cta__inner::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(ellipse 60% 90% at 20% 0%, rgba(10, 178, 151, 0.3), transparent 60%),
    radial-gradient(ellipse 60% 90% at 85% 100%, rgba(255, 198, 46, 0.18), transparent 62%);
}

.cta__inner::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(rgba(150, 220, 208, 0.16) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000, transparent 72%);
  mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000, transparent 72%);
}

.cta__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 3.75rem);
  font-weight: var(--fw-bold);
  line-height: 1.05;
  letter-spacing: var(--ls-display);
  color: #ffffff;
  text-wrap: balance;
}

.cta__title em {
  font-style: normal;
  background: linear-gradient(100deg, var(--brand-teal-bright), var(--brand-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.cta__text {
  margin: var(--sp-6) auto 0;
  max-width: 52ch;
  color: #a9c3be;
  font-size: var(--fs-lead);
}

.cta__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3);
  margin-top: var(--sp-10);
}

.cta__note {
  margin-top: var(--sp-6);
  font-size: var(--fs-xs);
  color: #7e9b96;
}

/* ====================================================== 12. page hero ==== */
/* Compact hero for the inner pages. */

.page-hero {
  position: relative;
  padding-top: calc(var(--header-h) + clamp(2rem, 3.6vw, 3.25rem));
  padding-bottom: clamp(2rem, 3.6vw, 3.25rem);
  overflow: hidden;
  isolation: isolate;
  border-bottom: 1px solid var(--border-color);
}

/* .page-hero__inner also carries .container, and .container centres itself
   with margin-inline:auto — so putting max-width here made every page hero a
   centred 760px column while the sections below were a left-aligned 1320px
   container, a 280px mismatch. The container keeps its own width; the
   CHILDREN are what get measured. */
.page-hero__inner {
  position: relative;
  z-index: var(--z-content);
}

.page-hero__inner > * {
  max-width: 760px;
}

.page-hero__title {
  margin-top: var(--sp-5);
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-display);
  line-height: 1.06;
}

/* A long inner-page title that would otherwise break across two lines inside
   the 760px measure. Freed to the container width from the desktop layout up,
   where it fits on one line; below that it wraps as normal. */
@media (min-width: 901px) {
  .page-hero__inner > .page-hero__title--long {
    max-width: none;
  }
}

.page-hero__lead {
  margin-top: var(--sp-5);
  font-size: var(--fs-lead);
  color: var(--text-secondary);
  max-width: 58ch;
}

.page-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
}

/* Breadcrumb-ish trail. */
.crumbs {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.crumbs a:hover {
  color: var(--color-primary);
}

.crumbs svg {
  width: 12px;
  height: 12px;
  opacity: 0.5;
}

/* ========================================================= 13. contact === */

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: start;
}

/* The "fields marked * are required" note sits between the panel heading and
   the first label; without this the three lines collide. */
.contact__form-wrap .form {
  margin-top: var(--sp-6);
}

.contact__form-wrap {
  padding: clamp(1.35rem, 2.2vw, 1.9rem);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  box-shadow: var(--shadow-md);
}

/* Two columns that finish together. The form is the taller of the two even
   after trimming, so the contact cards take equal shares of what is left over
   rather than leaving the column short. Only while the two sit side by side —
   stacked, each block keeps its natural height. */
@media (min-width: 1025px) {
  .contact {
    align-items: stretch;
  }

  .contact__aside {
    display: flex;
    flex-direction: column;
  }

  .contact__aside .contact__list {
    flex: 1;
    grid-auto-rows: 1fr;
  }
}

.contact__list {
  display: grid;
  gap: var(--sp-5);
  margin-top: var(--sp-8);
}

.contact__item {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
  padding: var(--sp-5);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

.contact__item:hover {
  border-color: var(--border-brand);
  transform: translateY(-2px);
}

.contact__item > svg {
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 2px;
  color: var(--color-primary);
}

.contact__item h3 {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
  font-size: var(--fs-eyebrow);
}

.contact__item p,
.contact__item a:not(.btn) {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

.contact__item a:not(.btn):hover {
  color: var(--color-primary);
}

.contact__people {
  display: grid;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}

.contact__person {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.contact__person b {
  font-size: var(--fs-sm);
  color: var(--text-primary);
}

.contact__person small {
  color: var(--text-muted);
  font-weight: var(--fw-medium);
}

/* ======================================================= 14. split art === */
/* Generic image-beside-copy block used on the inner pages. */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}

.split--flip .split__art {
  order: -1;
}

/* Copy on the left, a stack of cards on the right — the cards need less room
   than a full-bleed image would. */
.split--wide {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  /* top-aligned so the two eyebrows sit on the same line; the default
     centring left them staggered. */
  align-items: start;
}

/* The copy column of a split. Grid rather than flow so its leading eyebrow is
   a block-level box: as an inline-flex on a text line it picked up the
   paragraph's half-leading and sat ~9px lower than the eyebrow in the
   .mv-stack beside it, which is already a grid item. */
.split__copy {
  display: grid;
  align-content: start;
}

.split__art {
  position: relative;
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--border-color);
  background: var(--bg-page-alt);
}

.split__art img {
  width: 100%;
  aspect-ratio: 5 / 4;
  object-fit: cover;
}

.split__art--plain {
  border: 0;
  background: none;
  overflow: visible;
}

/* .split__art img forces width:100% for the cropped-photo case. Cut-out
   artwork sizes itself instead, and the per-artwork rules below have to
   out-specify that base rule — hence the descendant selectors. */
.split__art--plain img {
  width: auto;
  max-width: 100%;
  margin-inline: auto;
  aspect-ratio: auto;
  object-fit: contain;
}

/* ===========================================================================
   Inner-page blocks
   =========================================================================== */

/* ------------------------------------------------------ page-hero extras */

.crumbs-gap {
  margin-top: var(--sp-5);
}

/* A page hero carrying artwork behind the copy rather than beside it. */
.page-hero--art .page-hero__inner > * {
  max-width: 640px;
}

.page-hero__bg {
  position: absolute;
  right: -4%;
  bottom: -8%;
  width: min(620px, 52%);
  z-index: var(--z-behind);
  pointer-events: none;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(ellipse 75% 75% at 60% 50%, #000 25%, transparent 78%);
  mask-image: radial-gradient(ellipse 75% 75% at 60% 50%, #000 25%, transparent 78%);
}

/* The finance graphic is dark-on-transparent; on a pale page it needs to be
   knocked right back, and on a dark one it can carry more weight. */
[data-theme='light'] .page-hero__bg {
  opacity: 0.28;
}

.page-hero__bg--arcs {
  right: auto;
  left: 50%;
  bottom: auto;
  top: 0;
  width: min(1100px, 105%);
  transform: translateX(-30%);
  opacity: var(--lineart-opacity);
}

/* ------------------------------------------------------------ loop cards */
/* Image-topped cards for the three-stage platform loop. */

.loop-card {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
}

.loop-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-brand);
  box-shadow: var(--shadow-lg);
}

.loop-card:hover > img {
  transform: scale(1.035);
}

.loop-card__body {
  position: relative;
  padding: clamp(1.35rem, 2.4vw, 1.85rem);
}

.loop-card__step {
  position: absolute;
  top: 0;
  right: clamp(1.35rem, 2.4vw, 1.85rem);
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: #dcefe8;
  color: var(--brand-ink);
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: var(--fw-bold);
  /* A plain drop shadow, not the teal glow that used to be here — a coloured
     halo around a pale chip reads as a stray highlight. */
  box-shadow: 0 6px 16px -6px rgba(3, 14, 12, 0.55);
}

.loop-card__body h3 {
  font-size: var(--fs-h4);
  padding-right: 3rem;
}

.loop-card__body p {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* ------------------------------------------------------- artwork sizing */

.split__art--plain .shield-art {
  width: min(60%, 230px);
  animation: float-y 6s var(--ease-in-out) infinite;
}

/* The forklift is a wide cut-out on transparency; a drop-shadow gives it a
   ground plane so it doesn't float on the band. */
.split__art--plain .forklift-art {
  width: min(100%, 480px);
  filter: drop-shadow(0 26px 26px rgba(6, 32, 28, 0.22));
}

[data-theme='dark'] .split__art--plain .forklift-art {
  filter: drop-shadow(0 26px 30px rgba(0, 0, 0, 0.65));
}

.split__art--plain .container-art {
  width: min(100%, 480px);
}

/* ----------------------------------------------------- masked-call demo */

.call-demo {
  display: grid;
  place-items: center;
}

.call-demo__card {
  width: min(100%, 420px);
  padding: clamp(1.25rem, 2.5vw, 1.85rem);
  border-radius: var(--radius-xl);
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  box-shadow: var(--shadow-lg);
}

.call-demo__rows {
  margin-top: var(--sp-5);
}

.call-demo__row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0.85rem 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}

.call-demo__row svg {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--color-primary);
}

.call-demo__row em {
  margin-left: auto;
  font-style: normal;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
}

/* The bridge between the two parties — a lock on a dashed line. */
.call-demo__link {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 1rem;
}

.call-demo__link span {
  flex: 1;
  height: 1px;
  background: repeating-linear-gradient(90deg, var(--border-strong) 0 5px, transparent 5px 10px);
}

.call-demo__link svg {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--color-accent-text);
}

/* --------------------------------------------------------- insight panel */

.insight-panel {
  padding: clamp(1.25rem, 2.5vw, 1.85rem);
  background: var(--bg-surface);
}

.insight-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.insight-panel__note {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
}

.insight-panel__rows {
  display: grid;
  gap: var(--sp-5);
  margin-top: var(--sp-6);
}

.insight-row {
  display: grid;
  gap: var(--sp-2);
}

.insight-row span {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}

.insight-row i {
  display: block;
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--grad-brand);
  width: 0;
  transition: width 1.2s var(--ease-out);
  transition-delay: calc(var(--n) * 130ms);
}

.insight-panel.is-revealed .insight-row i {
  width: var(--w);
}

/* The last bar used to be amber. Against three teal bars that didn't read as
   "a fourth metric", it read as a warning state — so it stays in the family
   and separates on depth instead, running deep-teal rather than teal-to-mint. */
.insight-row:last-child i {
  background: linear-gradient(120deg, var(--brand-teal-darker), var(--brand-teal-deep));
}

/* ------------------------------------------------------ before / after */

.compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.compare__col {
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
}

.compare__col--before {
  background: var(--bg-page-alt);
}

.compare__col--after {
  background: var(--bg-surface);
  border-color: var(--border-brand);
  box-shadow: var(--shadow-md);
}

.compare__title {
  font-size: var(--fs-h4);
  margin-bottom: var(--sp-5);
}

.compare__col--after .compare__title {
  color: var(--color-primary);
}

.compare__col ul {
  display: grid;
  gap: var(--sp-4);
}

.compare__col li {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--text-secondary);
}

.compare__col li svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 1px;
  color: var(--color-primary);
}

/* Ticks on the "On Vitrak" side. These are inlined rather than <use
   href="#i-check"> on purpose: a <use> clones its symbol into a shadow tree
   that document selectors can't reach, so the earlier attempt to fill the disc
   never applied — every tick stayed the symbol's own stroked outline in
   currentColor, which is exactly why amber had no impact here. Inlined, the
   disc takes a solid --brand-teal-deep and the mark is cut out of it in white:
   a 22px badge needs the darkest step in the ramp to carry against
   --bg-surface, and white-on-deep clears AA either way. */
.compare__col--after li .tick {
  width: 22px;
  height: 22px;
  flex: none;
  margin-top: 1px;
}

.tick__disc {
  fill: var(--brand-teal-deep);
}

.tick__mark {
  fill: none;
  stroke: #ffffff;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Each tick pops in as the column arrives, top to bottom, and the mark draws
   itself inside the disc a beat later.
   Gated on .is-revealed: the column starts at opacity 0 and only fades in when
   the observer reaches it, so an ungated animation would have played itself
   out long before the tick was ever on screen. */
.compare__col--after li {
  --n: 0;
}

.reveal-up.is-revealed .compare__col--after li .tick {
  animation: tick-in 520ms var(--ease-spring) backwards;
  animation-delay: calc(var(--i, 0) * 90ms + 180ms);
}

/* The mark is ~11.4 user units long; 12 covers it, so once the animation ends
   the dash is a single unbroken stroke. */
.reveal-up.is-revealed .compare__col--after li .tick__mark {
  stroke-dasharray: 12;
  animation: tick-draw 340ms var(--ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 90ms + 330ms);
}

@keyframes tick-in {
  from {
    opacity: 0;
    transform: scale(0.4) rotate(-18deg);
  }
}

@keyframes tick-draw {
  from {
    stroke-dashoffset: 12;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal-up.is-revealed .compare__col--after li .tick,
  .reveal-up.is-revealed .compare__col--after li .tick__mark {
    animation: none;
  }

  .reveal-up.is-revealed .compare__col--after li .tick__mark {
    stroke-dasharray: none;
  }
}

/* The "before" list gets a muted dash instead of a tick. */
.compare__col--before li::before {
  content: '';
  width: 12px;
  height: 2px;
  border-radius: 2px;
  background: var(--border-strong);
  flex: none;
  margin-top: 0.62em;
}

/* -------------------------------------------------------- mission cards */

/* Gold-edged like the reference, with an amber wash rising from the base so
   the pair reads as a matched set rather than two more grey cards. */
.mv-card {
  text-align: center;
  /* Hoisted: the icon's own size and the card padding both feed the glow's
     offset below, and the light-band block retunes the icon, so all three have
     to read from one place. */
  --mv-pad: clamp(1.05rem, 1.7vw, 1.45rem);
  --mv-icon: clamp(48px, 4.2vw, 58px);
  --mv-glow: clamp(80px, 7.2vw, 100px);
  /* Tighter than the base card: the pair sits beside the idea copy and has to
     finish with it rather than run past the bottom of that column. */
  padding: var(--mv-pad);
  /* clips the tint pool below, which is wider than the card's padding box */
  overflow: hidden;
  border-color: rgba(10, 178, 151, 0.32);
  background:
    radial-gradient(ellipse 120% 90% at 50% 115%, rgba(10, 178, 151, 0.10), transparent 70%),
    var(--bg-surface);
  transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.mv-card:hover {
  border-color: rgba(10, 178, 151, 0.58);
  box-shadow: 0 22px 50px -24px rgba(10, 178, 151, 0.4);
}

/* The icons sit still at rest. A float loop and a breathing halo read as the
   mark slipping rather than responding, so nothing moves until the pointer is
   on the card — and then it is a plain zoom, the same language as .card__icon
   on the interactive cards. */
.mv-card__icon {
  position: relative;
  z-index: 1;
  width: var(--mv-icon);
  height: var(--mv-icon);
  margin: 0 auto var(--sp-3);
  object-fit: contain;
  transition: transform var(--dur) var(--ease-spring), filter var(--dur) var(--ease-out);
}

/* A soft teal pool under the icon. Idle at rest; the card's own hover is what
   lifts it, so the halo and the mark answer the same gesture instead of
   running on a timer of their own. */
.mv-card .card__icon-glow {
  position: absolute;
  left: 50%;
  /* centred on the icon: card padding plus half the icon's height */
  top: calc(var(--mv-pad) + var(--mv-icon) / 2);
  width: var(--mv-glow);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(22, 217, 180, 0.2), transparent 66%);
  /* scale, not transform: the centring above is its own `translate` property,
     so the two compose instead of one overwriting the other. */
  opacity: 0.72;
  scale: 0.94;
  transition: opacity var(--dur) var(--ease-out), scale var(--dur) var(--ease-out);
  pointer-events: none;
}

.mv-card:hover .card__icon-glow {
  opacity: 1;
  scale: 1.06;
}

.mv-card:hover .mv-card__icon {
  transform: scale(1.12);
  filter: drop-shadow(0 10px 18px rgba(10, 178, 151, 0.42));
}

.mv-card .card__title {
  margin-bottom: var(--sp-2);
}

.mv-card .card__text {
  max-width: 42ch;
  margin-inline: auto;
}

/* The values above are tuned for a dark surface, and the About band is white:
   --bg-surface IS the band colour there, so the cards had no body of their own,
   and --shadow-sm on light is too slight to draw an edge. Give them a pista
   wash and a teal edge — the same treatment every other card on these bands
   gets — so the pair reads as part of the page and not as a highlighted note.
   Flat, not washed: the pista rising from the base read as a gradient panel
   rather than a card, so the body is one tint and the edge does the work. */
.section--light .mv-card,
.section--soft .mv-card {
  border-color: rgba(10, 178, 151, 0.28);
  background: #f7fcfa;
  box-shadow: 0 1px 2px rgba(6, 32, 28, 0.04), 0 10px 24px -20px rgba(6, 32, 28, 0.18);
}

.section--light .mv-card:hover,
.section--soft .mv-card:hover {
  border-color: rgba(10, 178, 151, 0.58);
  box-shadow: 0 1px 2px rgba(6, 32, 28, 0.06), 0 16px 34px -22px rgba(0, 112, 95, 0.26);
}

/* Over the pale body rather than an ink surface, the halo needs roughly twice
   the alpha to stay visible around the icon puck. */
.section--light .mv-card .card__icon-glow,
.section--soft .mv-card .card__icon-glow {
  background: radial-gradient(circle, rgba(10, 178, 151, 0.32), transparent 68%);
}

/* The mark itself is white-and-gold line art drawn for an ink surface — the
   white strokes simply are not there on cream, which is most of why the pair
   read as empty. Same answer as .card__icon takes on these bands: sit it on
   an ink disc, teal-ringed, and the glow becomes a halo around the disc.
   The disc is border-box, so the padding is what sets the mark's own size. */
.section--light .mv-card,
.section--soft .mv-card {
  --mv-icon: clamp(66px, 5.6vw, 78px);
  --mv-glow: clamp(98px, 8.6vw, 118px);
}

.section--light .mv-card__icon,
.section--soft .mv-card__icon {
  padding: clamp(15px, 1.3vw, 18px);
  border-radius: 50%;
  background: var(--brand-ink);
  border: 1px solid rgba(10, 178, 151, 0.45);
}

.section--light .mv-card:hover .mv-card__icon,
.section--soft .mv-card:hover .mv-card__icon {
  border-color: rgba(10, 178, 151, 0.8);
  filter: drop-shadow(0 12px 22px rgba(0, 112, 95, 0.42));
}

/* ------------------------------------------------------------------- 404 */

.notfound {
  max-width: 620px;
  margin-inline: auto;
}

.notfound .eyebrow {
  justify-content: center;
}

.notfound__actions {
  justify-content: center;
}

.notfound__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4) var(--sp-8);
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: var(--sp-8);
  border-top: 1px solid var(--border-color);
}

/* ---------------------------------------------------------- journey ------ */
/* A horizontal timeline: five columns under a shared rail, the same shape as
   the "how it works" steps so the two read as one system. It stacks to two
   columns and then one, dropping the rail, at the breakpoints below. */

.journey {
  --jgap: clamp(1rem, 2vw, 1.75rem);
  --jcols: 5;
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--jcols), minmax(0, 1fr));
  gap: var(--jgap);
}

/* The rail stops at the first and last marker centres rather than running to
   the edges. With N equal columns a marker centre sits half a column in, so
   the inset is (track width) / 2N. */
.journey::before {
  content: '';
  position: absolute;
  left: calc((100% - (var(--jcols) - 1) * var(--jgap)) / (var(--jcols) * 2));
  right: calc((100% - (var(--jcols) - 1) * var(--jgap)) / (var(--jcols) * 2));
  top: 31px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--border-brand), var(--border-brand) 78%, rgba(255, 198, 46, 0.55));
}

.journey__item {
  position: relative;
  display: grid;
  gap: var(--sp-5);
  text-align: center;
}

.journey__marker {
  position: relative;
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin-inline: auto;
  border-radius: 50%;
  border: 2px solid var(--brand-teal);
  /* opaque, layered over the band colour — the rail runs behind it */
  background: linear-gradient(var(--bg-brand-subtle), var(--bg-brand-subtle)), var(--band-bg, var(--bg-page));
  color: var(--color-primary);
  font-family: var(--font-display);
  font-size: 0.9375rem;
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
}

.journey__marker svg {
  width: 24px;
  height: 24px;
}

/* Where the story lands today — and the only marker that moves, so the eye
   lands on the end of the timeline rather than the start. A slow gold halo
   breathing under the disc, and a ring pinging out of its edge. */
.journey__item--now .journey__marker {
  border-color: var(--brand-gold);
  background: linear-gradient(var(--bg-gold-subtle), var(--bg-gold-subtle)), var(--band-bg, var(--bg-page));
  color: var(--color-accent-text);
  box-shadow: 0 0 0 0 rgba(255, 198, 46, 0.35);
  animation: now-glow 3.6s var(--ease-in-out) infinite;
}

/* The ping sits BEHIND the marker (z-index: -1 against its opaque background)
   so the expanding ring reads as coming out from under the disc rather than
   crossing over the year. */
.journey__item--now .journey__marker::after {
  content: '';
  position: absolute;
  inset: -2px;
  z-index: -1;
  border-radius: 50%;
  border: 2px solid var(--brand-gold);
  animation: ping 3.6s var(--ease-out) infinite;
}

.journey__body h3 {
  font-size: var(--fs-h4);
}

/* Marker and title stay centred on the rail; the copy reads left-aligned, so
   five ragged-both-edges blocks don't fight the eye across the row. */
.journey__body p {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
  text-align: left;
  max-width: 32ch;
  margin-inline: auto;
}

/* While the five sit in one row, marker / title / copy line up as three shared
   rows rather than five independent stacks — otherwise a one-line title (Vitrak
   2.0) starts its paragraph a line above its neighbours. Subgrid needs the body
   wrapper out of the way, so it becomes display:contents and the row rhythm
   moves from the item's gap onto the children's margins. */
@media (min-width: 761px) {
  .journey {
    grid-template-rows: auto auto auto;
    row-gap: 0;
  }

  .journey__item {
    grid-row: span 3;
    grid-template-rows: subgrid;
    gap: 0;
  }

  .journey__body {
    display: contents;
  }

  .journey__body h3 {
    margin-top: var(--sp-5);
  }
}

/* Everything above was drawn against ink. On the pista band the parts land
   within a few points of each other: the disc fill is --bg-brand-subtle
   (#e2f4ef) on a #f4f8f7 band, so each marker was band-coloured with a ring
   around it, and the rail's 32%-alpha teal read as a grey hairline. White
   discs with a small lift read as beads threaded on the rail, and the rail
   runs at an alpha that survives — solid teal, since the end marker it feeds
   into is teal rather than gold on these bands. */
.section--light .journey::before,
.section--soft .journey::before {
  background: rgba(10, 178, 151, 0.55);
}

.section--light .journey__marker,
.section--soft .journey__marker {
  background: var(--band-bg, var(--bg-page));
  box-shadow: none;
}

/* Where the story lands today is the one filled disc in the row — solid teal
   with a white label, so it reads as the end of the line without needing the
   gold accent, which was a dark-band colour and barely registered on white.
   --brand-teal-deep rather than --brand-teal: white on #0ab297 is 2.7:1, which
   is why .btn--primary sets ink text on that fill; #00705f carries white at
   ~6:1 and is already the teal the years above it are set in. */
.section--light .journey__item--now .journey__marker,
.section--soft .journey__item--now .journey__marker {
  border-color: var(--brand-teal-deep);
  background: var(--brand-teal-deep);
  color: #ffffff;
  animation-name: now-glow-light;
}

.section--light .journey__item--now .journey__marker::after,
.section--soft .journey__item--now .journey__marker::after {
  border-color: rgba(10, 178, 151, 0.85);
}

/* ------------------------------------------------- idea + mission stack --- */

.mv-stack {
  display: grid;
  gap: clamp(0.85rem, 1.6vw, 1.25rem);
  align-content: start;
}

.mv-stack .eyebrow {
  margin-bottom: var(--sp-1);
}

/* ----------------------------------------------------------- rollout ----- */
/* Phased expansion, told with the real state maps: each phase shows the
   geography it covers, and dashed connectors carry the eye across the gaps
   between them — the same device the maps use internally for phase 2.
   Deliberately not the .flow / .track vocabulary used earlier on the page;
   this is a route over time, not a set of steps. */

.rollout {
  --rollout-gap: clamp(1rem, 2.6vw, 2.25rem);
  display: grid;
  /* Column weights track the artwork's aspect ratios (360x260, 640x260,
     430x520) so three very differently-shaped maps end up optically balanced
     rather than one squeezed and one adrift in whitespace. */
  grid-template-columns: 1fr 1.45fr 0.85fr;
  gap: var(--rollout-gap);
  list-style: none;
  padding: 0;
  margin: 0;
}

.rollout__phase {
  position: relative;
  text-align: center;
}

/* The maps sit on a shared baseline, so the row reads as one landscape
   instead of three floating shapes. */
.rollout__art {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: clamp(165px, 23vw, 290px);
}

/* Shrink-wraps the artwork so a label placed at a percentage lands on the map
   itself, not somewhere in the column's whitespace. */
.rollout__figure {
  position: relative;
  display: inline-block;
  line-height: 0;
}

/* State names, as on the deck. They sit over the artwork rather than inside
   the SVG files: an <img> cannot reach the page's webfont or its colours, so
   labels baked into the file would come out in a default sans. */
.rollout__label {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(-50%, -50%);
  line-height: 1;
  white-space: nowrap;
  font-size: clamp(0.625rem, 0.85vw, 0.8125rem);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.01em;
  color: var(--text-muted);
  pointer-events: none;
  opacity: 0;
  transition: opacity 500ms var(--ease-out);
  transition-delay: calc(var(--n) * 240ms + 520ms);
}

.reveal-up.is-revealed .rollout__label {
  opacity: 1;
}

.rollout__art img {
  height: clamp(120px, 15vw, 190px);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 520ms var(--ease-out), transform 620ms var(--ease-spring);
  transition-delay: calc(var(--n) * 240ms + 120ms);
}

/* India is the whole country rather than one state, so it earns more height —
   as it has on the deck this section comes from. */
.rollout__phase:last-child .rollout__art img {
  height: clamp(165px, 23vw, 290px);
}

/* The connector overlays the row and is drawn by animations.js, which measures
   where the markers inside each map actually land. Revealed by wiping a clip
   from the left rather than by animating stroke-dashoffset — the line is dashed,
   and dashoffset is already spoken for by the dash pattern itself. */
.rollout-wrap {
  position: relative;
}

.rollout__link {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 1;
}

.rollout__link-path {
  fill: none;
  stroke: var(--color-primary-fill);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 8 7;
}

/* The mask stroke only has to be fatter than the line it reveals. Its
   dash length and offset are set in JS from the measured path length. */
.rollout__link-wipe {
  fill: none;
  stroke: #ffffff;
  stroke-width: 14;
  stroke-linecap: round;
  transition: stroke-dashoffset 2s var(--ease-out) 280ms;
}

@media (prefers-reduced-motion: reduce) {
  .rollout__link-wipe {
    transition: none;
  }
}

.rollout__title,
.rollout__where,
.rollout__text {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
  transition-delay: calc(var(--n) * 240ms + 360ms);
}

.reveal-up.is-revealed .rollout__art img,
.reveal-up.is-revealed .rollout__title,
.reveal-up.is-revealed .rollout__where,
.reveal-up.is-revealed .rollout__text {
  opacity: 1;
  transform: none;
}

.reveal-up.is-revealed .rollout__phase:not(:last-child)::after {
  transform: scaleX(1);
}

.rollout__title {
  margin-top: var(--sp-4);
  font-size: var(--fs-h4);
  color: var(--color-primary);
}

.rollout__where {
  margin-top: var(--sp-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}

.rollout__text {
  margin-top: var(--sp-2);
  margin-inline: auto;
  max-width: 34ch;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------- founders ----- */

.founders {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  max-width: 720px;
  margin-inline: auto;
}

.founder {
  position: relative;
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.founder:hover {
  transform: translateY(-4px);
  border-color: var(--border-brand);
  box-shadow: var(--shadow-lg);
}

.founder img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center 22%;
}

/* Ink plate rather than white: the caption is the only part of these cards
   the site owns — the photographs come as they are — so it carries a brand
   surface instead of disappearing into the card. The base is #0c1c1a — the
   dark theme's --bg-surface, hard-coded because the band it sits in pins
   light values in both themes, so the token would resolve to white here —
   lifted with a little teal so the plate sits above the near-black backdrop
   of the photography rather than merging into it. */
.founder figcaption {
  padding: clamp(1rem, 2vw, 1.35rem);
  background: color-mix(in srgb, var(--brand-teal) 12%, #0c1c1a);
  border-top: 1px solid color-mix(in srgb, var(--brand-teal) 12%, #0c1c1a);
}

.founder strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-heading);
  color: #ffffff;
}

.founder span {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  /* Steps down from the name without dropping to a grey that would read as
     disabled on a dark plate. */
  color: rgba(255, 255, 255, 0.78);
}


/* --------------------------------------------------------- photography -- */
/* The stock photography inherited from the Figma is a mixed bag — warm
   interiors next to a cold blue composite. One tint plus reduced saturation
   pulls them onto a single palette so a row of them reads as a set rather
   than three unrelated stock images. */

.photo {
  position: relative;
  isolation: isolate;
}

.photo img {
  filter: saturate(0.45) contrast(1.06) brightness(1.02);
  /* every source is portrait or square; bias the crop upward so hands, faces
     and product stay in frame instead of being cut to a table top */
  object-position: center 34%;
}

.photo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(155deg, rgba(10, 178, 151, 0.36) 0%, rgba(10, 178, 151, 0.1) 48%, rgba(4, 16, 14, 0.34) 100%);
}

/* The caption has to sit above the tint. */
.photo figcaption {
  z-index: 2;
}

.loop-card.photo > img {
  filter: none;
  object-position: center;
}

.loop-card.photo::after {
  content: none;
}

/* Loop-card images are square-ish so all three sit at one height. */
.loop-card > img {
  aspect-ratio: 4 / 3;
  transition: transform var(--dur-slow) var(--ease-out);
  will-change: transform;
  backface-visibility: hidden;
}

/* ========================================================= 15. network === */
/* The counter band under the hero. It takes --brand-ink from .section--ink,
   which is the exact colour the hero's own backdrop fades to at its base — so
   the seam between the two is invisible and the numbers read as part of the
   fold rather than as the next section down. */

.netstat {
  /* The hero pays for the air above the seam; this band only owes the gap
     below its own content. A full --section-py here re-opened the join. */
  padding-top: clamp(1.75rem, 3.2vw, 3rem);
}

.netstat__head {
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}

.netstat__head .section-title em {
  font-style: normal;
  background: linear-gradient(100deg, var(--brand-teal-bright), var(--brand-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.netstat__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.netstat__item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

/* A single brand halo behind the icon and the figure, so the card has depth
   without a second background layer to keep in sync with the ink band.

   Sized in pixels, not percentages: on the full-width card the ≤900px layout
   makes of the third item, a percentage-sized ellipse stretched into a faint
   arc running the whole way across it. */
.netstat__item::before {
  content: '';
  position: absolute;
  top: -110px;
  left: -60px;
  width: min(300px, 85%);
  aspect-ratio: 1;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(22, 217, 180, 0.26), transparent 68%);
  pointer-events: none;
}

.netstat__item:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
  background: var(--bg-elevated);
}

.netstat__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-brand);
  background: color-mix(in srgb, var(--brand-teal) 14%, transparent);
  color: var(--brand-teal-bright);
  flex: none;
}

.netstat__icon svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --fs-numeral is the same scale the journey and bento numerals use, so the
   three big figures here match the rest of the page rather than inventing a
   size of their own. */
.netstat__value {
  display: block;
  margin-top: var(--sp-6);
  font-family: var(--font-display);
  font-size: var(--fs-numeral);
  font-weight: var(--fw-bold);
  letter-spacing: -0.04em;
  line-height: 1;
  /* The counter rewrites textContent every frame; a fixed tabular width stops
     the label below from shuffling sideways as 0 → 1,000 gains digits. */
  font-variant-numeric: tabular-nums;
  background: linear-gradient(100deg, #ffffff 10%, var(--brand-teal-bright) 55%, var(--brand-gold) 115%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.netstat__label {
  display: block;
  margin-top: var(--sp-3);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
  line-height: var(--lh-snug);
}

.netstat__note {
  margin-top: var(--sp-3);
  /* The three notes are different lengths, so this is the minimum gap above
     the line below — the line itself is pushed to the card's floor. */
  margin-bottom: var(--sp-6);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* The growth line. It shares the reveal observer's timing by hanging off
   .is-revealed on the grid above it, so the bars draw as the numbers start
   counting rather than on their own unrelated trigger. */
.netstat__bar {
  display: block;
  width: 100%;
  height: 3px;
  /* Bottom-aligned across the row: a two-line note and a three-line note
     otherwise leave the lines at two different heights. */
  margin-top: auto;
  border-radius: var(--radius-pill);
  background: var(--border-color);
  overflow: hidden;
}

.netstat__bar i {
  display: block;
  height: 100%;
  width: var(--fill, 100%);
  border-radius: inherit;
  background: linear-gradient(90deg, var(--brand-teal), var(--brand-teal-bright), var(--brand-gold));
  transform: scaleX(0);
  transform-origin: left;
}

.netstat__grid.is-revealed .netstat__bar i {
  animation: netstat-fill 1400ms var(--ease-out) forwards;
  animation-delay: calc(var(--n, 0) * 80ms + 120ms);
}

.netstat__foot {
  margin-top: var(--sp-6);
  text-align: center;
}

/* ==================================================== 16. cat strip ====== */
/* The categories marquee. It used to be a near-white band carrying twelve
   solid teal slabs — the only way to get contrast on that ground, and it read
   as a colour bar rather than a set of cards.

   Inverting the band is the fix: on ink, a translucent panel with a lit mark
   inside it has all the contrast it needs. It also gives the page a clean
   hinge — the dark half of the home page ends here and the white half starts
   at the section below. */

.cat-strip {
  overflow: hidden;
  isolation: isolate;
  /* The platform section above is --bg-page, which on the dark theme is within
     a shade of --brand-ink. Without these the strip has no edge of its own and
     reads as the bottom of that section. */
  border-block: 1px solid rgba(150, 220, 208, 0.13);
}

/* No bespoke wash: the band carries the same .dot-field over plain ink that
   the network counters do, so the two ink bands on the page are one family. */

/* A band, not a full section, so it carries its own padding rather than
   --section-py or --tight's. */
.cat-strip {
  padding-block: clamp(2rem, 3.4vw, 3rem);
}

/* One line, in the page's eyebrow treatment. It stays an <h2> so the section
   still has a name in the outline and aria-labelledby still points at a
   heading — .eyebrow only changes how it looks. */
.cat-strip__head {
  text-align: center;
  margin-bottom: clamp(1.35rem, 2.4vw, 2rem);
}

.cat-strip__head .eyebrow {
  margin: 0;
}

/* ==================================================== hero actions ======= */
/* The hero sits on artwork, not on the page background, so the shared button
   styles — which derive their edges from --border-strong on an assumed flat
   surface — came out almost edgeless here. Both buttons get their contrast
   stated explicitly instead of inherited. */

.hero__actions .btn {
  font-weight: var(--fw-semibold);
}

.hero__actions .btn--primary {
  box-shadow: 0 10px 30px -12px rgba(10, 178, 151, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.hero__actions .btn--outline {
  background: rgba(6, 26, 23, 0.58);
  -webkit-backdrop-filter: blur(12px) saturate(130%);
  backdrop-filter: blur(12px) saturate(130%);
  border-color: rgba(150, 220, 208, 0.5);
  color: #eaf5f2;
  box-shadow: 0 10px 26px -18px rgba(0, 0, 0, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.hero__actions .btn--outline:hover {
  background: rgba(10, 44, 39, 0.72);
  border-color: var(--brand-teal);
  color: #ffffff;
}

/* ======================================================== faq reveal ===== */
/* The questions are not part of the page's reading order — they are what the
   footer's "FAQ" link opens. :target rather than JS so the link still works
   with scripting off, and so the browser does the scrolling itself. */

#faq {
  display: none;
}

#faq:target {
  display: block;
}

/* While it's hidden the FAQ is still a same-coloured sibling, so the
   "two bands in a row share one gap" rule in global.css strips the top padding
   off whatever follows — leaving that section butted against the band above it
   with nothing in between. Give the padding back for as long as the FAQ is
   collapsed; once it's targeted and visible, the collapse is correct again. */
#faq:not(:target) + .section {
  padding-top: var(--section-py);
}

/* ------------------------------------------------ consultants sign-in --- */
/* The one action the consultants section carries. Centred under the card
   grid rather than left-aligned like `.app-cta`, because the heading above it
   is centred too and a flush-left button under a centred block reads as a
   stray. */

.consult-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  margin-top: clamp(2rem, 4vw, 3rem);
  text-align: center;
}

.consult-cta__note {
  max-width: 52ch;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--text-muted);
}

/* Kept whole: broken across two lines the link reads as two separate ones,
   and the underline makes the split more obvious, not less. */
.consult-cta__note a {
  color: var(--color-primary);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
