/* ─────────────────────────────────────────────────────────────────────────
   sections.css — §1 to §9 of the home page.

   Layout law from 02 §6: enormous negative space, hairline rules only, no
   card grids, no shadows on UI. Green is current; everything else is ink,
   ink-60 and graphite on white.

   Every section is a scroll extent with a sticky pin inside it. The extent
   provides the travel; the pin holds the frame still while the director
   renders progress into it.
   ───────────────────────────────────────────────────────────────────────── */

/* SECTIONS FLOW AT THEIR OWN HEIGHT.

   They were a 160vh extent with a 100vh sticky pin inside, and that put an
   empty viewport between every pair of them. The pin only sticks for the
   first 60vh; the remaining 100vh is the pin sliding out, with its centred
   content already gone off the top, while the next section's content —
   centred in ITS pin, a viewport further down — has not arrived. Halfway
   through that exit the screen is the empty foot of one pin above the empty
   head of the next: a blank white page you scroll through, once per section.

   Nothing is pinned now. Each section is exactly as tall as its content plus
   its own margin, so the page is continuous, and the reveals still scrub —
   the director composes them on ENTRY and holds. See progressOf(). */
.sec { position: relative; }

.sec-pin {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s4);
  padding: var(--s7) var(--s5);
  max-width: 1560px;
  margin: 0 auto;
}

.sec-head {
  font-size: clamp(30px, 4.4vw, 74px);
  max-width: 18ch;
}

.sec-body {
  font-size: clamp(16px, 1.4vw, 21px);
  color: var(--ink-60);
  max-width: 46ch;
  line-height: 1.5;
}

.sec-copy { display: flex; flex-direction: column; gap: var(--s3); will-change: transform, opacity; }

.reveal { will-change: transform, opacity; }

/* ─────────────────────────────────────────────────────────────────────────
   THE BELT — work already delivered, directly under the hero.

   A capsule pinned to the left edge and bleeding off it, ending in a disc
   with the bolt in it, and the engagements streaming leftward BEHIND it, so
   the capsule reads as the thing pushing them along rather than a control
   parked beside them.

   Out to the page's edges, because a belt that starts and stops inside the
   gutter is a list in a box; one that runs off both sides is a belt.
   ───────────────────────────────────────────────────────────────────────── */

.strip {
  position: relative;
  margin-inline: calc(var(--s5) * -1);
  padding: var(--s6) 0;
  /* Clips the capsule's own bleed and both ends of the belt. */
  overflow: hidden;
}

.strip-rail {
  overflow: hidden;
  /* Only the trailing end is faded — the leading end is the capsule, which
     is opaque and is what the chips are supposed to disappear behind. */
  -webkit-mask-image: linear-gradient(90deg, #000 0 86%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0 86%, transparent 100%);
}

/* `margin-right` per item and NO `gap`: with a gap, one copy of the list is
   half the track minus half a gap, so translating exactly −50% drifts by
   half a gap every lap and the seam walks across the screen. Folding the
   spacing into each item makes one copy exactly half the track. */
.strip-track {
  list-style: none;
  display: flex;
  align-items: center;
  width: max-content;
  animation: strip-run 42s linear infinite;
}

@keyframes strip-run { to { transform: translate3d(-50%, 0, 0); } }

/* A belt the visitor is trying to read should stop while they read it. */
.strip:hover .strip-track,
.strip:focus-within .strip-track { animation-play-state: paused; }

.strip-item {
  flex: none;
  margin-right: var(--s3);
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  padding: 9px var(--s4) 9px 9px;
  border: var(--hairline);
  border-radius: 999px;
  white-space: nowrap;
}

.strip-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--leaf-08);
  color: var(--leaf);
}

.strip-mark svg { width: 18px; height: 18px; }

.strip-label { letter-spacing: 0.1em; color: var(--ink); }
.strip-label .sep { color: var(--graphite); }
.strip-label .place { color: var(--ink-60); }

/* ── the capsule ───────────────────────────────────────────────────────── */

.strip-head {
  position: absolute;
  top: 50%;
  /* Starts off the left edge and is clipped by the section, so it reads as
     continuing past the page. The left padding puts its text back on the
     page's own gutter. */
  left: calc(var(--s5) * -1);
  translate: 0 -50%;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--s4);
  padding: 7px 7px 7px calc(var(--s5) * 2);
  background: var(--leaf);
  border-radius: 999px;
}

.strip-head-text { color: var(--ink); letter-spacing: 0.16em; }

.strip-bolt {
  flex: none;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--leaf);
}

.strip-bolt svg { width: 19px; height: 28px; display: block; }

@media (max-width: 720px) {
  .strip { margin-inline: calc(var(--s3) * -1); padding: var(--s5) 0; }
  .strip-head {
    left: calc(var(--s3) * -1);
    gap: var(--s3);
    padding-left: calc(var(--s3) * 2);
  }
  .strip-bolt { width: 46px; height: 46px; }
  .strip-bolt svg { width: 16px; height: 24px; }
  .strip-item { padding: 7px var(--s3) 7px 7px; gap: var(--s2); }
  .strip-mark { width: 30px; height: 30px; }
  .strip-mark svg { width: 15px; height: 15px; }
}

/* Stopped, and scrollable by hand instead — a belt that cannot move still
   has to let the visitor reach the far end of it. */
@media (prefers-reduced-motion: reduce) {
  .strip-track { animation: none; }
  .strip-rail { overflow-x: auto; scrollbar-width: none; }
  .strip-rail::-webkit-scrollbar { display: none; }
}

/* ── §1 the claim ──────────────────────────────────────────────────────── */

.sec-claim .sec-pin { gap: var(--s3); }

.claim-wire {
  position: relative;
  height: 2px;
  margin-top: var(--s6);
  background: linear-gradient(90deg, var(--graphite) 0 60%, transparent 60% 100%);
  background-size: 10px 1px;
  background-repeat: repeat-x;
  background-position: 0 50%;
}

.claim-packet {
  position: absolute;
  top: 50%;
  left: 0;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, var(--leaf-hot), var(--leaf) 55%, var(--leaf-ink));
  box-shadow: 0 0 0 4px var(--leaf-14);
  will-change: transform;
}

/* ── §2 the current — the macro conduit ────────────────────────────────── */

.sec-current .sec-pin { justify-content: center; padding-inline: 0; }

.macro {
  position: absolute;
  inset: 0;
  perspective: var(--macro-depth, 500px);
  perspective-origin: 50% 50%;
  overflow: hidden;
}

/* Two conduit walls that separate until one connection fills the screen. */
.macro-wall {
  position: absolute;
  left: -4%;
  right: -4%;
  height: 42vh;
  /* Flat, not a gradient: a near-white gradient on a promoted layer dithers
     by a level between rasterizations, which reads as scroll asymmetry when
     it is nothing of the kind. */
  background: repeating-linear-gradient(90deg, var(--graphite) 0 2px, transparent 2px 34px);
  opacity: 0.55;
  will-change: transform;
}

.macro-wall-a { top: 4vh; transform-origin: 50% 100%; }
.macro-wall-b { bottom: 4vh; transform-origin: 50% 0; }

.macro-pulse {
  position: absolute;
  top: 50%;
  left: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, var(--leaf-hot), var(--leaf) 52%, rgba(31, 191, 102, 0));
  will-change: transform, opacity;
}

.sec-current .sec-copy {
  position: relative;
  padding: 0 var(--s5);
  max-width: 1560px;
  margin: 0 auto;
  width: 100%;
  will-change: transform, opacity;
}

/* ── §3 the nine ───────────────────────────────────────────────────────── */

.sec-nine .sec-pin { gap: var(--s5); }

.lanes { list-style: none; display: flex; flex-direction: column; gap: 2px; }

.lane {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: 6px 0;
  will-change: transform, opacity;
}

/* The leader line draws out from the spine as the lane resolves. */
.lane-wire {
  flex: none;
  width: clamp(40px, 12vw, 190px);
  height: 1px;
  background: var(--graphite);
  transform: scaleX(var(--split, 0));
  transform-origin: left;
}

.lane-label {
  display: grid;
  /* AUTOMATION is the longest name and sets this column: at 9.5rem it ran
     straight into its own line, which is exactly what the Stage 5 type
     check measures. */
  grid-template-columns: 2.6rem minmax(0, 13rem) minmax(0, 1fr);
  gap: var(--s3);
  align-items: baseline;
  flex: 1 1 auto;
  min-width: 0;
  border-bottom: 1px solid transparent;
  padding-bottom: 3px;
}

.lane-label:hover { border-bottom-color: var(--graphite); }

.lane-bay { color: var(--leaf-ink); }

.lane-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(15px, 1.5vw, 23px);
  white-space: nowrap;
  letter-spacing: var(--display-tracking);
}

.lane-line { color: var(--ink-60); font-size: clamp(13px, 1.05vw, 16px); }

/* ── the service pages' step controls ──────────────────────────────────────
   All that survives of the removed §04 sweep: `src/page.js` uses this button
   for the prev/next step controls on each of the nine service pages. */

.sweep-arrow {
  font-family: var(--font-mono);
  font-size: 15px;
  background: none;
  border: var(--hairline);
  color: var(--ink);
  width: 44px;
  height: 44px;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.sweep-arrow:hover { border-color: var(--leaf); color: var(--leaf-ink); }

/* ── §5 how it gets built ──────────────────────────────────────────────── */

.sec-process .sec-pin { gap: var(--s6); }

.spine { position: relative; list-style: none; padding-left: var(--s5); }

.spine-rail {
  position: absolute;
  left: 0;
  top: 12px;
  bottom: 12px;
  width: 2px;
  background: var(--graphite);
}

.spine-fill {
  position: absolute;
  inset: 0;
  background: var(--leaf);
  transform: scaleY(0);
  transform-origin: top;
  will-change: transform;
}

.spine-step {
  position: relative;
  display: grid;
  grid-template-columns: 3rem minmax(0, 16rem) minmax(0, 1fr);
  gap: var(--s3) var(--s4);
  align-items: baseline;
  padding: var(--s3) 0;
  border-bottom: var(--hairline);
  will-change: transform, opacity;
}

.spine-step::before {
  content: '';
  position: absolute;
  left: calc(var(--s5) * -1 - 3px);
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--page);
  border: 1.5px solid var(--graphite);
  transition: background 260ms var(--ease-out), border-color 260ms var(--ease-out);
}

.spine-step.is-on::before { background: var(--leaf); border-color: var(--leaf); }

.spine-num { font-family: var(--font-mono); font-size: var(--tech-size); color: var(--leaf-ink); }

.spine-title {
  font-family: var(--font-mono);
  font-size: clamp(13px, 1.1vw, 16px);
  letter-spacing: 0.06em;
}

.spine-desc { color: var(--ink-60); }

/* ── §6 ownership ──────────────────────────────────────────────────────── */

.sec-own .sec-pin { gap: var(--s6); }

.own-head { max-width: 14ch; }

.own-lines { list-style: none; }

.own-line {
  border-top: var(--hairline);
  padding: var(--s3) 0;
  letter-spacing: 0.06em;
  color: var(--ink);
  will-change: transform, opacity;
}

.own-line:last-child { border-bottom: var(--hairline); }

/* ── §7 proof ──────────────────────────────────────────────────────────── */

.figures {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
  margin-top: var(--s5);
}

.figure {
  border-top: 2px solid var(--ink);
  padding-top: var(--s3);
  will-change: transform, opacity;
}

.figure-value {
  display: block;
  font-family: var(--font-display);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  font-size: clamp(40px, 7vw, 122px);
  letter-spacing: var(--display-tracking);
  line-height: 0.92;
}

.figure-label {
  display: block;
  margin-top: var(--s3);
  color: var(--ink-60);
  font-size: clamp(14px, 1.1vw, 17px);
  max-width: 20ch;
}

/* ── §8 build your stack ───────────────────────────────────────────────── */

.sec-stack .sec-pin { gap: var(--s5); }

.stack-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: var(--s6);
  align-items: start;
  will-change: transform, opacity;
}

.stack-chips {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--s2);
}

.stack-chip {
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr) 1.2rem;
  gap: var(--s2);
  align-items: center;
  width: 100%;
  min-height: 52px;
  padding: var(--s3);
  background: none;
  border: 1px solid var(--graphite);
  border-radius: 10px;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
  transition: border-color 200ms var(--ease-out), background 200ms var(--ease-out);
}

.stack-chip:hover { border-color: var(--ink-60); }

.stack-chip-bay { color: var(--ink-60); }

.stack-chip-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: var(--display-tracking);
  /* AUTOMATION has no break opportunity, so on a narrow chip it ran under
     the +/− mark instead of wrapping. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stack-chip-mark { color: var(--ink-60); text-align: right; }

.stack-chip.is-on {
  border-color: var(--leaf);
  background: var(--leaf-08);
}

.stack-chip.is-on .stack-chip-bay,
.stack-chip.is-on .stack-chip-mark { color: var(--leaf-ink); }

.stack-side { display: flex; flex-direction: column; gap: var(--s4); }

/* The combined graph: one node per chosen service on a single spine. */
.stack-graph {
  position: relative;
  min-height: 148px;
  border: var(--hairline);
  border-radius: 12px;
  padding: var(--s4) var(--s4) var(--s4) calc(var(--s4) + 18px);
  display: flex;
  align-items: center;
}

.stack-spine {
  position: absolute;
  left: var(--s4);
  top: var(--s4);
  bottom: var(--s4);
  width: 2px;
  background: var(--graphite);
}

.stack-graph.is-live .stack-spine { background: var(--leaf); }

.stack-nodes { list-style: none; display: flex; flex-direction: column; gap: 6px; width: 100%; }

.stack-node {
  position: relative;
  display: grid;
  grid-template-columns: 2.2rem 1fr;
  gap: var(--s2);
  align-items: baseline;
  animation: stack-in 320ms var(--ease-out) backwards;
  animation-delay: calc(var(--i) * 40ms);
}

.stack-node::before {
  content: '';
  position: absolute;
  left: calc(var(--s4) * -1 + 1px);
  top: 0.55em;
  width: calc(var(--s4) - 4px);
  border-top: 1px dashed var(--leaf-30);
}

@keyframes stack-in {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: none; }
}

.stack-node-bay { font-family: var(--font-mono); font-size: 12px; color: var(--leaf-ink); }

.stack-node-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: var(--display-tracking);
}

.stack-empty { color: var(--ink-60); font-size: 15px; }

.stack-readout { display: flex; flex-direction: column; }

.stack-readout > div {
  display: grid;
  grid-template-columns: 11.5rem minmax(0, 1fr);
  gap: var(--s3);
  border-top: var(--hairline);
  padding: var(--s2) 0;
}

.stack-readout > div:last-child { border-bottom: var(--hairline); }

.stack-readout dt { color: var(--ink-60); letter-spacing: 0.08em; }
.stack-readout dd { color: var(--ink); letter-spacing: 0.04em; }

.stack-price { color: var(--ink-60); font-size: 14px; max-width: 46ch; }

.stack-cta { align-self: flex-start; }

/* ── §9 end card ───────────────────────────────────────────────────────── */

.sec-end .sec-pin { align-items: center; text-align: center; justify-content: center; }

.end-bolt { color: var(--leaf); will-change: transform, opacity; }
.end-bolt svg { width: 34px; height: 50px; display: block; }

.end-head { max-width: 16ch; will-change: transform, opacity; }

.end-cta { will-change: transform, opacity; }

/* ── breakpoints ───────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
  .sweep-stage { grid-template-columns: 1fr; gap: var(--s4); align-content: start; }
  .stack-grid { grid-template-columns: 1fr; }
  .figures { grid-template-columns: 1fr; gap: var(--s4); }
  .spine-step { grid-template-columns: 2.6rem 1fr; }
  .spine-desc { grid-column: 2; }
}

@media (max-width: 720px) {
  .sec-pin { padding: var(--s6) var(--s3); }
  .sec-current .sec-copy { padding: 0 var(--s3); }
  .lane { gap: var(--s2); }
  .lane-wire { width: 18px; }
  .lane-label { grid-template-columns: 2.2rem 1fr; }
  .lane-line { grid-column: 2; }
  .stack-chips { grid-template-columns: 1fr; }
  .stack-readout > div { grid-template-columns: 1fr; gap: 2px; }
}

/* ── reduced motion ────────────────────────────────────────────────────── */
/* The director still runs — it is what composes each section — but nothing
   translates, so the page reads as a plain stack of legible sections. */

@media (prefers-reduced-motion: reduce) {
  .macro-pulse { display: none; }
  .stack-node { animation: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   THE PHONE-SHAPED SEQUENCE — used twice: the hero (§0) and §02.

   A PATTERN, NOT A DEVICE. There was a handset here: a bezel shell, a pill
   cut-out, a fake 9:41 status bar with signal bars. All of it is gone at
   the owner's direction. What remains is the shape — phone proportions,
   the site's own hairline and radius — so it reads as the site's own
   panel rather than a picture of somebody's product.

   No video file either: nothing to download or decode, sharp at any
   density.
   ───────────────────────────────────────────────────────────────────────── */

.phone-pin {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: var(--s6);
  align-items: center;
}

.phone-legend { list-style: none; display: flex; flex-direction: column; margin-top: var(--s3); }

.phone-legend li {
  display: grid;
  grid-template-columns: 2.4rem 1fr;
  gap: var(--s3);
  align-items: baseline;
  border-top: var(--hairline);
  padding: var(--s3) 0;
  color: var(--ink-60);
  max-width: 34ch;
}

.phone-legend li:last-child { border-bottom: var(--hairline); }
.phone-legend-n { color: var(--leaf-ink); }

.phone-stage {
  display: grid;
  place-items: center;
  will-change: transform, opacity;
  transform-style: preserve-3d;
}

/* Sized by whichever runs out first: the width it is given, or --phone-cap,
   the width implied by the height its frame has left. Nothing pins §02 any
   more, so the cap is no longer about clipping — it is about a panel taller
   than the window, which cannot be seen in one piece however tall the
   section is willing to grow. At 19.5:9 a panel is 1.844× as tall as it is
   wide, so one that must fit H of height cannot exceed H / 1.844.
   The cap is a VARIABLE, not a second width rule: the breakpoints below set
   their own widths, and a `.sec-phone .phone` selector would outrank them.
   Its default is the var() FALLBACK rather than a declaration on `.phone` —
   a custom property set on the element itself beats the one it would
   inherit, so declaring it here would silently ignore every context below. */
.phone { width: min(300px, 78%, var(--phone-cap, 100vw)); }

/* 210px is the section's own padding above and below the panel in the
   two-column layout, where the panel sits beside the copy rather than
   under it. */
.sec-phone { --phone-cap: max(150px, calc((100svh - 210px) / 1.844)); }

/* The panel itself. Phone proportions and a hairline — the same border the
   rest of the page uses — with one soft shadow to lift it off the white.
   No bezel, no notch, no device gloss. */
.phone-screen {
  position: relative;
  aspect-ratio: 9 / 16.6;
  border-radius: 26px;
  overflow: hidden;
  background: #fff;
  border: 1px solid #E4E7E5;
  box-shadow: 0 22px 54px rgba(18, 24, 21, 0.10);
  display: flex;
  flex-direction: column;
  padding: 16px 13px 12px;
}

/* The cut between services: a green wipe crossing the screen. */
.phone-screen::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(100deg, var(--leaf) 40%, var(--leaf-hot));
  opacity: calc(1 - (2 * abs(var(--cut, 0) - 0.5)));
  transform: translate3d(calc((var(--cut, 0) * 210% ) - 105%), 0, 0);
}

.phone-head {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 0 4px 10px;
  border-bottom: 1px solid #EDEFEE;
}

.phone-mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--leaf-08);
  color: var(--leaf);
}

.phone-mark svg { width: 10px; height: 15px; }

.phone-title { display: flex; flex-direction: column; min-width: 0; }
.phone-bay { font-size: 9px; letter-spacing: 0.1em; color: var(--leaf-ink); }

.phone-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: var(--display-tracking);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.phone-live {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: 0.12em;
  color: var(--leaf-ink);
}

.phone-live i { width: 5px; height: 5px; border-radius: 50%; background: var(--leaf); display: block; }

/* FILLS THE PANEL. The rows share the height left between the header and the
   foot — `flex: 1 1 0` on each — so six or seven cards reach both edges with
   no dead band, whatever the flow's length. Centring a fixed four left a
   third of a 19.5:9 panel empty top and bottom. */
.phone-rows {
  list-style: none;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 2px;
  min-height: 0;
}

.phone-row {
  flex: 1 1 0;
  min-height: 38px;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 12px;
  gap: 8px;
  align-items: center;
  padding: 6px 8px;
  border-radius: 10px;
  background: #FAFBFA;
  border: 1px solid #EDEFEE;
  will-change: transform, opacity;
}

.phone-row-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #EFF2F0;
  color: #9AA19D;
  transition: background 300ms var(--ease-out), color 300ms var(--ease-out);
}

.phone-row-icon svg { width: 13px; height: 13px; }

.phone-row-text { display: flex; flex-direction: column; min-width: 0; }

.phone-row-title {
  font-weight: 700;
  font-size: 11px;
  line-height: 1.2;
  color: var(--ink);
}

.phone-row-sub {
  font-size: 9.5px;
  line-height: 1.3;
  color: var(--ink-60);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-row-tick { font-size: 11px; color: transparent; transition: color 260ms var(--ease-out); }

.phone-row.is-done { border-color: #D8EFE2; }
.phone-row.is-done .phone-row-tick { color: var(--leaf); }
.phone-row.is-done .phone-row-icon {
  background: radial-gradient(circle at 34% 28%, var(--leaf-hot), var(--leaf));
  color: #fff;
}

.phone-foot { display: flex; align-items: center; gap: 8px; padding: 8px 4px 0; }

.phone-progress {
  flex: 1 1 auto;
  height: 3px;
  border-radius: 2px;
  background: #EDEFEE;
  overflow: hidden;
}

.phone-progress span {
  display: block;
  height: 100%;
  background: var(--leaf);
  transform-origin: left;
  will-change: transform;
}

.phone-count { font-size: 9px; color: var(--ink-60); letter-spacing: 0.08em; }

/* ── the cover: what that service actually is ──────────────────────────────
   When the run finishes, this rises and fills the panel edge to edge with
   the service's own written explanation, holds long enough to read, then
   the wipe takes it to the next service. It is the point of the whole
   sequence: the rows show the work happening, the cover says what it was.
   Driven by --up (0 down, 1 covering), written once per frame from JS. */

.phone-cover {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  padding: 24px 20px;
  background: var(--ink);
  color: #fff;
  opacity: var(--up, 0);
  transform: translate3d(0, calc((1 - var(--up, 0)) * 26%), 0);
  will-change: transform, opacity;
  pointer-events: none;
}

.phone-cover-bay {
  font-size: 9px;
  letter-spacing: 0.12em;
  color: var(--leaf);
}

.phone-cover-head {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 19px;
  line-height: 1.12;
  letter-spacing: var(--display-tracking);
  text-wrap: balance;
}

.phone-cover-line {
  font-size: 11.5px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}

.phone-cover-tag {
  margin-top: 2px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  font-size: 8.5px;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.62);
}

.phone-cover-tag:empty { display: none; }

/* ─────────────────────────────────────────────────────────────────────────
   §03 — the nine services, as a CARD RAIL.

   Was a 3×3 grid of white cards that arrived all at once — nine near
   identical rectangles asking to be read in one glance, which is how a
   visitor reads none of them. It is now a horizontal rail: the copy and its
   two arrows hold the left, the cards run off the right edge, and the
   visitor moves through them a card at a time.

   The scrolling is NATIVE — scroll-snap plus `scrollBy` from the arrows.
   Nothing writes scrollLeft per frame, so a trackpad swipe, shift-wheel,
   drag and the arrow keys all work without a line of code, and the rail can
   never desync from what the visitor actually did.
   ───────────────────────────────────────────────────────────────────────── */

/* `overflow-x: clip` makes the rail's bleed SELF-LIMITING. The bleed below
   is a fixed −40px, but the room to bleed into is the page and section
   padding together, and that shrinks to 16+16 on a phone — so the rail hung
   8px off the side of the viewport and gave the whole page a horizontal
   scrollbar. Clip (not hidden, not auto) trims it at the section edge
   without creating a scroll container, so the bleed shows where there is
   room for it and simply stops where there is not. */
.sec-cards { overflow-x: clip; }

/* The rail runs OUT to the right edge of the screen, so the next card is
   always part-visible and the rail reads as continuing. */
.cards-pin {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: var(--s6);
  align-items: center;
}

.cards-copy { max-width: 30ch; }

/* ── the controls ─────────────────────────────────────────────────────── */

.rail-nav {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-top: var(--s4);
}

.rail-arrow {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 0;
  background: var(--leaf);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 200ms var(--ease-out), color 200ms var(--ease-out),
              transform 200ms var(--ease-out);
}

.rail-arrow:hover:not(:disabled) { transform: scale(1.06); }

/* At either end the arrow goes inert and SAYS SO — it is the only feedback
   the control gives about where you are in the nine. */
.rail-arrow:disabled {
  background: #EDEFEE;
  color: #A6ACA8;
  cursor: default;
}

.rail-count { color: var(--ink-60); margin-left: var(--s2); }

/* ── the rail ─────────────────────────────────────────────────────────── */

.cards {
  list-style: none;
  display: flex;
  gap: var(--s3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Bleed past the pin toward the viewport edge, then pad the far side back
     so the last card can still snap flush. */
  margin-right: calc(var(--s5) * -1);
  padding: var(--s2) var(--s5) var(--s4) 0;
  scrollbar-width: none;
}

.cards::-webkit-scrollbar { display: none; }

.card {
  flex: 0 0 auto;
  width: clamp(230px, 20vw, 272px);
  scroll-snap-align: start;
  will-change: transform, opacity;
}

.card-hit {
  display: flex;
  flex-direction: column;
  gap: 7px;
  height: 100%;
  min-height: 384px;
  padding: var(--s4);
  border-radius: 22px;
  text-decoration: none;
  /* Deep, then bright, alternating down the rail: two neighbours never merge
     into one block, and the rail reads as nine things rather than a stripe. */
  background: var(--ink);
  color: #fff;
  transition: transform 240ms var(--ease-out);
}

.card:nth-child(even) .card-hit { background: var(--leaf); color: var(--ink); }

.card-hit:hover { transform: translateY(-4px); }

.card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--s3);
}

.card-bay { color: inherit; opacity: 0.5; }

.card-icon {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--leaf);
  color: var(--ink);
}

.card:nth-child(even) .card-icon { background: var(--ink); color: var(--leaf); }
.card-icon svg { width: 28px; height: 28px; }

.card-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(19px, 1.7vw, 25px);
  letter-spacing: var(--display-tracking);
}

.card-line {
  font-size: 14.5px;
  line-height: 1.35;
  opacity: 0.78;
  text-wrap: balance;
}

.card-steps {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.card:nth-child(even) .card-steps { border-top-color: rgba(11, 13, 16, 0.16); }

.card-step {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  opacity: 0.72;
}

.card-step i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--leaf);
  flex: none;
}

.card:nth-child(even) .card-step i { background: var(--ink); }

/* The pill sits at the foot of the card, inverted out of it. */
.card-go {
  margin-top: auto;
  align-self: flex-start;
  padding: 11px var(--s3);
  border-radius: 999px;
  background: var(--leaf);
  color: var(--ink);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  transition: background 200ms var(--ease-out), color 200ms var(--ease-out);
}

.card:nth-child(even) .card-go { background: var(--ink); color: var(--leaf); }
.card-hit:hover .card-go { background: #fff; color: var(--ink); }


/* ── breakpoints ───────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
  .phone-pin { grid-template-columns: 1fr; gap: var(--s5); }
  /* Stacked, the panel sits under the copy rather than beside it, so it is
     no longer sharing a window's height with anything — it can take the
     width it is given and no cap applies. */
  .sec-phone { --phone-cap: 100vw; }
  .phone { width: min(260px, 62%, var(--phone-cap, 100vw)); }
  /* The rail stacks under its copy rather than beside it. It stays a rail —
     that is the point of it on a narrow screen. */
  .cards-pin { grid-template-columns: 1fr; gap: var(--s5); }
  .cards-copy { max-width: none; }
}

@media (max-width: 720px) {
  .phone { width: min(240px, 72%, var(--phone-cap, 100vw)); }
  .card { width: clamp(216px, 68vw, 260px); }
}
