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

   TYPE SYSTEM FOR THIS PAGE
     Figtree            → headings (human, confident)
     Instrument Sans    → body copy (human, plain)
     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: clamp(1.875rem, 3.4vw, 2.75rem);
  letter-spacing: -0.03em; line-height: 1.06;
  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-mono);
  font-size: 0.625rem; 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: clip; text-align: left;
  max-width: none;
  padding: calc(var(--header-height) + var(--space-8)) var(--gutter) var(--space-8);
  /* 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. */
  overflow-clip-margin: 420px;
}
.ds-hero__glow, .ds-hero__glow--b, .ds-hero__glow--corner {
  position: absolute; z-index: 0; pointer-events: none; border-radius: 50%;
}
/* Blue wash, top-right — box and offset share the same vw value (half the
   box, negative, on both axes) so the gradient's own centre lands exactly on
   the hero's top-right corner rather than somewhere inside the box. Stays
   inside the blue family as it morphs (208-238deg) so it always reads as
   blue, never drifts into the page's green. Reuses the morph custom
   properties registered once in styles.css. */
.ds-hero__glow {
  top: -37.2vw; right: -37.2vw;
  width: 74.4vw; height: 74.4vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.66 0.19 var(--g-h1, 224deg) / 0.34),
    oklch(0.74 0.17 var(--g-h1, 224deg) / 0.15) 44%,
    transparent 70%
  );
  animation:
    ds-glow-morph 6s ease-in-out infinite,
    ds-glow-float 9s ease-in-out infinite;
}
@keyframes ds-glow-morph {
  0%, 100% { --g-h1: 210deg; --g-w: 46%; --g-h: 56%; --g-x: 46%; --g-y: 54%; }
  50%      { --g-h1: 238deg; --g-w: 56%; --g-h: 42%; --g-x: 60%; --g-y: 40%; }
}
@keyframes ds-glow-float {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);     filter: saturate(1); }
  50%      { transform: scale(1.2)  translate3d(-9%, 7%, 0);  filter: saturate(1.1); }
}
/* Green wash, bottom-left — box and offset share the same vw value so the
   gradient's own centre lands exactly on the hero's bottom-left corner.
   Stays inside the green family (142-165deg) for the same reason as the
   blob above. */
.ds-hero__glow--b {
  bottom: -27.6vw; left: -27.6vw;
  width: 55.2vw; height: 55.2vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.76 0.18 var(--g-h1, 152deg) / 0.26),
    transparent 66%
  );
  animation:
    ds-glow-morph-b 7s ease-in-out -4s infinite,
    ds-glow-float-b 10s ease-in-out -6s infinite;
}
@keyframes ds-glow-morph-b {
  0%, 100% { --g-h1: 142deg; --g-w: 44%; --g-h: 44%; --g-x: 54%; --g-y: 46%; }
  50%      { --g-h1: 165deg; --g-w: 53%; --g-h: 35%; --g-x: 42%; --g-y: 60%; }
}
@keyframes ds-glow-float-b {
  0%, 100% { transform: scale(1.05) translate3d(0, 0, 0);      filter: saturate(1); }
  50%      { transform: scale(0.86) translate3d(11%, -8%, 0);  filter: saturate(1.12); }
}
/* Mandatory corner-seam accent: centred exactly on the hero's bottom-right
   corner (box width in vw, offset = -half that same vw value on both axes) —
   picks up the blue half of the page again at the opposite bottom corner
   from the green blob, so the seam reads as a quieter echo of blue, not a
   third muddy colour. */
.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.68 0.18 var(--g-h1, 224deg) / 0.17),
    transparent 58%
  );
  animation:
    ds-glow-morph-corner 8s ease-in-out -3s infinite,
    ds-glow-float-corner 11s ease-in-out -7s infinite;
}
@keyframes ds-glow-morph-corner {
  0%, 100% { --g-h1: 214deg; --g-w: 46%; --g-h: 46%; --g-x: 50%; --g-y: 50%; }
  50%      { --g-h1: 236deg; --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); }
}
.ds-hero__grid {
  position: relative; z-index: 2;
  max-width: var(--ds-max); margin-inline: auto;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 4.5vw, 4.25rem); align-items: stretch;
}

.ds-pill {
  display: inline-flex; align-items: center; gap: 0.6em;
  font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-ink-70);
  background: var(--glass); border: 1px solid var(--border-ink);
  padding: 0.45rem 0.85rem; border-radius: var(--radius-pill);
  backdrop-filter: blur(4px);
}
.ds-pill__dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--ds-proof);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--ds-proof) 18%, transparent);
  animation: nc-pulse 2.4s var(--ease) infinite;
}

.ds-hero__title {
  font-family: var(--font-title); font-weight: 700;
  font-size: clamp(2.5rem, 5vw, 4.25rem);
  line-height: 0.98; letter-spacing: -0.045em;
  color: var(--color-ink);
  margin: var(--space-4) 0 0; max-width: 15ch; 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.12; letter-spacing: -0.03em;
  color: var(--color-ink);
  margin: var(--space-4) 0 0; max-width: 22ch; text-wrap: balance;
}
.ds-hero__lead {
  font-size: var(--fs-lead); line-height: 1.6; color: var(--color-ink-70);
  max-width: 48ch; margin: var(--space-4) 0 0; text-wrap: pretty;
}
.ds-hero__lead strong { color: var(--color-ink); 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;
  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-forge::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-intent) 16%, transparent), transparent 64%),
    radial-gradient(60% 50% at 0% 100%, color-mix(in srgb, var(--ds-spec) 14%, transparent), transparent 64%),
    /* The corner the build ends in, so the panel warms toward proof. */
    radial-gradient(58% 50% at 100% 100%,
      color-mix(in srgb, var(--ds-proof) 22%, transparent),
      color-mix(in srgb, var(--ds-proof) 7%, transparent) 44%,
      transparent 72%);
}
.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.09);
  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: 0.625rem; 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;
  background: rgba(255, 255, 255, 0.14);
  transition: background 0.25s var(--ease), box-shadow 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);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ds-proof) 45%, transparent);
}

/* 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: 7.5rem; --ds-modgap: 1rem;
  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.7rem; row-gap: 0.35rem;
  }
}
/* 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: 1rem 1.1rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  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.08);
  border-radius: calc(var(--ds-icon-size) / 4);
  background: rgba(255, 255, 255, 0.05);
  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;
}
/* 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: 0.5625rem; 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: 0.5625rem; 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.09);
}
.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: 0.5625rem; 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: 0.625rem; 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: 0.625rem; 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-mono); font-size: 0.625rem; 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-md); 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-md); 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__sign {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--border-ink-strong); color: var(--color-ink-45);
  font-family: var(--font-mono); font-size: 0.75rem; line-height: 1;
  transition: transform 0.22s var(--ease), background 0.22s var(--ease), color 0.22s var(--ease), border-color 0.22s var(--ease);
}
.ds-faq__item[open] .ds-faq__sign {
  transform: rotate(45deg);
  background: var(--color-ink); border-color: var(--color-ink); color: var(--color-paper);
}
.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; border-radius: 50%;
  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: 1.03; 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); }

.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 { display: block; margin-left: 0; margin-top: 4px; color: var(--color-on-dark-muted); white-space: normal; }
.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: 20ch; }
  .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; }
}

@media (max-width: 720px) {
  .ds-section { padding-top: var(--space-7); }
  #spec { padding-top: var(--space-8); padding-bottom: var(--space-6); }
  .ds-hero { padding-top: calc(var(--header-height) + var(--space-7)); }
  .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) {
  .ds-forge__stage { --ds-modh: 6rem; --ds-modgap: 0.7rem; }
  .ds-mod__desc { display: none; }
  .ds-mod { padding: 0.8rem; column-gap: 0.5rem; }
  .ds-mod__name { font-size: 0.6875rem; }
  .ds-mod__icon { --ds-icon-size: 22px; }
  .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--corner, .ds-close__glow, .ds-pill__dot { 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; }
}
