/* ═══════════════════════════════════════════════════════════════════════════
   The four discipline pages — /services/{websites,mobile-apps,e-commerce,
   graphic-design}. One spine, four different signature mechanisms.

   WHAT THIS REPLACED, and the two defects that made the rebuild necessary
   rather than cosmetic:

   1. THE WORD-PER-LINE BUG. service-detail.css:408 set
        .sd-scope-list li { display: grid; grid-template-columns: 1rem minmax(0,1fr) }
      An <li> written as `<b>Lead.</b> trailing sentence…` has THREE grid items:
      the ::before marker, the <b>, and an anonymous item wrapping the trailing
      text. Auto-flow put that third item in row 2, column 1 — which is 1rem
      wide. Every word landed on its own line and a leading comma or em dash sat
      alone above them. Thirteen list items across the four pages rendered that
      way, and two on /services/mobile-apps overlapped into "billedhich".

      The rule that stops it coming back is below and it is structural, not a
      patch: AN ELEMENT THAT IS A GRID OR FLEX CONTAINER MAY NOT HOLD LOOSE
      TEXT. The marker leaves the flow entirely, the li stays `display: block`,
      and mixed inline content wraps the only way it cannot break.

   2. THE COLLAPSED MEASURE. Body copy computed to 14px inside a 486px column
      on a 1440px page — `62ch` is correct per PAGE-KIT, but `ch` is derived
      from the font size and --fluid-font puts 1rem at 13.33px there. Two
      thirds of every page was empty, which is most of why they read as
      documents rather than pages. Fixed twice over: the body size goes up so
      62ch lands near 560px, and the empty column now carries a drawing.

   STRUCTURE. Hero in the discipline's own ground — the same colour its panel
   uses on the hub, so arriving from /services is continuous — then the body on
   paper because a full page of near-black magenta is not a reading surface,
   then one full-bleed signature band back in the discipline colour, then the
   close. Colour identity where it identifies; paper where it is read.

   Namespace `.dsc-*`, gate class `dscjs`. `.sd-*` belonged to the page this
   replaces and `.wid-*` to the hub; neither may be reused here.
   ═══════════════════════════════════════════════════════════════════════════ */

.taxi-w.discipline {
  --dsc-bg: #fafcfb;
  --dsc-surface: #eef4f1;
  --dsc-surface-2: #e3ece7;
  --dsc-ink: #040504;
  --dsc-ink-soft: #10120f;
  --dsc-grey: #535450;
  --dsc-line: rgba(4, 5, 4, .09);
  --dsc-rim: #cbd3ce;
  --dsc-mint: #21f1a8;
  --dsc-mint-ink: #0f6f4e;     /* mint is ~1.5:1 on paper; this carries text */
  --dsc-ease: cubic-bezier(.215, .61, .355, 1);
  --dsc-rhythm: clamp(4rem, 9vh, 6.5rem);
  --page-bg: var(--dsc-bg);

  background: var(--dsc-bg);
  color: var(--dsc-ink);
}

/* Each page's ground, taken from its own panel on the hub so the arrival is
   continuous rather than a jump to an unrelated colour. */
.taxi-w.discipline[data-dsc="websites"] { --g-bg: #e9eef5; --g-ink: #0a0f18; --g-soft: #33405a; --g-rim: rgba(10,15,24,.16);  --g-tint: rgba(90,120,200,.16); --g-acc: var(--dsc-mint-ink); }
.taxi-w.discipline[data-dsc="mobile"]   { --g-bg: #0b1030; --g-ink: #eaf0ff; --g-soft: #a8b4dd; --g-rim: rgba(234,240,255,.22); --g-tint: rgba(90,120,255,.20); --g-acc: var(--dsc-mint); }
.taxi-w.discipline[data-dsc="shop"]     { --g-bg: #07100c; --g-ink: #e9f7f0; --g-soft: #9fc4b3; --g-rim: rgba(233,247,240,.22); --g-tint: rgba(33,241,168,.13); --g-acc: var(--dsc-mint); }
.taxi-w.discipline[data-dsc="brand"]    { --g-bg: #16070f; --g-ink: #fbeef4; --g-soft: #d3a9bd; --g-rim: rgba(251,238,244,.22); --g-tint: rgba(232,60,120,.18); --g-acc: var(--dsc-mint); }

/* THE RESET IS WRAPPED IN :where() SO IT WEIGHS NOTHING, and that is the whole
   point of it. Written the obvious way — `.taxi-w.discipline p { margin: 0 }` —
   it scores 0,1,1 and out-specifies every single-class `.dsc-* { margin-top }`
   below, which silently zeroes them. That exact bug shipped on the hub and cost
   an afternoon: five lists computed to marginTop 0px and the gap under one
   heading measured ONE PIXEL. :where() contributes zero, so a component rule
   always wins and a reset can never be the reason spacing disappeared. */
/* Split deliberately. `list-style` and `padding` must BEAT the shared sheet's
   element-level list rules, so they keep real specificity. `margin` must LOSE
   to every component below it, so it is the one wrapped in :where(). Putting
   the whole reset at zero weight let the shared sheet's markers back in. */
.taxi-w.discipline :is(ul, ol) { padding: 0; }
/* The li needs its own list-style: the shared sheet sets one on the element, and
   a specified value on the child beats an inherited one from the parent. Padding
   is deliberately NOT reset here — .dsc-list li owns padding-left, and at 0,1,1
   it would lose to a 0,2,1 reset. */
.taxi-w.discipline :is(ul, ol, li) { list-style: none; }
:where(.taxi-w.discipline) :where(ul, ol, p, h1, h2, h3, h4, dl, dd, figure, blockquote) { margin: 0; }
.taxi-w.discipline img { display: block; max-width: 100%; }

.taxi-w.discipline :where(a, button):focus-visible {
  outline: 2px solid var(--dsc-mint);
  outline-offset: 3px;
  border-radius: .25rem;
}

.dsc-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 60;
  padding: .75rem 1.25rem;
  background: var(--dsc-ink);
  color: var(--dsc-bg);
  border-radius: .5rem;
  font-family: 'Quicksand Label', Arial, sans-serif;
  font-size: .8125rem;
}
.dsc-skip:focus { left: 1rem; top: 1rem; }

/* ── atoms ─────────────────────────────────────────────────────────────── */

.dsc-s { padding-block: var(--dsc-rhythm); }
.dsc-wrap {
  width: 100%;
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: var(--padding--container);
}

.dsc-eyebrow {
  font-family: 'Quicksand Label', Arial, sans-serif;
  font-size: .625rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  font-variation-settings: "wght" 700;
  color: var(--dsc-grey);
}
.dsc-eyebrow b { color: var(--dsc-mint-ink); font-weight: inherit; }

.dsc-h2 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 700, "wdth" 93;
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  line-height: 1.05;
  letter-spacing: -.02em;
  margin-top: .75rem;
  max-width: 22ch;
}

.dsc-body {
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--dsc-ink-soft);
  max-width: 62ch;
  margin-top: 1.25rem;
}
.dsc-body b, .dsc-body strong {
  font-weight: inherit;
  font-variation-settings: "wght" 650;
  color: var(--dsc-ink);
}
.dsc-body a { color: inherit; text-underline-offset: .25em; }

.dsc-ico { width: 1.125rem; height: 1.125rem; flex: none; display: block; }

/* THE LIST PRIMITIVE — the fix for the defect this file's header describes.
   `display: block` and an absolutely positioned marker. The li never becomes a
   grid or flex container, so a <b> followed by loose text is just inline
   content and wraps like prose. Nothing about the content can break it. */
.dsc-list { display: block; margin-top: 1.5rem; }
.dsc-list li {
  display: block;
  position: relative;
  padding-left: 1.75rem;
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--dsc-grey);
}
.dsc-list li + li { margin-top: .875rem; }
/* Markers are icons, not squares: an included line gets a circled check, an
   excluded line a circled minus. Drawn as masks so the one background-color
   channel keeps working everywhere the old square was recolored (the fork
   cards repaint it with --g-acc and nothing there has to change). */
.dsc-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .28em;
  width: 1.0625rem;
  height: 1.0625rem;
  background: var(--dsc-mint-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.2 12.4l2.6 2.6 5-5.6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.2 12.4l2.6 2.6 5-5.6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.dsc-list.is-out li::before {
  background: var(--dsc-grey);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.4 12h7.2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.4 12h7.2'/%3E%3C/svg%3E");
}
.dsc-list b {
  font-weight: inherit;
  font-variation-settings: "wght" 650;
  color: var(--dsc-ink);
}

/* ── drawings ──────────────────────────────────────────────────────────── */

.dsc-scene {
  display: block;
  width: 100%;
  height: auto;
  --ill-fill: color-mix(in srgb, currentColor 13%, transparent);
  --ill-fill-2: color-mix(in srgb, currentColor 7%, transparent);
  --ill-fill-3: color-mix(in srgb, currentColor 24%, transparent);
  --ill-panel: var(--dsc-bg);
  --ill-accent: var(--dsc-mint);
  --ill-on-accent: #040504;
}
/* On a dark ground the tonal room below the ink is far smaller than above a
   light one, so the same percentages measure invisible. */
.dsc-on-ground .dsc-scene,
.dsc-hero .dsc-scene {
  --ill-panel: var(--g-bg);
  --ill-fill: color-mix(in srgb, currentColor 17%, transparent);
  --ill-fill-2: color-mix(in srgb, currentColor 9%, transparent);
  --ill-fill-3: color-mix(in srgb, currentColor 32%, transparent);
}
.taxi-w.discipline[data-dsc="websites"] .dsc-hero .dsc-scene,
.taxi-w.discipline[data-dsc="websites"] .dsc-on-ground .dsc-scene {
  --ill-fill: color-mix(in srgb, currentColor 13%, transparent);
  --ill-fill-2: color-mix(in srgb, currentColor 7%, transparent);
  --ill-fill-3: color-mix(in srgb, currentColor 24%, transparent);
}

/* ── 1 · the hero ──────────────────────────────────────────────────────── */

.dsc-hero {
  position: relative;
  background: var(--g-bg);
  color: var(--g-ink);
  overflow: clip;
  isolation: isolate;
  /* real padding, not a margin on .dsc-spec: overflow: clip is not a BFC, so
     a child margin would collapse out and open a paper-colored gap under the
     hero */
  padding-bottom: clamp(2.5rem, 6vh, 4rem);
}
.dsc-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(115% 78% at 82% 24%, var(--g-tint), transparent 62%);
}
.dsc-hero-in {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
  padding-top: calc(var(--on-t-nav-spacer, 5.375rem) + 2.5rem);
  padding-bottom: clamp(3rem, 8vh, 5.5rem);
}

.dsc-crumb {
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--g-soft);
}
.dsc-crumb a { color: inherit; text-underline-offset: .3em; }
.dsc-crumb a:hover { color: var(--g-ink); }
.dsc-crumb b { color: var(--g-ink); font-weight: inherit; }

.dsc-h1 {
  font-family: Orbitron, Arial, sans-serif;
  font-weight: 700;
  font-size: clamp(1.875rem, 4.6vw, 4.25rem);
  line-height: .98;
  letter-spacing: -.02em;
  text-transform: uppercase;
  margin-top: 1.25rem;
  max-width: 13ch;
}
.dsc-lede {
  font-family: Quicksand, Arial, sans-serif;
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  line-height: 1.5;
  color: var(--g-soft);
  max-width: 46ch;
  margin-top: 1.25rem;
}
.dsc-lede b { color: var(--g-ink); font-weight: inherit; font-variation-settings: "wght" 650; }

.dsc-hero-art { justify-self: end; width: 100%; max-width: min(26rem, 52vh); }

/* The spec strip: what a reader checking you out wants in ten seconds. One
   bordered plate under the hero copy — a dossier, not five bare columns. The
   cells are numbered by CSS counter so the markup stays a plain <dl>, and each
   cell repaints a slightly lifted ground so the hairlines read as drawn rules
   rather than table borders. */
.dsc-spec {
  position: relative;
  z-index: 1;
  counter-reset: dsc-spec;
  display: grid;
  /* exactly five columns, never auto-fit: five cells in any other count leaves
     an empty tile in the plate */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--g-rim);
  border: 1px solid var(--g-rim);
  border-radius: 1rem;
  overflow: clip;
}
.dsc-spec > div {
  counter-increment: dsc-spec;
  background: color-mix(in srgb, var(--g-ink) 4%, var(--g-bg));
  padding: 1.35rem 1.35rem 1.6rem;
}
.dsc-spec dt {
  display: flex;
  align-items: baseline;
  gap: .625rem;
  font-family: 'Quicksand Label', Arial, sans-serif;
  font-size: .625rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--g-soft);
}
.dsc-spec dt::before {
  content: counter(dsc-spec, decimal-leading-zero);
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .6875rem;
  letter-spacing: 0;
  color: var(--g-acc);
}
.dsc-spec dd {
  font-family: Quicksand, Arial, sans-serif;
  font-size: .9375rem;
  line-height: 1.45;
  color: var(--g-ink);
  margin-top: .625rem;
}

/* ── 2 · the diagram set — 5 or 6 drawings that carry the argument ─────── */

.dsc-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
  margin-top: clamp(2.5rem, 6vw, 4rem);
}
.dsc-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--dsc-rim);
  border-radius: 1.25rem;
  overflow: clip;
  background: var(--dsc-bg);
  transition: border-color .35s var(--dsc-ease);
}
.dsc-card:hover { border-color: var(--dsc-ink); }
.dsc-card-fig {
  background: var(--dsc-surface);
  border-bottom: 1px solid var(--dsc-line);
  padding: 1.25rem;
}
.dsc-card-fig .dsc-scene { --ill-panel: var(--dsc-surface); }
.dsc-card-b { padding: 1.25rem 1.375rem 1.5rem; }
.dsc-card-k {
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dsc-grey);
}
.dsc-card h3 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: 1.125rem;
  line-height: 1.25;
  margin-top: .5rem;
}
.dsc-card p {
  font-family: Quicksand, Arial, sans-serif;
  font-size: .9375rem;
  line-height: 1.55;
  color: var(--dsc-grey);
  margin-top: .625rem;
}

/* ── 3 · the signature band — full bleed, back in the page's own colour ── */

.dsc-band {
  background: var(--g-bg);
  color: var(--g-ink);
  position: relative;
  isolation: isolate;
  padding-block: clamp(4rem, 10vh, 7rem);
}
/* No `overflow: clip` here on purpose: a signature band holds a position:sticky
   stage, and an overflow value on an ancestor is the classic way to break one.
   Nothing inside needs clipping — the tint is an inset-0 pseudo-element. */
.dsc-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(110% 70% at 20% 18%, var(--g-tint), transparent 60%);
}
.dsc-band .dsc-wrap { position: relative; z-index: 1; }
.dsc-band .dsc-eyebrow { color: var(--g-soft); }
.dsc-band .dsc-eyebrow b { color: var(--g-acc); }
.dsc-band .dsc-h2 { color: var(--g-ink); }
.dsc-band .dsc-body { color: var(--g-soft); }
.dsc-band .dsc-body b, .dsc-band .dsc-body strong { color: var(--g-ink); }

/* ── SIGNATURE · websites — THE THREE PLANES ──────────────────────────── */

/* Three drawings of the same page at the same coordinates. Merged they are one
   page; scrolled, they pull apart into the three files it is made of, and then
   reassemble.

   The separation is a TRIANGLE WAVE off the single number init.js writes:
     a   = p * 2 - 1        →  -1 … 0 … 1
     sep = 1 - |a|          →   0 … 1 … 0
   and |a| is `max(a, -a)`, which is plain CSS with no abs() dependency. So the
   whole mechanism is one custom property in and pure declarative maths out —
   the script never knows a plane exists.

   BASE = the no-JS pose. --dsc-p is unset, so sep resolves to 0 through the
   fallback and the deck renders merged and flat: one finished page, which is
   the settled state. The pin, the perspective and the wave are all inside the
   .dscjs gate, and reduced motion peels them off again. */
.dsc-planes { position: relative; }
.dsc-planes-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
  align-items: center;
  gap: clamp(2rem, 5vw, 4rem);
  width: 100%;
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: var(--padding--container);
  padding-block: clamp(2rem, 6vh, 4rem);
}
.dsc-planes-deck {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: min(38rem, 62vh);
  aspect-ratio: 4 / 3;
}
.dsc-plane { position: absolute; inset: 0; }
.dsc-plane .dsc-scene { --ill-panel: var(--g-bg); }
/* Merged, only the finished page shows; the other two are annotations that
   arrive as it comes apart. `display: none` rather than `opacity: 0` on
   purpose — an element parked at zero opacity in the settled state reads as a
   stuck reveal to every harness that counts them, and rightly so. These are
   alternates, like the hero's four silhouettes: not rendered is the finished
   pose, not a hidden one. */
.dsc-plane.is-1,
.dsc-plane.is-3 { display: none; }
.dsc-plane-tag {
  position: absolute;
  left: 0;
  top: -2.25rem;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .35rem .7rem;
  border-radius: 2rem;
  background: var(--g-ink);
  color: var(--g-bg);
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .6875rem;
  letter-spacing: .04em;
  opacity: 0;
}
.dsc-plane-tag i { font-style: normal; opacity: .6; }

.dscjs .dsc-planes {
  height: 300vh;
  --a: calc(var(--dsc-p, 0) * 2 - 1);
  --sep: calc(1 - max(var(--a), var(--a) * -1));
}
.dscjs .dsc-planes-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  perspective: 1600px;
  padding-block: 0;
}
.dscjs .dsc-planes-deck {
  transform-style: preserve-3d;
  transform:
    rotateX(calc(var(--sep) * 44deg))
    rotateZ(calc(var(--sep) * -7deg))
    scale(calc(1 - var(--sep) * .08));
}
.dscjs .dsc-plane { transform-style: preserve-3d; }
.dscjs .dsc-plane.is-1 { display: block; transform: translate3d(0, 0, calc(var(--sep) * 190px)); opacity: var(--sep); }
.dscjs .dsc-plane.is-3 { display: block; transform: translate3d(0, 0, calc(var(--sep) * -190px)); opacity: var(--sep); }
.dscjs .dsc-plane-tag { opacity: var(--sep); }

/* The roles, read out beside the deck. Each is keyed to the step index the
   scrub publishes, so the words change as the planes come apart. */
.dsc-planes-read {
  position: relative;
  z-index: 2;
  margin-top: clamp(2rem, 5vh, 3.5rem);
  min-height: 7.5rem;
}
.dsc-planes-read li {
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--g-soft);
  max-width: 54ch;
}
.dsc-planes-read li + li { margin-top: .875rem; }
.dsc-planes-read b { color: var(--g-ink); font-weight: inherit; font-variation-settings: "wght" 650; }
/* THE INACTIVE ITEM IS NOT DIMMED, and that is a correctness decision. Fading
   real prose to 0.3 opacity to mark it inactive drops it under 3:1 on every one
   of these grounds — it is still text, a reader still has to be able to read it,
   and "it is not the current step" is not a licence to fail contrast. So the
   current item is marked with a rule and a colour promotion instead, and every
   line stays at a ratio that passes whether it is current or not. */
.dscjs .dsc-planes-read { min-height: 0; }
.dscjs .dsc-planes-read li {
  padding-left: 1rem;
  border-left: 2px solid transparent;
  transition: color .45s var(--dsc-ease), border-color .45s var(--dsc-ease);
}
.dscjs .dsc-planes[data-dsc-i="1"] .dsc-planes-read li:nth-child(1),
.dscjs .dsc-planes[data-dsc-i="2"] .dsc-planes-read li:nth-child(2),
.dscjs .dsc-planes[data-dsc-i="3"] .dsc-planes-read li:nth-child(3) {
  color: var(--g-ink);
  border-left-color: var(--g-acc);
}


/* ── SIGNATURE · mobile — FIVE SCREENS, ONE THUMB ─────────────────────── */

/* One device, five states, one question per state. The five drawings are
   COMPLETE phones at identical geometry rather than one shell with inserts —
   see wid-scenes.svg — so switching between them cannot drift by a pixel.

   BASE = the no-JS pose: state 01 rendered, the other four not in the tree.
   They are alternates, not reveals; five stacked phones with no script to pick
   between them is noise, so `display: none` here IS the settled state. */
.dsc-flow { position: relative; }
.dsc-flow-stage {
  display: grid;
  grid-template-columns: minmax(0, 26rem) minmax(0, 1fr);
  align-items: center;
  gap: clamp(2rem, 6vw, 5rem);
  width: 100%;
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: var(--padding--container);
  padding-block: clamp(2rem, 6vh, 4rem);
}
.dsc-flow-phone {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: min(24rem, 66vh);
  aspect-ratio: 360 / 740;
}
.dsc-flow-screen { position: absolute; inset: 0; display: none; }
.dsc-flow-screen.is-1 { display: block; }
.dsc-flow-screen .dsc-scene { --ill-panel: var(--g-bg); }

.dsc-flow-steps { counter-reset: none; }
.dsc-flow-steps li { position: relative; padding-left: 3rem; }
.dsc-flow-steps li + li { margin-top: clamp(1.25rem, 3vh, 2rem); }
.dsc-flow-steps .n {
  position: absolute;
  left: 0;
  top: .1em;
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .75rem;
  letter-spacing: .1em;
  color: var(--g-soft);
}
.dsc-flow-steps h3 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: clamp(1.0625rem, 1.8vw, 1.375rem);
  line-height: 1.25;
  color: var(--g-ink);
}
.dsc-flow-steps p {
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--g-soft);
  max-width: 44ch;
  margin-top: .5rem;
}

/* 5 states x 76vh. 460vh (92vh a state) read as generous scrolling for a
   diagram; below about 70vh a state the change starts to feel like a flicker. */
.dscjs .dsc-flow { height: 380vh; }
.dscjs .dsc-flow-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  align-content: center;
  padding-block: 0;
}
.dscjs .dsc-flow-screen {
  display: block;
  opacity: 0;
  transition: opacity .45s var(--dsc-ease);
}
.dscjs .dsc-flow[data-dsc-i="0"] .dsc-flow-screen.is-1,
.dscjs .dsc-flow[data-dsc-i="1"] .dsc-flow-screen.is-2,
.dscjs .dsc-flow[data-dsc-i="2"] .dsc-flow-screen.is-3,
.dscjs .dsc-flow[data-dsc-i="3"] .dsc-flow-screen.is-4,
.dscjs .dsc-flow[data-dsc-i="4"] .dsc-flow-screen.is-5 { opacity: 1; }
/* Same rule as the planes read list: the step that is not current is still
   prose somebody may be reading, so it keeps its contrast and loses only its
   marker. Nothing here is ever dimmed below a passing ratio. */
.dscjs .dsc-flow-steps h3 { color: var(--g-soft); transition: color .45s var(--dsc-ease); }
.dscjs .dsc-flow-steps .n { transition: color .45s var(--dsc-ease); }
.dscjs .dsc-flow-steps li::before {
  content: "";
  position: absolute;
  left: 2rem;
  top: .35em;
  bottom: .35em;
  width: 2px;
  background: transparent;
  transition: background-color .45s var(--dsc-ease);
}
.dscjs .dsc-flow[data-dsc-i="0"] .dsc-flow-steps li:nth-child(1) h3,
.dscjs .dsc-flow[data-dsc-i="1"] .dsc-flow-steps li:nth-child(2) h3,
.dscjs .dsc-flow[data-dsc-i="2"] .dsc-flow-steps li:nth-child(3) h3,
.dscjs .dsc-flow[data-dsc-i="3"] .dsc-flow-steps li:nth-child(4) h3,
.dscjs .dsc-flow[data-dsc-i="4"] .dsc-flow-steps li:nth-child(5) h3 { color: var(--g-ink); }
.dscjs .dsc-flow[data-dsc-i="0"] .dsc-flow-steps li:nth-child(1)::before,
.dscjs .dsc-flow[data-dsc-i="1"] .dsc-flow-steps li:nth-child(2)::before,
.dscjs .dsc-flow[data-dsc-i="2"] .dsc-flow-steps li:nth-child(3)::before,
.dscjs .dsc-flow[data-dsc-i="3"] .dsc-flow-steps li:nth-child(4)::before,
.dscjs .dsc-flow[data-dsc-i="4"] .dsc-flow-steps li:nth-child(5)::before { background: var(--g-acc); }
.dscjs .dsc-flow[data-dsc-i="0"] .dsc-flow-steps li:nth-child(1) .n,
.dscjs .dsc-flow[data-dsc-i="1"] .dsc-flow-steps li:nth-child(2) .n,
.dscjs .dsc-flow[data-dsc-i="2"] .dsc-flow-steps li:nth-child(3) .n,
.dscjs .dsc-flow[data-dsc-i="3"] .dsc-flow-steps li:nth-child(4) .n,
.dscjs .dsc-flow[data-dsc-i="4"] .dsc-flow-steps li:nth-child(5) .n { color: var(--g-acc); }


/* ── SIGNATURE · e-commerce — THE FORK ────────────────────────────────── */

/* The page physically diverges. A single stem comes down, splits, and the two
   answers move apart into their own columns — because the honest version of
   "should you have a custom store" has a side I lose, and a layout that puts
   both sides on one axis says that before the copy does.

   No pin here, deliberately. The scrub runs off the section's own travel
   across the viewport, so the page does not grow by 300vh to hold a diagram
   that reads perfectly well in place.

   BASE = --dsc-p unset → the fallback is 1 → fully forked and fully drawn,
   which is the settled, readable state. Nothing here is ever hidden: the
   branches move, they do not fade, so no reader can lose a sentence to a
   scroll position. */
.dsc-fork { position: relative; --p: var(--dsc-p, 1); }
.dsc-fork-line {
  display: block;
  width: 100%;
  height: auto;
  color: var(--g-soft);
  margin-bottom: clamp(1rem, 3vh, 2rem);
}
.dsc-fork-path {
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--p));
}
.dsc-fork-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}
.dsc-fork-branch {
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border: 1px solid var(--g-rim);
  border-radius: 1.25rem;
  transition: transform .1s linear;
}
.dscjs .dsc-fork-branch.is-l { transform: translateX(calc((1 - var(--p)) * 26%)); }
.dscjs .dsc-fork-branch.is-r { transform: translateX(calc((1 - var(--p)) * -26%)); }
.dsc-fork-h {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: clamp(1.0625rem, 1.8vw, 1.375rem);
  line-height: 1.3;
  color: var(--g-ink);
  max-width: 26ch;
}
.dsc-fork-branch .dsc-list li { color: var(--g-soft); }
.dsc-fork-branch .dsc-list li::before { background: var(--g-acc); }
.dsc-fork-branch .dsc-list b { color: var(--g-ink); }
.dsc-fork-k {
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--g-acc);
  margin-bottom: .625rem;
}
/* Where the two tracks come back together. */
.dsc-rejoin {
  margin-top: clamp(2.5rem, 6vh, 4rem);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-radius: 1.25rem;
  background: color-mix(in srgb, var(--g-ink) 8%, transparent);
  border: 1px solid var(--g-rim);
}
.dsc-rejoin p {
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--g-soft);
  max-width: 70ch;
}
.dsc-rejoin b { color: var(--g-ink); font-weight: inherit; font-variation-settings: "wght" 650; }


/* ── SIGNATURE · graphic design — NOTHING IS DRAWN TWICE ──────────────── */

/* A drafting sheet assembles the identity in build order: the construction
   grid, the monogram inked along its own guides, then palette, type and
   pattern, each measured off the mark — and the dashed frames at the foot,
   present from the first pixel, convert one by one into the surfaces the mark
   has to survive. The last beat fills the title block's seal.

   Same contract as the other two signatures: ONE custom property. Every group
   derives its own local 0→1 window from --dsc-p, so there is no chain of
   index selectors and no second rAF. At the base (--dsc-p unset, --p falls
   back to 1) every window is complete and the sheet is whole — that is the
   settled, no-JS, reduced-motion state. */
.dsc-sheet {
  position: relative;
  --p: var(--dsc-p, 1);
  --w-grid: clamp(0, calc(var(--p) * 7.2), 1);
  --w-d1: clamp(0, calc((var(--p) - .17) * 10), 1);
  --w-d2: clamp(0, calc((var(--p) - .25) * 10), 1);
  --w-ink: clamp(0, calc((var(--p) - .31) * 20), 1);
  --w-pal: clamp(0, calc((var(--p) - .34) * 7.7), 1);
  --w-type: clamp(0, calc((var(--p) - .5) * 8.3), 1);
  --w-pat: clamp(0, calc((var(--p) - .67) * 7.7), 1);
  --w-a0: clamp(0, calc((var(--p) - .83) * 33), 1);
  --w-a1: clamp(0, calc((var(--p) - .854) * 33), 1);
  --w-a2: clamp(0, calc((var(--p) - .878) * 33), 1);
  --w-a3: clamp(0, calc((var(--p) - .902) * 33), 1);
  --w-a4: clamp(0, calc((var(--p) - .926) * 33), 1);
  --w-a5: clamp(0, calc((var(--p) - .95) * 33), 1);
  --w-seal: clamp(0, calc((var(--p) - .97) * 33), 1);
}
.dsc-sheet-stage {
  display: grid;
  grid-template-columns: minmax(0, 30rem) minmax(0, 1fr);
  align-items: center;
  gap: clamp(2rem, 6vw, 5rem);
  width: 100%;
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: var(--padding--container);
  padding-block: clamp(2rem, 6vh, 4rem);
}
.dsc-sheet-fig {
  justify-self: center;
  width: 100%;
  max-width: min(30rem, 72vh);
}
.dsc-sheet-svg { display: block; width: 100%; height: auto; }
.shg-grid { opacity: var(--w-grid); }
.shg-draw { fill: none; stroke-dasharray: 1; }
.shg-d1 { stroke-dashoffset: calc(1 - var(--w-d1)); }
.shg-d2 { stroke-dashoffset: calc(1 - var(--w-d2)); }
.shg-ink { opacity: var(--w-ink); }
.shg-palette { opacity: var(--w-pal); transform: translateX(calc((1 - var(--w-pal)) * 12px)); }
.shg-type { opacity: var(--w-type); transform: translateY(calc((1 - var(--w-type)) * 12px)); }
.shg-pattern { opacity: var(--w-pat); transform: translateX(calc((1 - var(--w-pat)) * -12px)); }
.shg-a0 .shg-fin { opacity: var(--w-a0); }
.shg-a0 .shg-ph { opacity: calc(1 - var(--w-a0)); }
.shg-a1 .shg-fin { opacity: var(--w-a1); }
.shg-a1 .shg-ph { opacity: calc(1 - var(--w-a1)); }
.shg-a2 .shg-fin { opacity: var(--w-a2); }
.shg-a2 .shg-ph { opacity: calc(1 - var(--w-a2)); }
.shg-a3 .shg-fin { opacity: var(--w-a3); }
.shg-a3 .shg-ph { opacity: calc(1 - var(--w-a3)); }
.shg-a4 .shg-fin { opacity: var(--w-a4); }
.shg-a4 .shg-ph { opacity: calc(1 - var(--w-a4)); }
.shg-a5 .shg-fin { opacity: var(--w-a5); }
.shg-a5 .shg-ph { opacity: calc(1 - var(--w-a5)); }
.shg-seal {
  opacity: var(--w-seal);
  transform: scale(calc(.7 + .3 * var(--w-seal)));
  transform-box: fill-box;
  transform-origin: center;
}

.dsc-sheet-steps li { position: relative; padding-left: 3rem; }
.dsc-sheet-steps li + li { margin-top: clamp(1rem, 2.5vh, 1.5rem); }
.dsc-sheet-steps .n {
  position: absolute;
  left: 0;
  top: .1em;
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .75rem;
  letter-spacing: .1em;
  color: var(--g-soft);
}
.dsc-sheet-steps h3 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  line-height: 1.25;
  color: var(--g-soft);
}
.dsc-sheet-steps p {
  font-family: Quicksand, Arial, sans-serif;
  font-size: .9375rem;
  line-height: 1.55;
  color: var(--g-soft);
  max-width: 42ch;
  margin-top: .375rem;
}
/* Marked, never dimmed — same rule as the other two signatures. */
.dscjs .dsc-sheet-steps h3 { transition: color .4s var(--dsc-ease); }
.dscjs .dsc-sheet-steps li::before {
  content: "";
  position: absolute;
  left: 2rem;
  top: .3em;
  bottom: .3em;
  width: 2px;
  background: transparent;
  transition: background-color .4s var(--dsc-ease);
}
.dscjs .dsc-sheet[data-dsc-i="0"] .dsc-sheet-steps li:nth-child(1) h3,
.dscjs .dsc-sheet[data-dsc-i="1"] .dsc-sheet-steps li:nth-child(2) h3,
.dscjs .dsc-sheet[data-dsc-i="2"] .dsc-sheet-steps li:nth-child(3) h3,
.dscjs .dsc-sheet[data-dsc-i="3"] .dsc-sheet-steps li:nth-child(4) h3,
.dscjs .dsc-sheet[data-dsc-i="4"] .dsc-sheet-steps li:nth-child(5) h3,
.dscjs .dsc-sheet[data-dsc-i="5"] .dsc-sheet-steps li:nth-child(6) h3 { color: var(--g-ink); }
.dscjs .dsc-sheet[data-dsc-i="0"] .dsc-sheet-steps li:nth-child(1)::before,
.dscjs .dsc-sheet[data-dsc-i="1"] .dsc-sheet-steps li:nth-child(2)::before,
.dscjs .dsc-sheet[data-dsc-i="2"] .dsc-sheet-steps li:nth-child(3)::before,
.dscjs .dsc-sheet[data-dsc-i="3"] .dsc-sheet-steps li:nth-child(4)::before,
.dscjs .dsc-sheet[data-dsc-i="4"] .dsc-sheet-steps li:nth-child(5)::before,
.dscjs .dsc-sheet[data-dsc-i="5"] .dsc-sheet-steps li:nth-child(6)::before { background: var(--g-acc); }

.dscjs .dsc-sheet { height: 420vh; }
.dscjs .dsc-sheet-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  align-content: center;
  padding-block: 0;
}

/* ── 4 · scope, two columns of equal weight ───────────────────────────── */

.dsc-scope {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin-top: clamp(2rem, 5vw, 3rem);
  background: var(--dsc-line);
  border: 1px solid var(--dsc-line);
  border-radius: 1.25rem;
  overflow: clip;
}
.dsc-scope-col { background: var(--dsc-bg); padding: clamp(1.5rem, 3vw, 2.25rem); }
.dsc-scope-h {
  display: flex;
  align-items: center;
  gap: .625rem;
  font-family: 'Quicksand Label', Arial, sans-serif;
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dsc-ink);
}
.dsc-scope-h .dsc-ico { color: var(--dsc-mint-ink); }
.dsc-scope-col.is-out .dsc-scope-h .dsc-ico { color: var(--dsc-grey); }

/* ── 5 · the objections ───────────────────────────────────────────────── */

.dsc-obj { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.dsc-q {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650, "wdth" 93;
  font-size: clamp(1.375rem, 2.4vw, 1.875rem);
  line-height: 1.2;
  letter-spacing: -.015em;
  max-width: 26ch;
}
.dsc-measure {
  margin-top: 1.5rem;
  padding: 1rem 1.125rem;
  border-radius: .875rem;
  background: var(--dsc-surface-2);
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .75rem;
  line-height: 1.6;
  color: var(--dsc-ink-soft);
  max-width: 62ch;
}

.dsc-a {
  font-family: Quicksand, Arial, sans-serif;
  font-size: 1.1875rem;
  line-height: 1.55;
  color: var(--dsc-ink);
  max-width: 60ch;
  margin-top: 1rem;
  padding-left: 1.25rem;
  border-left: 2px solid var(--dsc-mint);
}

/* ── 6 · the work ─────────────────────────────────────────────────────── */

.dsc-work {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  margin-top: clamp(2.5rem, 6vw, 4rem);
}
.dsc-piece {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: 1.25rem;
  overflow: clip;
  background: var(--dsc-surface);
  border: 1px solid var(--dsc-rim);
  transition: border-color .4s var(--dsc-ease), transform .4s var(--dsc-ease);
}
.dsc-piece:hover { border-color: var(--dsc-ink); transform: translateY(-.35rem); }
.dsc-piece img { width: 100%; height: auto; }
.dsc-piece figcaption,
.dsc-piece-b {
  padding: 1.125rem 1.25rem 1.375rem;
  border-top: 1px solid var(--dsc-line);
  background: var(--dsc-bg);
  margin-top: auto;
}
.dsc-piece h3 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: 1rem;
}
.dsc-piece p,
.dsc-piece figcaption {
  font-family: Quicksand, Arial, sans-serif;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--dsc-grey);
}
.dsc-piece h3 + p { margin-top: .3rem; }
.dsc-piece a::after { content: ""; position: absolute; inset: 0; }

/* ── 7 · close and switcher ───────────────────────────────────────────── */

.dsc-cta {
  background: linear-gradient(180deg, var(--dsc-bg) 0%, #e8f8f0 100%);
  padding-block: clamp(4rem, 11vh, 8rem);
}
.dsc-cta-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 28rem);
  align-items: center;
  gap: clamp(2rem, 6vw, 4.5rem);
}
.dsc-cta-h {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 720, "wdth" 93;
  font-size: clamp(1.875rem, 4.4vw, 3.5rem);
  line-height: 1.02;
  letter-spacing: -.03em;
  max-width: 14ch;
  margin-top: .75rem;
}
.dsc-cta-art { justify-self: end; width: 100%; max-width: 28rem; }
.dsc-cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem;
  margin-top: 2rem;
}
.dsc-tlink {
  color: var(--dsc-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--dsc-rim);
  padding-bottom: .2rem;
  min-height: 24px;
  box-sizing: border-box;
  font-family: 'Quicksand Label', Arial, sans-serif;
  font-size: .8125rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  transition: border-color .3s var(--dsc-ease);
}
.dsc-tlink:hover { border-color: var(--dsc-ink); }

/* THE OTHER THREE — an index of the remaining worlds rather than three orphan
   cards. Each row wears its destination's hero ground as its numbered plate
   (keyed by href, so the markup stays three plain anchors), and the section
   ground runs the CTA's pale mint back down to the page paper, which is what
   the shared footer band paints — so the handover to the footer has no seam. */
.dsc-switch-s {
  background: linear-gradient(180deg, #e8f8f0 0%, var(--dsc-bg) 72%);
  padding-block: clamp(3.5rem, 8vh, 5.5rem) clamp(4rem, 9vh, 6rem);
}
.dsc-switch-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.dsc-switch-h h2 {
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: 1.25rem;
}
.dsc-switch {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: .875rem;
  margin-top: 1.75rem;
}
.dsc-switch-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "n name arrow" "n note arrow";
  align-items: center;
  column-gap: clamp(1.125rem, 3vw, 1.75rem);
  padding: 1rem clamp(1.25rem, 3vw, 1.875rem) 1rem 1rem;
  min-height: 24px;
  box-sizing: border-box;
  border: 1px solid var(--dsc-rim);
  border-radius: 1rem;
  background: var(--dsc-bg);
  color: var(--dsc-ink);
  text-decoration: none;
  transition: border-color .3s var(--dsc-ease), background-color .3s var(--dsc-ease);
}
a.dsc-switch-row:hover { border-color: var(--dsc-ink); background: #fff; }
a.dsc-switch-row[href$="/websites"] { --sw-g: #e9eef5; --sw-i: #0a0f18; }
a.dsc-switch-row[href$="/mobile-apps"] { --sw-g: #0b1030; --sw-i: #eaf0ff; }
a.dsc-switch-row[href$="/e-commerce"] { --sw-g: #07100c; --sw-i: #e9f7f0; }
a.dsc-switch-row[href$="/graphic-design"] { --sw-g: #16070f; --sw-i: #fbeef4; }
.dsc-switch-n {
  grid-area: n;
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: .75rem;
  background: var(--sw-g, var(--dsc-surface));
  color: var(--sw-i, var(--dsc-ink));
  font-family: var(--dsc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .75rem;
  letter-spacing: .1em;
}
.dsc-switch-name {
  grid-area: name;
  align-self: end;
  font-family: Quicksand, Arial, sans-serif;
  font-variation-settings: "wght" 650;
  font-size: 1.0625rem;
}
.dsc-switch-note {
  grid-area: note;
  align-self: start;
  font-family: Quicksand, Arial, sans-serif;
  font-size: .875rem;
  color: var(--dsc-grey);
  margin-top: .125rem;
}
.dsc-switch-row::after {
  content: "";
  grid-area: arrow;
  width: 1.25rem;
  height: 1.25rem;
  background: var(--dsc-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 12h15M13.5 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 12h15M13.5 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .3s var(--dsc-ease);
}
a.dsc-switch-row:hover::after { transform: translateX(.25rem); }

/* ── reveals (gated) ──────────────────────────────────────────────────── */

.dscjs .dsc-reveal { opacity: 0; transform: translateY(1.25rem); }
.dscjs .dsc-reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity .8s var(--dsc-ease), transform .8s var(--dsc-ease);
  transition-delay: calc(var(--i, 0) * 80ms);
}

/* ── responsive ───────────────────────────────────────────────────────── */

@media screen and (max-width: 991px) {
  .dsc-hero-in,
  .dsc-cta-in { grid-template-columns: minmax(0, 1fr); }
  .dsc-hero-art { justify-self: start; max-width: 20rem; order: -1; }
  .dsc-spec { grid-template-columns: minmax(0, 1fr); }
  .dsc-cards,
  .dsc-work { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dsc-scope { grid-template-columns: minmax(0, 1fr); }
  .dsc-planes-stage { grid-template-columns: minmax(0, 1fr); }
  .dscjs .dsc-planes-deck { max-width: min(26rem, 42vh); }
  .dsc-flow-stage { grid-template-columns: minmax(0, 1fr); }
  .dscjs .dsc-flow-phone { max-width: min(12rem, 34vh); }
  .dsc-fork-cols { grid-template-columns: minmax(0, 1fr); }
  .dsc-sheet-stage { grid-template-columns: minmax(0, 1fr); }
  .dscjs .dsc-sheet-fig { max-width: min(21rem, 48vh); }
  .dscjs .dsc-fork-branch.is-l,
  .dscjs .dsc-fork-branch.is-r { transform: none; }
  .dsc-fork-line { display: none; }
}

@media screen and (max-width: 767px) {
  .dsc-cards,
  .dsc-work { grid-template-columns: minmax(0, 1fr); }
  .dsc-switch-h { flex-direction: column; align-items: flex-start; }
  .dsc-switch-n { width: 3rem; height: 3rem; }
}

/* Minimum target size in PIXELS. --fluid-font is viewport-derived and its
   bands do not run continuously — 1rem is 13.31px at 479px and 5.56px at 480px
   — so any rem-based floor collapses exactly where it is needed. 720px matters
   as much as 480: it is what a 1440 desktop becomes at the 200% zoom PAGE-KIT
   requires be tested. */
.dsc-tlink,
.dsc-switch-row,
.dsc-crumb a { min-height: 24px; box-sizing: border-box; }

/* ── reduced motion ───────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .dscjs .dsc-reveal { opacity: 1; transform: none; transition: none; }
  /* Back to the base pose exactly: one merged, finished page, no pin, no tilt. */
  .dscjs .dsc-planes { height: auto; }
  .dscjs .dsc-planes-stage { position: static; height: auto; perspective: none; padding-block: clamp(2rem, 6vh, 4rem); }
  .dscjs .dsc-planes-deck { transform: none; }
  .dscjs .dsc-plane.is-1,
  .dscjs .dsc-plane.is-3 { display: none; }
  .dscjs .dsc-planes-read li { opacity: 1; transition: none; }
  .dscjs .dsc-flow { height: auto; }
  .dscjs .dsc-flow-stage { position: static; height: auto; padding-block: clamp(2rem, 6vh, 4rem); }
  .dscjs .dsc-flow-screen { display: none; opacity: 1; transition: none; }
  .dscjs .dsc-flow-screen.is-1 { display: block; }
  .dscjs .dsc-flow-steps h3,
  .dscjs .dsc-flow-steps .n { transition: none; }
  .dscjs .dsc-planes-read li { transition: none; }
  .dscjs .dsc-fork { --p: 1; }
  .dscjs .dsc-fork-branch { transition: none; transform: none; }
  .dscjs .dsc-sheet { height: auto; --p: 1; }
  .dscjs .dsc-sheet-stage { position: static; height: auto; padding-block: clamp(2rem, 6vh, 4rem); }
  .dscjs .dsc-sheet-steps h3 { transition: none; }
  .dsc-card,
  .dsc-piece,
  .dsc-switch-row,
  .dsc-tlink { transition: none; }
}

/* ═══ RTL — html[dir="rtl"] only ═══════════════════════════════════════════
   The measure line quotes tool names with trailing colons (`axe-core:` read
   as `:axe-core` — the colon is a neutral and flipped to the other end).
   plaintext derives direction from the token's own content. */
html[dir="rtl"] .dsc-measure { unicode-bidi: plaintext; }
