/* =============================================================
   DevStudio — bespoke page composition on NC tokens
   Loaded after styles.css; reuses :root design tokens.
   Namespace: .ds-

   TYPE SYSTEM FOR THIS PAGE
     Afacad             → headings
     Instrument Sans    → body copy
     JetBrains Mono     → the "machine voice": anything that is a
                          verifiable fact — spec clauses, artifacts,
                          gates, check names, step numbers, labels.
     Nothing decorative is set in mono. If it's mono, it's checkable.

   COLOUR LANGUAGE FOR THIS PAGE
     cyan    → intent   (what you said)
     violet  → spec     (what we wrote)
     gold    → build    (what we made)
     green   → verified (what we proved)
     magenta → drift    (reserved for the failure section only)
   ============================================================= */
.ds {
  --ds-max: var(--container-inner);
  --ds-intent: var(--color-secondary-cyan);
  --ds-spec: var(--color-secondary-violet);
  --ds-build: var(--color-secondary-gold);
  --ds-proof: var(--color-secondary-green);
  --ds-drift: var(--color-secondary-magenta);
}

.ds-section {
  padding: var(--space-8) var(--gutter) 0;
  scroll-margin-top: calc(var(--header-height) + var(--space-3));
}
.ds-section--tight { padding-top: var(--space-7); }
.ds-section--last { padding-bottom: var(--space-8); }
/* The ledger is denser than the sections around it, so it needs more
   air above and below to keep the same rhythm. */
#spec {
  padding-top: calc(var(--space-8) + var(--space-5));
  padding-bottom: var(--space-7);
}

/* ---------- Shared section chrome ---------- */
.ds-h2 {
  font-family: var(--font-title); font-weight: 700;
  font-size: var(--fs-h2);
  letter-spacing: -0.03em; line-height: 0.98;
  margin: var(--space-3) 0 0; max-width: 26ch; text-wrap: balance;
}
.ds-h2--bright { color: var(--color-on-dark); }
.ds-h2--wide { max-width: 34ch; }
.ds-sub {
  font-size: var(--fs-lead); line-height: 1.55; color: var(--color-ink-60);
  max-width: 60ch; margin: var(--space-3) 0 0; text-wrap: pretty;
}
.ds-sub--bright { color: var(--color-on-dark-muted); }
.ds-sub strong { color: var(--color-ink); font-weight: 600; }
.ds-sub--bright strong { color: var(--color-on-dark); font-weight: 600; }

.ds-head--center { text-align: center; }
.ds-head--center .ds-h2,
.ds-head--center .ds-sub { margin-inline: auto; }

/* Small mono label used inside cards ("artifact", "gate", "cause") */
.ds-tag {
  display: inline-block; font-family: var(--font-tag);
  font-size: var(--fs-tag); font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--color-ink-35);
}

/* ---------- Scroll reveal (progressive enhancement) ---------- */
.ds-js [data-ds-reveal] {
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.65s var(--ease), transform 0.65s var(--ease);
}
.ds-js [data-ds-reveal].is-in { opacity: 1; transform: none; }
.ds-js [data-ds-reveal][data-ds-delay="1"] { transition-delay: 0.08s; }
.ds-js [data-ds-reveal][data-ds-delay="2"] { transition-delay: 0.16s; }
.ds-js [data-ds-reveal][data-ds-delay="3"] { transition-delay: 0.24s; }
.ds-js [data-ds-reveal][data-ds-delay="4"] { transition-delay: 0.32s; }

/* =============================================================
   1 — HERO
   Left: the promise. Right: the build forge — four app archetypes
   that assemble themselves, growing from 3 modules at complexity
   2/6 to 6 modules at 6/6. Keeps .page-hero so js/main.js can
   toggle the header CTA.
   ============================================================= */
.ds-hero {
  position: relative; overflow-x: clip; text-align: left;
  max-width: none;
  padding: calc(var(--header-height) + var(--space-5)) var(--gutter) var(--space-7);
  /* The clip keeps the glows off the next section, but it also sliced the
     forge panel's drop shadow into a straight line. The margin lets ink
     overflow past the padding box by more than the shadow's reach
     (44px offset + 90px blur - 50px spread) while the glows, which are
     transparent at their own edges, stay invisible in the extra band.
     Bumped for the corner-seam accent: its 74vw box needs more room past
     the padding box before its (already-transparent) falloff is safe to
     hard-clip.
     X-only: clipping both axes (`overflow: clip`) let this margin leak into
     the page's real horizontal scroll width on narrow viewports. */
  overflow-clip-margin: 420px;
}
.ds-hero__glow, .ds-hero__glow--b, .ds-hero__glow--c, .ds-hero__glow--corner {
  position: absolute; z-index: 0; pointer-events: none;
}
/* Literal copy of home's hero glow recipe (css/styles.css .hero__glow /
   --lime / --violet), per the "Background glow gradient" rule — position,
   size, timing, keyframe percentage steps, hue-drift deltas, alphas and
   stop percentages are all identical to home's; only the two hues (224deg
   blue, 152deg green, from docs/_as/colors.html) and the pastel oklch
   register (L 0.9, C ~0.1-0.12) are page-specific — see css/resources.css
   for the confirmed-working reference. */
.ds-hero__glow {
  top: -24%; right: -42%;
  width: 100vw; height: 100vh;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.9 0.12 var(--g-h1, 224deg) / 0.85),
    oklch(0.9 0.1 var(--g-h2, 152deg) / 0.4) 46%,
    transparent 72%
  );
  animation:
    ds-glow-morph 11s ease-in-out infinite,
    ds-glow-float 17s ease-in-out infinite;
}
@keyframes ds-glow-morph {
  0%, 100% { --g-h1: 224deg; --g-h2: 152deg; --g-w: 44%; --g-h: 54%; --g-x: 46%; --g-y: 54%; }
  30%      { --g-h1: 260deg; --g-h2: 174deg; --g-w: 66%; --g-h: 42%; --g-x: 60%; --g-y: 40%; }
  62%      { --g-h1: 198deg; --g-h2: 126deg; --g-w: 42%; --g-h: 64%; --g-x: 40%; --g-y: 60%; }
}
@keyframes ds-glow-float {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);    filter: hue-rotate(0deg)  saturate(1); }
  50%      { transform: scale(1.22) translate3d(-8%, 6%, 0); filter: hue-rotate(14deg) saturate(1.1); }
}
/* Bottom-left blob: blue on its own, home's lime formula and delta shape. */
.ds-hero__glow--b {
  bottom: -20%; left: -22%;
  width: 60vw; height: 60vh;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.9 0.12 var(--g-h1, 224deg) / 0.4),
    transparent 66%
  );
  animation:
    ds-glow-morph-b 14s ease-in-out -5s infinite,
    ds-glow-float-b 21s ease-in-out -9s infinite;
}
@keyframes ds-glow-morph-b {
  0%, 100% { --g-h1: 224deg; --g-w: 46%; --g-h: 46%; --g-x: 50%; --g-y: 50%; }
  40%      { --g-h1: 256deg; --g-w: 68%; --g-h: 56%; --g-x: 60%; --g-y: 42%; }
  72%      { --g-h1: 202deg; --g-w: 42%; --g-h: 66%; --g-x: 40%; --g-y: 58%; }
}
@keyframes ds-glow-float-b {
  0%, 100% { transform: scale(1.06) translate3d(0, 0, 0);    filter: hue-rotate(0deg)   saturate(1); }
  50%      { transform: scale(0.84) translate3d(9%, -7%, 0); filter: hue-rotate(-12deg) saturate(1.12); }
}
/* Top-centre blob: green on its own, home's violet slot (position + timing)
   carrying a single-hue fade instead of a blend. */
.ds-hero__glow--c {
  top: -26%; left: 52%; right: auto; bottom: auto;
  width: 44vw; height: 44vh;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.9 0.1 var(--g-h1, 152deg) / 0.28),
    transparent 64%
  );
  animation:
    ds-glow-morph-c 18s ease-in-out -7s infinite,
    ds-glow-float-c 26s ease-in-out -13s infinite;
}
@keyframes ds-glow-morph-c {
  0%, 100% { --g-h1: 152deg; --g-w: 48%; --g-h: 48%; --g-x: 50%; --g-y: 50%; }
  38%      { --g-h1: 128deg; --g-w: 70%; --g-h: 42%; --g-x: 40%; --g-y: 58%; }
  70%      { --g-h1: 172deg; --g-w: 42%; --g-h: 60%; --g-x: 60%; --g-y: 44%; }
}
@keyframes ds-glow-float-c {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);     filter: hue-rotate(0deg)   saturate(1);   opacity: 1; }
  45%      { transform: scale(1.28) translate3d(-9%, 5%, 0);   filter: hue-rotate(-10deg) saturate(1.1); opacity: 0.7; }
}
/* Mandatory corner-seam accent: centred exactly on the hero's bottom-right
   corner, a quiet echo of the blue wash. */
.ds-hero__glow--corner {
  top: auto; left: auto;
  bottom: -37vw; right: -37vw; width: 74vw; height: 74vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.9 0.12 var(--g-h1, 224deg) / 0.15),
    transparent 60%
  );
  animation:
    ds-glow-morph-corner 8s ease-in-out -4s infinite,
    ds-glow-float-corner 11s ease-in-out -8s infinite;
}
@keyframes ds-glow-morph-corner {
  0%, 100% { --g-h1: 224deg; --g-w: 46%; --g-h: 46%; --g-x: 50%; --g-y: 50%; }
  50%      { --g-h1: 246deg; --g-w: 55%; --g-h: 37%; --g-x: 40%; --g-y: 60%; }
}
@keyframes ds-glow-float-corner {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);    filter: saturate(1); }
  50%      { transform: scale(1.15) translate3d(9%, -6%, 0); filter: saturate(1.05); }
}

/* Mandatory mobile override: desktop's percentage-based blob positions
   clip away on a narrow screen. */
@media (max-width: 900px) {
  .ds-hero {
    background:
      radial-gradient(120% 70% at 85% 0%, oklch(0.9 0.12 224 / 0.28), transparent 62%),
      radial-gradient(90% 55% at 10% 35%, oklch(0.9 0.1 152 / 0.19), transparent 58%),
      radial-gradient(80% 50% at 70% 18%, oklch(0.9 0.12 224 / 0.08), transparent 55%),
      var(--color-paper);
  }
  .ds-hero__glow {
    top: -8%; right: -28%; width: 100vh; height: 100vh; opacity: 1;
    background: radial-gradient(
      var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
      oklch(0.9 0.12 var(--g-h1, 224deg) / 0.45),
      oklch(0.9 0.1 var(--g-h2, 152deg) / 0.22) 42%,
      transparent 70%
    );
  }
  .ds-hero__glow--b {
    bottom: 18%; left: -35%; width: 85vh; height: 85vh;
    background: radial-gradient(
      var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
      oklch(0.9 0.12 var(--g-h1, 224deg) / 0.28),
      transparent 68%
    );
  }
  .ds-hero__glow--c {
    top: 4%; left: 42%; width: 65vh; height: 65vh;
    background: radial-gradient(
      var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
      oklch(0.9 0.1 var(--g-h1, 152deg) / 0.16),
      transparent 66%
    );
  }
}
/* The whole hero sits on one dark inset panel, capped at the page's content
   width and rounded like the closing CTA panel, per the "Section backgrounds
   never go full-bleed" rule. The pastel page glows above stay on the section
   and read around the panel; inside, a darker wash in the same two hues. */
.ds-hero__panel {
  position: relative; z-index: 1; overflow: hidden;
  max-width: var(--ds-max); margin-inline: auto;
  background: var(--color-ink); color: var(--color-on-dark);
  border-radius: var(--radius-xl);
  padding: clamp(2.5rem, 5vw, 4.5rem) clamp(1.5rem, 4vw, 4rem);
}
.ds-hero__wash {
  position: absolute; z-index: 0; pointer-events: none;
  /* Fade the box itself to transparent before its edge: the morph moves the
     gradient centre off-centre, and a clipped edge would show as a hard arc. */
  -webkit-mask-image: radial-gradient(closest-side, #000 55%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 55%, transparent 100%);
  top: -40%; left: -20%; width: 70vw; height: 70vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.72 0.17 var(--g-h1, 224deg) / 0.28),
    oklch(0.8 0.16 var(--g-h2, 152deg) / 0.12) 46%,
    transparent 70%
  );
  animation:
    ds-glow-morph-close 9s ease-in-out -3s infinite,
    ds-glow-float-close 13s ease-in-out -7s infinite;
}
.ds-hero__grid {
  position: relative; z-index: 2;
  /* Copy gets the wider column; the forge is illustration, so it takes less. */
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  /* Both columns keep their own height and centre on each other, so the
     copy and the forge share one vertical midline. */
  gap: clamp(2rem, 4.5vw, 4.25rem); align-items: center;
}

/* Desktop + mobile glyphs beside the hero eyebrow: line icons in the
   eyebrow's own colour, sized to its cap height. */
.ds-eyebrow__platforms {
  display: inline-flex; align-items: center; gap: 0.45em;
  margin-left: 0.55em; vertical-align: -0.2em;
}
.ds-eyebrow__platforms svg { width: 1.2em; height: 1.2em; flex-shrink: 0; }

.ds-hero__title {
  font-family: var(--font-title); font-weight: 700;
  /* Scaled to the copy column so the headline holds one line in EN and FR:
     beside the forge the column is ~44.5vw wide, and the FR headline is
     ~9.7x its font size wide. */
  font-size: clamp(2.5rem, 4.4vw, 4.25rem);
  line-height: 0.9; letter-spacing: -0.045em;
  color: var(--color-on-dark);
  margin: var(--space-4) 0 0; max-width: none; text-wrap: balance;
}
/* The line that carries the promise. Same ink as the title — the size
   step is what separates them, not colour. */
.ds-hero__deck {
  font-family: var(--font-title); font-weight: 600;
  font-size: clamp(1.375rem, 2.4vw, 2rem);
  line-height: 1.03; letter-spacing: -0.03em;
  color: var(--color-on-dark);
  margin: var(--space-4) 0 0; max-width: none; text-wrap: pretty;
}
.ds-hero__lead {
  font-size: var(--fs-md); line-height: 1.6; color: var(--color-on-dark-muted);
  max-width: 48ch; margin: var(--space-4) 0 0; text-wrap: pretty;
}
.ds-hero__lead strong { color: var(--color-on-dark); font-weight: 600; }
.ds-hero__cta { margin-top: var(--space-6); display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }

/* Screen-reader equivalent for the decorative forge animation. */
.ds-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---------- SIGNATURE: the build forge ----------
   Any app, any complexity. Four archetypes rotate; each one names
   its modules, builds them in with a stagger, fills a bar per
   module and ticks it off. The complexity meter and the module
   count are what carry the claim — small builds look small.

   The panel runs the full height of the copy beside it, and every
   scene fills that height: three rows of equal-height modules, one
   column when the build has three modules and two when it has six.
   Each module carries what it actually covers, so the cards are
   sized by their content rather than padded out with dead space. */
.ds-forge {
  /* One inset for the whole panel: the top bar, the stage and the foot
     all sit on it, so the cards line up with the bar's file name. */
  --ds-forge-pad: 1.5rem;
  /* The modules are sized by the panel, not the window: the panel is half
     the hero grid, so it narrows well before any viewport breakpoint does. */
  container-type: inline-size; container-name: forge;
  position: relative;
  display: flex; flex-direction: column;
  /* Wireframe: no fill of its own, the hero panel's ink shows through and
     every surface inside is drawn with a 1px line. */
  background: transparent; color: var(--color-on-dark);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.ds-forge > * { position: relative; z-index: 1; }
/* The module icons live in one sprite at the top of the panel and
   are pulled in with <use>. It renders nothing itself. */
.ds-forge__icons { width: 0; height: 0; flex: 0 0 0; overflow: hidden; }

/* Top bar: what is being built, and how hard it is */
.ds-forge__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
  padding: 0.95rem var(--ds-forge-pad);
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
  font-family: var(--font-mono); font-size: 0.75rem;
}
.ds-forge__file { color: var(--color-on-dark-muted); }
.ds-forge__slugs { position: relative; }
.ds-forge__slug { display: none; color: var(--color-on-dark); }
.ds-forge__slug.is-active { display: inline; }

.ds-forge__cx {
  display: inline-flex; align-items: center; gap: 0.6em;
  font-size: var(--fs-label-xs); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--color-on-dark-muted);
}
.ds-forge__cxbars { display: inline-flex; gap: 3px; }
.ds-forge__cxbar {
  width: 12px; height: 5px; border-radius: 1px; box-sizing: border-box;
  background: transparent; border: 1px solid rgba(255, 255, 255, 0.28);
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease);
}
/* Filled segments follow data-cx on the forge, which the script walks
   between 0 and 6. At 0 nothing matches and the meter reads empty. */
.ds-forge[data-cx="1"] .ds-forge__cxbar:nth-child(-n + 1),
.ds-forge[data-cx="2"] .ds-forge__cxbar:nth-child(-n + 2),
.ds-forge[data-cx="3"] .ds-forge__cxbar:nth-child(-n + 3),
.ds-forge[data-cx="4"] .ds-forge__cxbar:nth-child(-n + 4),
.ds-forge[data-cx="5"] .ds-forge__cxbar:nth-child(-n + 5),
.ds-forge[data-cx="6"] .ds-forge__cxbar:nth-child(-n + 6) {
  background: var(--ds-proof); border-color: var(--ds-proof);
}

/* Stage: takes whatever height the panel has, with a floor tall
   enough that a row still fits a name, its line of detail, the
   stage label and the bar when nothing is stretching the panel. */
.ds-forge__stage {
  --ds-rows: 3; --ds-modh: 7rem; --ds-modgap: 0.75rem;
  position: relative;
  flex: 1 1 auto;
  margin: var(--ds-forge-pad);
  min-height: calc(var(--ds-rows) * var(--ds-modh) + (var(--ds-rows) - 1) * var(--ds-modgap));
}
/* Rows are equal and always fill the stage. Column count is the
   only thing a scene changes, so every archetype lands on the same
   baseline grid however many modules it has. */
.ds-forge__scene {
  --ds-cols: 2;
  position: absolute; inset: 0;
  display: none;
  grid-template-columns: repeat(var(--ds-cols), minmax(0, 1fr));
  grid-template-rows: repeat(var(--ds-rows), minmax(0, 1fr));
  gap: var(--ds-modgap);
}
.ds-forge__scene[data-mods="3"] { --ds-cols: 1; }
/* A full-width row is too wide to read as a stacked card, so the
   icon and text take the left half and the bar runs down the right. */
@media (min-width: 561px) {
  .ds-forge__scene[data-mods="3"] .ds-mod {
    align-items: center; align-content: center; column-gap: 1rem;
    /* The readout holds mono text that only breaks at spaces, so it takes
       the larger share — below roughly 145px it wraps past the row height. */
    grid-template-columns: auto minmax(0, 0.9fr) minmax(0, 1.1fr);
    grid-template-rows: auto auto;
  }
  .ds-forge__scene[data-mods="3"] .ds-mod__icon {
    --ds-icon-size: 46px; grid-row: 1 / span 2; align-self: center;
  }
  .ds-forge__scene[data-mods="3"] .ds-mod__name { grid-column: 2; align-self: end; }
  .ds-forge__scene[data-mods="3"] .ds-mod__desc { grid-column: 2; align-self: start; }
  /* Stage, bar and readout stack as one block in the right column, so
     the spacing between them holds however tall the row gets. */
  .ds-forge__scene[data-mods="3"] .ds-mod__meta {
    display: flex; flex-direction: column;
    grid-column: 3; grid-row: 1 / -1; align-self: center;
    /* The column is centred, so the bar can land at the same height as
       the tick in the corner. Keep it out of that lane. */
    padding-right: 0.9rem;
  }
  .ds-forge__scene[data-mods="3"] .ds-mod__phase { align-self: flex-start; padding-top: 0; }
  .ds-forge__scene[data-mods="3"] .ds-mod__facts {
    display: grid; margin-top: 0.5rem; row-gap: 0.35rem;
  }
  /* Only the check line is shown: the spec file name repeated the row's
     own name and made the panel taller than the copy beside it. */
  .ds-forge__scene[data-mods="3"] .ds-mod__fact:first-child { display: none; }
}
/* No JS: the first archetype stands on its own, fully legible. */
.ds-forge__scene:first-child { display: grid; }
.ds-js .ds-forge__scene {
  display: grid; opacity: 0; visibility: hidden;
  transition: opacity 0.45s var(--ease), visibility 0.45s var(--ease);
}
.ds-js .ds-forge__scene.is-active { opacity: 1; visibility: visible; }

/* One module of the app being built: an icon for what it is, its
   name, what it covers, the stage of the method it belongs to, and
   its build bar. Icon and name share the first row, the bar and the
   stage label always sit on the bottom two. */
.ds-mod {
  --ds-mod-tone: var(--ds-intent);
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto 1fr auto;
  column-gap: 0.8rem; row-gap: 0.25rem;
  padding: 0.75rem 1rem;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-sm, 8px);
  overflow: hidden;
}
.ds-mod--intent { --ds-mod-tone: var(--ds-intent); }
.ds-mod--spec { --ds-mod-tone: var(--ds-spec); }
.ds-mod--build { --ds-mod-tone: var(--ds-build); }
.ds-mod--proof { --ds-mod-tone: var(--ds-proof); }

/* Drawn from the sprite at the top of the panel, in the module's
   own tone so the icon, the stage label and the bar agree. */
.ds-mod__icon {
  --ds-icon-size: 30px;
  grid-column: 1; grid-row: 1 / span 2; align-self: start;
  width: var(--ds-icon-size); height: var(--ds-icon-size);
  padding: calc(var(--ds-icon-size) / 5);
  box-sizing: border-box;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: calc(var(--ds-icon-size) / 4);
  background: transparent;
  color: var(--ds-mod-tone);
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
  overflow: visible;
}
.ds-mod__name {
  grid-column: 2; grid-row: 1;
  margin: 0; padding-right: 1.1rem;
  font-family: var(--font-mono); font-size: 0.8125rem; line-height: 1.3;
  color: var(--color-on-dark); text-wrap: balance;
}
.ds-mod__desc {
  grid-column: 2; grid-row: 2;
  margin: 0; padding-right: 1.1rem;
  font-size: 0.75rem; line-height: 1.45; color: var(--color-on-dark-muted);
  text-wrap: pretty;
}
/* The six-module scenes are read as a grid of names and progress bars; the
   one-line descriptions only made every card, and the panel, taller. */
.ds-forge__scene[data-mods="6"] .ds-mod__desc { display: none; }
/* Sits on the last line of the card, above the bar, and names the
   stage of the method the module is in. */
.ds-mod__phase {
  grid-column: 1 / -1; grid-row: 3; align-self: end;
  padding-top: 0.5rem;
  font-family: var(--font-mono); font-size: var(--fs-label-xs); line-height: 1;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ds-mod-tone);
}
.ds-mod__bar {
  grid-column: 1 / -1; grid-row: 4;
  position: relative; display: block; height: 3px; border-radius: 2px;
  margin-top: 0.45rem;
  background: rgba(255, 255, 255, 0.1); overflow: hidden;
}
.ds-mod__bar::after {
  content: ""; position: absolute; inset: 0;
  background: var(--ds-mod-tone);
  transform-origin: left center;
}
/* The stage label, the bar and the readout. It is display: contents by
   default so those three stay direct children of the card grid; only the
   wide three-module layout pulls them into a column of their own. */
.ds-mod__meta { display: contents; }

/* The build readout under the bar: the file the module is written down
   in, and the one check that decides it is done. Only the wide
   three-module layout has room for it, so it stays off everywhere else. */
.ds-mod__facts { display: none; margin: 0; }
.ds-mod__fact {
  display: grid; grid-template-columns: 2.6rem minmax(0, 1fr);
  column-gap: 0.55rem; align-items: baseline;
  font-family: var(--font-mono);
}
.ds-mod__fact dt {
  font-size: var(--fs-label-xs); line-height: 1.5;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
}
.ds-mod__fact dd {
  margin: 0; font-size: 0.6875rem; line-height: 1.5;
  color: var(--color-on-dark-muted); text-wrap: pretty;
}

.ds-mod__tick {
  position: absolute; top: 0.8rem; right: 0.85rem;
  font-family: var(--font-mono); font-size: 0.6875rem; line-height: 1;
  color: var(--ds-mod-tone);
}

/* Below this the two-column scenes leave each card around 210px, and the
   name and its line of detail start wrapping past the row height. Tighten
   the card so the same content still lands inside it. */
@container forge (max-width: 620px) {
  .ds-mod { padding: 0.85rem 0.9rem; column-gap: 0.65rem; }
  .ds-mod__icon { --ds-icon-size: 26px; }
  .ds-mod__name { font-size: 0.75rem; padding-right: 0.6rem; }
  .ds-mod__desc { font-size: 0.6875rem; line-height: 1.4; padding-right: 0.6rem; }
  .ds-mod__tick { top: 0.65rem; right: 0.7rem; }
  .ds-forge__scene[data-mods="3"] .ds-mod__icon { --ds-icon-size: 40px; }
}

/* The build motion. Everything is scoped to .ds-js and to the
   active scene, so re-activating a scene replays it from zero. */
.ds-js .ds-mod { opacity: 0; }
.ds-js .ds-forge__scene.is-active .ds-mod {
  animation: ds-forge-in 0.5s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 0.09s);
}
.ds-js .ds-mod__bar::after { transform: scaleX(0); }
.ds-js .ds-forge__scene.is-active .ds-mod__bar::after {
  animation: ds-forge-fill 0.8s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 0.09s + 0.3s);
}
.ds-js .ds-mod__tick { opacity: 0; }
.ds-js .ds-forge__scene.is-active .ds-mod__tick {
  animation: ds-forge-tick 0.3s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 0.09s + 1.05s);
}
@keyframes ds-forge-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
@keyframes ds-forge-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes ds-forge-tick {
  from { opacity: 0; transform: scale(0.6); }
  to { opacity: 1; transform: none; }
}

.ds-forge__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
  padding: 0.95rem var(--ds-forge-pad);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.ds-forge__dots { display: inline-flex; gap: 6px; }
.ds-forge__dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  transition: background 0.35s var(--ease), transform 0.35s var(--ease);
}
.ds-forge__dot.is-active { background: var(--ds-proof); transform: scale(1.25); }
.ds-forge__note {
  margin: 0; font-size: var(--fs-sm); line-height: 1.5;
  color: var(--color-on-dark-muted);
}
.ds-forge__note strong { color: var(--color-on-dark); font-weight: 600; }

/* ---------- SIGNATURE: the spec ledger ----------
   One sentence a founder actually says, the clause it becomes,
   and the check that proves it. Three examples, auto-advancing.
   Lives in section 2b, answering the pivot above it. */
.ds-ledger-block {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 4vw, 3.5rem); align-items: center;
}
.ds-ledger {
  position: relative;
  background: var(--color-ink); color: var(--color-on-dark);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: var(--radius-lg);
  box-shadow: 0 44px 90px -50px rgba(0, 0, 0, 0.65);
  overflow: hidden;
}
.ds-ledger::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(70% 55% at 100% 0%, color-mix(in srgb, var(--ds-proof) 15%, transparent), transparent 64%),
    radial-gradient(60% 50% at 0% 100%, color-mix(in srgb, var(--ds-spec) 14%, transparent), transparent 64%);
}
.ds-ledger > * { position: relative; z-index: 1; }

.ds-ledger__bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: 0.85rem 1.15rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.06em;
}
.ds-ledger__file { color: var(--color-on-dark-muted); }
.ds-ledger__state { display: inline-flex; align-items: center; gap: 0.5em; color: var(--ds-proof); text-transform: uppercase; letter-spacing: 0.14em; }
.ds-ledger__state-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ds-proof);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ds-proof) 22%, transparent);
}

.ds-ledger__tabs {
  display: flex; gap: 2px; padding: 0.75rem 1.15rem 0;
}
.ds-ledger__tab {
  position: relative; flex: 1 1 0; min-width: 0;
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: 0.45rem 0.35rem 0.7rem;
  font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-on-dark-muted) 70%, transparent);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  transition: color 0.2s var(--ease);
}
.ds-ledger__tab:hover { color: var(--color-on-dark); }
.ds-ledger__tab.is-active { color: var(--color-on-dark); }
.ds-ledger__tab::after {
  content: ""; position: absolute; left: 0; bottom: -1px; height: 2px; width: 0;
  background: var(--ds-proof);
}
.ds-ledger__tab.is-active::after { width: 100%; }
/* While auto-advancing, the underline doubles as the timer. */
.ds-ledger.is-auto .ds-ledger__tab.is-active::after {
  width: 0; animation: ds-tick var(--ds-dwell, 6s) linear forwards;
}
.ds-ledger.is-auto.is-paused .ds-ledger__tab.is-active::after { animation-play-state: paused; }
@keyframes ds-tick { from { width: 0; } to { width: 100%; } }

.ds-ledger__panel { display: none; padding: var(--space-5) 1.35rem var(--space-4); }
.ds-ledger__panel.is-active { display: block; }

.ds-lg-row { position: relative; padding-left: 1.6rem; }
.ds-lg-row + .ds-lg-row { margin-top: 1.35rem; }
/* the thread that runs down the ledger: intent → spec → proof */
.ds-lg-row::before {
  content: ""; position: absolute; left: 4px; top: 0.5rem;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ds-row, var(--ds-intent));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ds-row, var(--ds-intent)) 20%, transparent);
}
.ds-lg-row:not(:last-child)::after {
  content: ""; position: absolute; left: 7px; top: 1.3rem; bottom: -1.35rem; width: 1px;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--ds-row, var(--ds-intent)) 55%, transparent), rgba(255, 255, 255, 0.08));
}
.ds-lg-row--said { --ds-row: var(--ds-intent); }
.ds-lg-row--spec { --ds-row: var(--ds-spec); }
.ds-lg-row--proof { --ds-row: var(--ds-proof); }

.ds-lg-row__key {
  margin: 0 0 0.35rem; font-family: var(--font-mono);
  font-size: var(--fs-label-xs); font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ds-row, var(--ds-intent));
}
/* What the founder said — set in the human voice, quoted. */
.ds-lg-row__said {
  margin: 0; font-family: var(--font-title); font-weight: 600;
  font-size: clamp(0.9375rem, 1.2vw, 1.0625rem); line-height: 1.4;
  letter-spacing: -0.015em; color: var(--color-on-dark);
}
/* What we wrote — the machine voice. */
.ds-lg-row__spec {
  margin: 0; font-family: var(--font-mono); font-size: 0.75rem; line-height: 1.7;
  color: var(--color-on-dark-muted);
}
.ds-lg-row__spec em { font-style: normal; color: var(--color-on-dark); }
.ds-lg-clause {
  color: var(--ds-spec); font-weight: 600; margin-right: 0.35em;
}
.ds-lg-row__proof {
  margin: 0; display: flex; align-items: flex-start; gap: 0.5em;
  font-family: var(--font-mono); font-size: 0.75rem; line-height: 1.65;
  color: var(--color-on-dark-muted);
}
.ds-lg-row__proof span:last-child { min-width: 0; }
.ds-lg-row__proof strong { color: var(--ds-proof); font-weight: 600; }
.ds-lg-check {
  flex: 0 0 auto; width: 17px; height: 17px; border-radius: 50%;
  display: inline-grid; place-items: center; align-self: center;
  background: var(--ds-proof); color: var(--color-ink);
  font-size: 0.625rem; font-weight: 700; line-height: 1;
}

.ds-ledger__foot {
  margin: 0; padding: 0.9rem 1.15rem 1.05rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: var(--fs-sm); line-height: 1.5; color: var(--color-on-dark-muted);
}
.ds-ledger__foot strong { color: var(--color-on-dark); font-weight: 600; }

/* Panel rows enter in sequence each time a panel is shown. */
.ds-js .ds-ledger__panel.is-active .ds-lg-row {
  animation: ds-lg-in 0.5s var(--ease) both;
}
.ds-js .ds-ledger__panel.is-active .ds-lg-row:nth-child(2) { animation-delay: 0.16s; }
.ds-js .ds-ledger__panel.is-active .ds-lg-row:nth-child(3) { animation-delay: 0.32s; }
@keyframes ds-lg-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* =============================================================
   2 — THE STAKES (drift)
   The only section allowed to use magenta.
   ============================================================= */
.ds-drift-head { --ds-tone: var(--ds-drift); }
.ds-drifts {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3);
}
.ds-drift {
  position: relative; padding: var(--space-5) var(--space-4) var(--space-4);
  background: var(--color-surface-light);
  border: 1px solid var(--border-ink);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* the founder's own words — the symptom */
.ds-drift__said {
  margin: 0; font-family: var(--font-title); font-weight: 700;
  font-size: clamp(1.125rem, 1.6vw, 1.375rem); line-height: 1.28;
  letter-spacing: -0.02em; color: var(--color-ink); text-wrap: pretty;
}
.ds-drift__cause { margin: var(--space-4) 0 0; }
.ds-drift__cause .ds-tag { color: color-mix(in srgb, var(--ds-drift) 78%, var(--color-ink)); }
.ds-drift__body {
  margin: 6px 0 0; font-size: var(--fs-base); line-height: 1.55; color: var(--color-ink-60);
}

/* The pivot: one line that turns the problem into our method. Light panel
   with the same cyan/green wash as the testimonial viewport on the home
   page (.voices__viewport in styles.css). */
.ds-pivot {
  max-width: var(--ds-max); margin: var(--space-5) auto 0;
  background: var(--color-surface-light); color: var(--color-ink);
  border: 1px solid var(--border-ink);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1.5rem, 3.4vw, 2.75rem);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4); align-items: center;
  position: relative; overflow: hidden;
}
.ds-pivot::before {
  content: ""; position: absolute; inset: -30% -10% auto; height: 85%;
  pointer-events: none;
  background:
    radial-gradient(42% 55% at 18% 30%, oklch(0.84 0.12 200 / 0.28), transparent 70%),
    radial-gradient(48% 60% at 82% 45%, oklch(0.88 0.14 145 / 0.26), transparent 72%);
  animation: nc-hue 12s ease-in-out infinite alternate;
}
.ds-pivot > * { position: relative; z-index: 1; }
.ds-pivot__text {
  margin: 0; font-family: var(--font-title); font-weight: 600;
  font-size: clamp(1.125rem, 2vw, 1.625rem); line-height: 1.3; letter-spacing: -0.025em;
  color: var(--color-ink); max-width: 40ch; text-wrap: pretty;
}
.ds-pivot__text em {
  font-style: normal;
}

/* =============================================================
   3 — THE PATH
   Five steps. Numbering is honest here: it is a sequence. Each step
   names its artifact (what you receive) and its gate (what must be
   true before we move on). Card slider: same markup shape and same
   visual language as the services carousel on ux-ui-services.html
   (.uxp-svcs / .uxp-svc) — dark cards on the page's own light
   background, not inside a dark panel of their own.
   ============================================================= */

/* ---------- Path steps: horizontal card slider ----------
   A scroll-snap track with 2.5 cards in view, driven by
   initSnapSlider('path'). The viewport bleeds all the way to the true
   window edge (not just out to the section's gutter) so the peeking
   card is cropped by the edge of the screen, never by empty page
   background. --path-inset is how far the first card sits from that
   edge: normally just the gutter, but on screens wider than the site's
   1600px container it grows to match the extra centering margin
   .ds-wrap picks up, so card one still lines up under the heading. */
.ds-path__slider {
  margin-top: var(--space-6);
  --path-gap: 20px;
  --path-card: calc((100% - var(--path-gap) * 2) / 2.5);
  --path-inset: max(var(--gutter), calc((100vw - var(--container-inner)) / 2));
}
.ds-path__viewport {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scroll-padding-inline-start: var(--path-inset);
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.ds-path__viewport::-webkit-scrollbar { display: none; }
.ds-path__viewport:focus-visible { outline: 2px solid var(--color-active); outline-offset: 4px; }
.ds-path__track {
  display: flex;
  align-items: stretch;
  gap: var(--path-gap);
  margin: 0;
  padding: 20px 0 44px var(--path-inset);
}
/* Trailing room for the last card, as a flex item rather than track padding:
   end padding is left out of scrollWidth. It keeps a hairline of width because
   at the sizes where the gap equals the inset this works out to zero, and a
   zero-width box drops out of the overflow again along with its gap. */
.ds-path__track::after {
  content: "";
  flex: 0 0 max(1px, calc(var(--path-inset) - var(--path-gap)));
}
.ds-pathcard {
  --card-accent: var(--ds-intent);
  --art-x: 100%; --art-y: 100%;
  flex: 0 0 var(--path-card);
  min-width: 0;
  min-height: 340px;
  scroll-snap-align: start;
  position: relative; overflow: hidden; display: flex; flex-direction: column;
  background: var(--color-ink); color: var(--color-on-dark);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), border-color 0.2s var(--ease);
}
.ds-pathcard::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(58% 58% at var(--art-x) var(--art-y),
      color-mix(in srgb, var(--card-accent) 30%, transparent), transparent 60%),
    repeating-radial-gradient(circle at var(--art-x) var(--art-y),
      transparent 0 27px,
      color-mix(in srgb, var(--card-accent) 13%, transparent) 27px 28.5px);
  -webkit-mask: radial-gradient(78% 78% at var(--art-x) var(--art-y), #000 28%, transparent 80%);
  mask: radial-gradient(78% 78% at var(--art-x) var(--art-y), #000 28%, transparent 80%);
  transition: transform 0.3s var(--ease);
}
.ds-pathcard > * { position: relative; z-index: 1; }
.ds-pathcard:hover::before { transform: scale(1.06); }
.ds-pathcard:hover {
  transform: translateY(-4px);
  box-shadow: 0 24px 50px -30px rgba(0, 0, 0, 0.55);
  border-color: color-mix(in srgb, var(--card-accent) 42%, transparent);
}
.ds-pathcard--1 { --card-accent: var(--ds-intent); }
.ds-pathcard--2 { --card-accent: var(--ds-spec); }
.ds-pathcard--3 { --card-accent: var(--ds-build); }
.ds-pathcard--4 { --card-accent: var(--ds-proof); }
.ds-pathcard--5 { --card-accent: var(--ds-drift); }
.ds-pathcard__top { margin-bottom: var(--space-4); }
.ds-pathcard__tag {
  font-family: var(--font-title); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-on-dark-muted);
  padding: 5px 11px; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: var(--radius-pill);
}
.ds-pathcard__title {
  margin: 0 0 8px; font-family: var(--font-title); font-weight: 700;
  font-size: 1.375rem; letter-spacing: -0.01em; line-height: 1.15;
  color: var(--color-on-dark);
}
.ds-pathcard__body {
  margin: 0 0 var(--space-4); font-size: 0.9375rem; line-height: 1.55;
  color: var(--color-on-dark-muted);
}
.ds-pathcard__meta {
  margin: auto 0 0; padding-top: var(--space-4);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: grid; gap: var(--space-3);
}
.ds-pathcard__row { display: grid; gap: 3px; margin: 0; }
.ds-pathcard__label {
  font-family: var(--font-title); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--card-accent); margin: 0;
}
.ds-pathcard__val { font-size: 0.9375rem; line-height: 1.5; color: var(--color-on-dark-muted); margin: 0; }

.ds-path__controls {
  display: flex; align-items: center; justify-content: center;
  gap: 18px; margin-top: var(--space-2);
}
.ds-path__nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; padding: 0;
  color: var(--color-paper);
  background: var(--color-ink);
  border: 1px solid var(--color-ink);
  border-radius: 50%;
  cursor: pointer;
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
.ds-path__nav:hover { opacity: 0.76; transform: translateY(-2px); }
.ds-path__nav:focus-visible { outline: 2px solid var(--color-active); outline-offset: 3px; }
.ds-path__nav svg { width: 19px; height: 19px; }
.ds-path__dots { display: flex; align-items: center; gap: 8px; }
.ds-path__dot {
  width: 8px; height: 8px; padding: 0; border: 0; border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--color-ink) 28%, transparent);
  cursor: pointer;
  transition: width 0.2s var(--ease), background 0.2s var(--ease);
}
.ds-path__dot.is-active { width: 26px; background: var(--color-ink); }
.ds-path__dot:focus-visible { outline: 2px solid var(--color-active); outline-offset: 3px; }

/* =============================================================
   4 — WHAT YOU GET
   ============================================================= */
.ds-gets {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3);
}
.ds-get {
  padding: var(--space-4);
  background: var(--color-surface-light);
  border: 1px solid var(--border-ink);
  border-radius: var(--radius-lg);
  transition: transform 0.22s var(--ease), border-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.ds-get:hover {
  transform: translateY(-3px);
  border-color: var(--border-ink-strong);
  box-shadow: 0 24px 50px -34px rgba(0, 0, 0, 0.42);
}
/* Each deliverable declares what kind of thing it is — a document,
   a repo, a report, an access grant. The kind is the information. */
.ds-get__kind {
  display: inline-flex; align-items: center;
  margin-bottom: var(--space-3);
  font-family: var(--font-tag); font-size: var(--fs-tag); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--ds-get, var(--ds-proof)) 62%, var(--color-ink));
}
.ds-get__title {
  margin: 0; font-family: var(--font-title); font-weight: 700;
  font-size: var(--fs-card-title); letter-spacing: -0.015em; color: var(--color-ink);
}
.ds-get__body { margin: 6px 0 0; font-size: var(--fs-base); line-height: 1.55; color: var(--color-ink-60); }
.ds-get--a { --ds-get: var(--ds-intent); }
.ds-get--b { --ds-get: var(--ds-spec); }
.ds-get--c { --ds-get: var(--ds-build); }
.ds-get--d { --ds-get: var(--ds-proof); }

/* =============================================================
   5 — FIT
   ============================================================= */
.ds-fit {
  list-style: none; margin: var(--space-6) 0 0; padding: clamp(1.75rem, 3.5vw, 2.75rem);
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.15rem 2rem;
  background: var(--color-ink); color: var(--color-on-dark);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-xl);
}
.ds-fit::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(50% 60% at 100% 0%,
    color-mix(in srgb, var(--ds-proof) 22%, transparent), transparent 65%);
}
.ds-fit__item {
  position: relative; z-index: 1;
  display: flex; gap: 0.85rem; align-items: flex-start;
  font-size: var(--fs-base); line-height: 1.55;
  color: var(--color-on-dark-muted);
  padding: 0.15rem 0;
}
.ds-fit__item strong { color: var(--color-on-dark); font-weight: 600; }
.ds-fit__txt { min-width: 0; }
.ds-fit__mark {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; margin-top: 1px;
  font-size: 0.6875rem; font-weight: 700; line-height: 1;
  background: var(--ds-proof); color: var(--color-ink);
}
.ds-fit__item:last-child:nth-child(odd) { grid-column: 1 / -1; max-width: 42ch; }

/* =============================================================
   6 — FAQ (native details/summary — works with JS off)
   ============================================================= */
/* Head on the left, questions on the right — the head stays with you
   while you read down the list. */
.ds-faq-grid {
  display: grid; grid-template-columns: minmax(0, 0.68fr) minmax(0, 1.32fr);
  gap: clamp(2rem, 4vw, 3.5rem); align-items: start;
}
.ds-faq-grid__head { position: sticky; top: calc(var(--header-height) + var(--space-5)); }
.ds-faq { border-top: 1px solid var(--border-ink); }
.ds-faq__item { border-bottom: 1px solid var(--border-ink); }
.ds-faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-4) 0; cursor: pointer; list-style: none;
  font-family: var(--font-title); font-weight: 600;
  font-size: var(--fs-faq); letter-spacing: -0.015em; color: var(--color-ink);
  transition: color 0.18s var(--ease);
}
.ds-faq__q::-webkit-details-marker { display: none; }
.ds-faq__q:hover { color: var(--color-ink-60); }
.ds-faq__icon { color: var(--color-active); }
.ds-faq__a {
  margin: 0; padding: 0 0 var(--space-4); max-width: 68ch;
  font-size: var(--fs-base); line-height: 1.65; color: var(--color-ink-60);
}
.ds-faq__a a { color: var(--color-ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.ds-faq__a a:hover { color: var(--color-active); }
.ds-js .ds-faq__item[open] .ds-faq__a { animation: ds-lg-in 0.32s var(--ease) both; }

/* =============================================================
   7 — CLOSING CTA (what actually happens if you book)
   ============================================================= */
.ds-close {
  margin-top: var(--space-8); padding: 0 var(--gutter) var(--space-8);
}
.ds-close__panel {
  position: relative; overflow: hidden;
  max-width: var(--ds-max); margin-inline: auto;
  background: var(--color-ink); color: var(--color-on-dark);
  border-radius: var(--radius-xl);
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1.5rem, 4vw, 3.5rem);
  display: flex; justify-content: center; align-items: center;
  text-align: center;
}
/* Blue -> green wash, same morph mechanic and hues as the hero glow above —
   this panel is a generic dark CTA card, not tied to any of the five
   pipeline-stage colours, so it echoes the page's two hero accents instead. */
.ds-close__glow {
  position: absolute; z-index: 0; pointer-events: none;
  /* Fade the box itself to transparent before its edge: the morph moves the
     gradient centre off-centre, and a clipped edge would show as a hard arc. */
  -webkit-mask-image: radial-gradient(closest-side, #000 55%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 55%, transparent 100%);
  top: -30%; left: 50%; width: 60vw; height: 60vw;
  translate: -50% 0;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.72 0.17 var(--g-h1, 224deg) / 0.4),
    oklch(0.8 0.16 var(--g-h2, 152deg) / 0.2) 46%,
    transparent 70%
  );
  animation:
    ds-glow-morph-close 7s ease-in-out -2s infinite,
    ds-glow-float-close 10s ease-in-out -5s infinite;
}
@keyframes ds-glow-morph-close {
  0%, 100% { --g-h1: 224deg; --g-h2: 152deg; --g-w: 46%; --g-h: 56%; --g-x: 50%; --g-y: 46%; }
  50%      { --g-h1: 152deg; --g-h2: 224deg; --g-w: 56%; --g-h: 42%; --g-x: 66%; --g-y: 62%; }
}
@keyframes ds-glow-float-close {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);    filter: saturate(1); }
  50%      { transform: scale(1.18) translate3d(-8%, 8%, 0); filter: saturate(1.1); }
}
.ds-close__panel > *:not(.ds-close__glow) { position: relative; z-index: 1; }
.ds-close__copy { max-width: 36rem; }
.ds-close__title {
  margin: var(--space-3) auto 0; font-family: var(--font-title); font-weight: 700;
  font-size: clamp(1.875rem, 3.6vw, 3rem); line-height: 0.95; letter-spacing: -0.04em;
  color: var(--color-on-dark); max-width: 22ch; text-wrap: balance;
}
.ds-close__lead {
  margin: var(--space-3) auto 0; font-size: var(--fs-lead); line-height: 1.55;
  color: var(--color-on-dark-muted); max-width: 44ch;
}
.ds-close__actions {
  margin-top: var(--space-5); display: flex; gap: 14px; flex-wrap: wrap;
  justify-content: center;
}

/* =============================================================
   ESTIMATE — unchanged behaviour, moved out of the page <style>.
   Heading on paper, then TWO dark blocks (calculator + range)
   side by side with spacing.
   ============================================================= */
/* Kill the leftover mono font on labels, align with the page */
.ds .calc__label {
  font-family: var(--font-title);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--color-ink);
  margin-bottom: var(--space-3);
}
/* Summary kickers: "Approximate range" / "What's driving your number" */
.ds .calc__summary-kicker {
  font-family: var(--font-title);
  letter-spacing: 0.08em;
  font-weight: 600;
}
.ds .calc-scale__tick { font-family: var(--font-title); }
.ds .calc__hint { font-family: var(--font-body); }
.ds .calc__driver dt,
.ds .calc__driver dd { font-family: var(--font-title); font-size: var(--fs-sm); }

/* Calculator temporarily hidden: the section and both "See your price range"
   buttons carry `hidden`. Remove those attributes to bring it back. */
.ds .ds-estimate[hidden],
.ds a[href="#estimate"][hidden] { display: none !important; }

.ds .calc-section.ds-estimate {
  position: relative;
  background: transparent;
  padding-block: var(--space-6);
}
/* Same measure as every other section on the page, so the dark blocks
   line up with the cards above and below them. */
.ds .ds-estimate .calc { max-width: var(--ds-max); margin-inline: auto; background: transparent; }

/* Intro lives OUTSIDE the blocks, on the paper, centred */
.ds .ds-estimate .calc__intro { max-width: 42rem; margin: 0 auto var(--space-6); text-align: center; }
.ds .ds-estimate .calc__intro .kicker { color: var(--color-ink-70); }
/* Matches .ds-h2 so the estimate head reads at the same level as every
   other section head on the page. */
.ds .ds-estimate .calc__intro .section__title {
  color: var(--color-ink);
  font-size: clamp(1.875rem, 3.4vw, 2.75rem);
  letter-spacing: -0.03em;
  line-height: 1.06;
  margin: var(--space-2) 0 0;
}
.ds .ds-estimate .calc__intro .section__lead { color: var(--color-ink-60); font-size: var(--fs-base); margin-inline: auto; }

/* Two separate blocks with a gap between them */
.ds .ds-estimate .calc__grid { gap: var(--space-4); grid-template-columns: minmax(0, 1fr) minmax(0, 28rem); align-items: start; }

/* Shared dark-block shell for both the form and the range */
.ds .ds-estimate .calc__form,
.ds .ds-estimate .calc__summary {
  background: var(--color-ink);
  color: var(--color-on-dark);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-xl);
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  box-shadow: 0 30px 70px -50px rgba(0, 0, 0, 0.6);
}
.ds .ds-estimate .calc__form { gap: var(--space-5); }
.ds .ds-estimate .calc-cards { margin-top: var(--space-3); }
.ds .ds-estimate .calc-card { padding: var(--space-2) var(--space-3); }
.ds .ds-estimate .calc-card__title { font-size: var(--fs-base); }
.ds .ds-estimate .calc-card__desc { font-size: 0.8125rem; }

.ds .ds-estimate .calc__label { color: var(--color-on-dark); margin-bottom: var(--space-3); }
.ds .ds-estimate .calc__hint { color: var(--color-on-dark-muted); }

.ds .ds-estimate .calc-range {
  background: linear-gradient(to right,
    var(--color-secondary-green) var(--pct, 50%),
    rgba(255, 255, 255, 0.16) var(--pct, 50%));
}

.ds .ds-estimate .calc-card {
  background: var(--color-ink-elevated);
  border-color: rgba(255, 255, 255, 0.1);
}
.ds .ds-estimate .calc-card:hover { border-color: rgba(255, 255, 255, 0.24); }
.ds .ds-estimate .calc-card.is-active {
  border-color: color-mix(in srgb, var(--color-secondary-green) 65%, transparent);
  background: color-mix(in srgb, var(--color-secondary-green) 16%, var(--color-ink-elevated));
  box-shadow: none;
}
.ds .ds-estimate .calc-card__title { color: var(--color-on-dark); }
.ds .ds-estimate .calc-card__desc { color: var(--color-on-dark-muted); }

.ds .ds-estimate .calc-scale__tick { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc-scale__tick.is-active { color: var(--color-secondary-green); }

.ds .ds-estimate .calc-toggle__btn {
  background: var(--color-ink-elevated);
  border-color: rgba(255, 255, 255, 0.1);
  color: var(--color-on-dark);
}
.ds .ds-estimate .calc-toggle__btn:hover { border-color: rgba(255, 255, 255, 0.24); }
.ds .ds-estimate .calc-toggle__btn.is-active {
  border-color: color-mix(in srgb, var(--color-secondary-green) 65%, transparent);
  background: color-mix(in srgb, var(--color-secondary-green) 16%, var(--color-ink-elevated));
  color: var(--color-on-dark);
}

.ds .ds-estimate .calc__summary { top: calc(var(--header-height) + var(--space-4)); }
.ds .ds-estimate .calc__summary-kicker { color: var(--color-secondary-green); }
.ds .ds-estimate .calc__summary-kicker--ink { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc__range {
  color: var(--color-on-dark);
  font-size: clamp(1.5rem, 2vw, 1.9rem);
  margin-top: var(--space-2);
  white-space: nowrap;
}
.ds .ds-estimate .calc__range #calc-low,
.ds .ds-estimate .calc__range #calc-high {
  color: var(--color-secondary-green);
}
.ds .ds-estimate .calc__range-dash { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc__range-unit { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc__divider { border-top-color: rgba(255, 255, 255, 0.12); }
.ds .ds-estimate .calc__driver dt { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc__driver dd { color: var(--color-on-dark); }
.ds .ds-estimate .calc__disclaimer { color: var(--color-on-dark-muted); }
.ds .ds-estimate .calc__cta { background: var(--color-on-dark); color: var(--color-ink); }
.ds .ds-estimate .calc__cta:hover { background: #fff; color: var(--color-ink); }

/* =============================================================
   RESPONSIVE
   ============================================================= */
/* Half the grid stops being enough for the forge before the rest of the page
   needs to stack: under this the panel drops below ~500px and the modules no
   longer hold their line of detail, so the hero goes to one column first. */
@media (max-width: 1240px) {
  .ds-hero__grid { grid-template-columns: 1fr; gap: var(--space-6); }
  .ds-hero__title { max-width: none; }
  .ds-hero__lead { max-width: 58ch; }
}

@media (max-width: 1080px) {
  .ds-ledger-block { grid-template-columns: 1fr; gap: var(--space-6); }
  .ds-drifts { grid-template-columns: 1fr; }
  .ds-gets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Tablet and phone both get the same slider: one card, plus the front edge
     of the next one cropped by the right side of the screen so the track still
     reads as scrollable. --path-sliver is how much of that next card shows;
     subtracting it and the gap from the full width leaves the room for it. */
  .ds-path__slider {
    --path-gap: 16px;
    --path-sliver: clamp(2.5rem, 9vw, 5.25rem);
    --path-card: calc(100% - var(--path-sliver) - var(--path-gap));
  }
  /* One card no longer has neighbours to match height with, so the floor that
     kept a row of them even goes away and the card sizes to its own copy. */
  .ds-pathcard { min-height: 0; }
  .ds-faq-grid { grid-template-columns: 1fr; gap: var(--space-5); }
  .ds-faq-grid__head { position: static; }
}

/* Estimate: stack the two dark blocks, range no longer sticky */
@media (max-width: 900px) {
  .ds .ds-estimate .calc__grid { grid-template-columns: 1fr; }
  .ds .ds-estimate .calc__summary { position: static; top: auto; }

  .ds .ds-estimate .calc__peek {
    background: var(--color-ink);
    border-color: rgba(255, 255, 255, 0.14);
    box-shadow: 0 20px 40px -24px rgba(0, 0, 0, 0.55);
  }
  .ds .ds-estimate .calc__peek-kicker { color: var(--color-secondary-green); }
  .ds .ds-estimate .calc__peek-range { color: var(--color-on-dark); }
  .ds .ds-estimate .calc__peek-range #calc-low-peek,
  .ds .ds-estimate .calc__peek-range #calc-high-peek { color: var(--color-secondary-green); }
  .ds .ds-estimate .calc__peek .calc__range-unit { color: var(--color-on-dark-muted); }
  .ds .ds-estimate .calc__peek-cta { background: var(--color-on-dark); color: var(--color-ink); }
  .ds .ds-estimate .calc__peek-cta:hover { background: #fff; color: var(--color-ink); }
}

@media (max-width: 720px) {
  .ds-section { padding-top: var(--space-5); }
  .ds-section--tight { padding-top: var(--space-4); }
  .ds-section--last { padding-bottom: var(--space-5); }
  #spec { padding-top: var(--space-6); padding-bottom: var(--space-4); }
  .ds-hero { padding-top: calc(var(--header-height) + var(--space-3)); padding-bottom: var(--space-5); }
  .ds-hero__panel { padding: var(--space-5) var(--space-4); border-radius: var(--radius-lg); }
  .ds-hero__cta .btn { flex: 1 1 100%; text-align: center; justify-content: center; }
  .ds-pivot { grid-template-columns: 1fr; }
  .ds-pivot .btn { width: 100%; text-align: center; }
  .ds-gets { grid-template-columns: 1fr; }
  .ds-fit { grid-template-columns: 1fr; }
  .ds-path__slider {
    margin-top: var(--space-4);
    --path-gap: 12px;
  }
  .ds-path__track { padding-bottom: 30px; }
  .ds-pathcard { padding: var(--space-4); border-radius: var(--radius-md); }
  .ds-pathcard__title { font-size: 1.125rem; }
  .ds-path__nav { width: 42px; height: 42px; }
  .ds-ledger__tabs { padding-inline: 0.85rem; }
  .ds-ledger__panel { padding-inline: 0.85rem; }
  .ds-ledger__bar, .ds-ledger__foot { padding-inline: 0.85rem; }
  .ds-close__actions .btn { flex: 1 1 100%; text-align: center; justify-content: center; }
  .ds-forge { --ds-forge-pad: 1rem; }
}

/* Two columns of modules on a phone leave no room for the line of
   detail, so the card drops to its name and its stage. */
@media (max-width: 560px) {
  /* Phone: each card is one line of icon + name with its bar under it.
     The stage label goes; the bar's colour already carries it. */
  .ds-forge__stage { --ds-modh: 3.25rem; --ds-modgap: 0.5rem; }
  .ds-mod__desc, .ds-mod__phase { display: none; }
  .ds-mod {
    grid-template-rows: 1fr auto;
    padding: 0.55rem 0.65rem; column-gap: 0.45rem; row-gap: 0;
  }
  .ds-mod__icon,
  .ds-forge__scene[data-mods="3"] .ds-mod__icon { --ds-icon-size: 20px; grid-row: 1; align-self: center; }
  .ds-mod__name { font-size: 0.6875rem; line-height: 1.2; align-self: center; padding-right: 0.7rem; }
  .ds-mod__bar { grid-row: 2; margin-top: 0.4rem; }
  .ds-mod__tick { top: 0.45rem; right: 0.5rem; font-size: 0.625rem; }
  .ds-forge__bar { font-size: 0.6875rem; }
  .ds-forge__note { font-size: 0.8125rem; }
}

@media (prefers-reduced-motion: reduce) {
  .ds-hero__glow, .ds-hero__glow--b, .ds-hero__glow--c, .ds-hero__glow--corner, .ds-hero__wash, .ds-close__glow { animation: none; }
  .ds-js [data-ds-reveal] { opacity: 1; transform: none; transition: none; }
  .ds-js .ds-ledger__panel.is-active .ds-lg-row { animation: none; }
  .ds-ledger.is-auto .ds-ledger__tab.is-active::after { animation: none; width: 100%; }
  /* Forge holds still: one archetype, fully built, no rotation. */
  .ds-js .ds-mod,
  .ds-js .ds-mod__tick { opacity: 1; animation: none; }
  .ds-js .ds-mod__bar::after,
  .ds-js .ds-forge__scene.is-active .ds-mod__bar::after { animation: none; transform: scaleX(1); }
  .ds-js .ds-forge__scene.is-active .ds-mod { animation: none; }
  .ds-forge__scene { transition: none; }
  .ds-js .ds-faq__item[open] .ds-faq__a { animation: none; }
}

/* Hero type on phones: the headline shrinks with the viewport so it keeps
   one line (EN and FR), and the lead drops to body size. */
@media (max-width: 720px) {
  .ds-hero__title { font-size: 7.8vw; }
  .ds-hero__lead { font-size: var(--fs-base); line-height: 1.55; }
}
