/* ============================================================================
   Westslope Labs — marketing site
   Built on the scrollcraft engine (scrollcraft.js / scrollcraft.css, both
   unedited — theme and compose here, never restyle [data-sc-*] or .sc-stage).

   Grammar: filmic one-shot. A single continuous column, no seams, each beat
   handing off to the next. Fixed minimal bar, corner-anchored kinetic hero,
   pinned close with a spotlight and a magnetic CTA. Aesthetic: brutalist —
   blunt structure and real contrast carried over from the first pass, not
   softened just because the grammar changed.
   ========================================================================== */

:root {
  /* --- the six required tokens, off the Westslope brand guide ------------ */
  --sc-canvas:     #090E0B;   /* Old Growth */
  --sc-surface:    #1A2612;   /* Riverbed */
  --sc-ink:        #F5F7F7;   /* Mist */
  --sc-ink-soft:   #9CA68F;   /* sage-tinted, 7.7:1 on canvas, 6.2:1 on surface */
  --sc-accent:     #AD4F25;   /* Slash Deep: the engine paints ::selection,
                                 caret and focus ring from this token, and
                                 mist on the solid Slash (#C05A30) is only
                                 4.11:1. Deep is 4.98:1 (design gate). */
  --sc-accent-ink: #F5F7F7;

  --sc-font-display: "Bebas Neue", "Archivo", system-ui, sans-serif;
  --sc-font-text:    "Manrope", system-ui, sans-serif;
  --sc-font-mono:    "JetBrains Mono", ui-monospace, monospace;

  /* --- accent ramp (verified, see BRIEF.md). One hue, three jobs. -------- */
  --wl-accent-deep:  #AD4F25; /* Slash Deep. Paired with mist text: 4.98:1 */
  --wl-accent-light: #E2895C; /* small accent text ON dark grounds: 7.4:1 */

  /* --- old-site pastiche palette. Appears once, whole, at the close. ----- */
  --wl-old-bg:     #EDEDE6;
  --wl-old-ink:    #1B1B18;
  --wl-old-link:   #163E9E;
  --wl-old-red:    #B3161A;
  --wl-old-font:   "Times New Roman", Times, serif;
}

/* ---------------------------------------------------------------- reset -- */
h1, h2, h3, p, ul, figure { margin: 0; padding: 0; }
ul { list-style: none; }
a { text-decoration: none; }
body { background: var(--sc-canvas); }
/* Bebas Neue ships one weight (400); the engine's .sc-display asks for 500,
   which the browser would synthesize. Declare the real one. (The site's
   copy of scrollcraft.css carries the same 400 so the static design gate,
   which reads rules without cascading, agrees with the render.) */
.sc-display { font-weight: 400; }

/* Filmic one-shot forbids a visible progress readout: "if the visitor can
   see where they are in a sequence, it is not one shot." The engine ships
   its own [data-sc-progress] bar; it stays in the DOM (other engine code
   reads it) but never paints. */
[data-sc-progress] { display: none; }

/* ============================================================== THE BAR ==
   Fixed wordmark, two nav links, one CTA — present from the first frame.
   (The original one-page build allowed no menu at all. Superseded once the
   site became three pages: Cory, 2026-09-03, "we can have menu items here."
   Two links do not earn a hamburger, so the nav never collapses behind a
   toggle — it shrinks. See PAGE-MAP.md §0.) */
.bar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sc-4) var(--sc-gutter);
  background: color-mix(in oklab, var(--sc-canvas) 78%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--sc-hairline);
}
/* The mark is the home link. Once the wordmark is hidden under 640px it is
   just the 24px fish glyph — measured at 20x23, well under the 44px floor —
   so it carries the same invisible expanded target as the nav links and the
   CTA. Measured in the pane at 375px, not eyeballed. */
.bar__mark { display: flex; align-items: center; gap: var(--sc-3); position: relative; }
.bar__mark::after { content: ""; position: absolute; inset: -14px -16px; }
.bar__mark img { width: 24px; height: auto; }
.bar__mark span {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink);
}
.bar__cta {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
  border-bottom: 1px solid color-mix(in oklab, var(--wl-accent-light) 55%, transparent);
  padding-bottom: 2px;
  position: relative;
}
.bar__cta::after { content: ""; position: absolute; inset: -14px -8px; } /* tap target, invisible */

/* Nav sits between mark and CTA. Mono caps, same size as the rest of the
   bar so nothing in it competes; the current page is the only one that
   reads as ink rather than soft. */
.bar__nav { display: flex; align-items: center; gap: var(--sc-5); }
.bar__link {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);          /* 7.7:1 on canvas */
  position: relative;
  padding-block: 2px;
}
.bar__link::after { content: ""; position: absolute; inset: -14px -8px; } /* 44px tap target */
.bar__link[aria-current="page"] {
  color: var(--sc-ink);
  box-shadow: 0 1px 0 0 var(--wl-accent-light);
}
/* Hover styling only where a real pointer exists — on touch, :hover sticks
   after a tap and the link stays lit (CLAUDE.md mobile pass). */
@media (hover: hover) {
  .bar__cta:hover { color: var(--sc-ink); border-color: var(--sc-ink); }
  .bar__link:hover { color: var(--sc-ink); }
}

/* The bar carries five things now (mark image, wordmark, two links, CTA).
   At narrow widths the wordmark goes first — the fish mark alone still
   identifies the site and links home — then the nav tightens. Nothing is
   ever hidden behind a toggle. Verified at 375px. */
@media (max-width: 640px) {
  .bar { gap: var(--sc-3); padding-block: var(--sc-3); }
  .bar__nav { gap: var(--sc-4); }
  .bar__mark span { display: none; }
  .bar__link, .bar__cta { font-size: 11px; letter-spacing: 0.06em; }

  /* Tap targets, measured in the pane at 375px rather than assumed.
     The ::after expansion goes vertical-only here: expanding it sideways
     made the mark, the nav links and the CTA overlap each other, and a
     target that steals its neighbour taps is worse than a small one. Width
     comes from real layout instead — padding the controls, so the bar's
     own flex spacing keeps them apart — and the mark, which is only a 24px
     glyph once the wordmark is hidden, gets a 44px floor of its own. */
  .bar__mark::after,
  .bar__link::after,
  .bar__cta::after { inset: -14px 0; }
  .bar__mark { min-width: 44px; min-height: 44px; justify-content: center; }
  .bar__link, .bar__cta { padding-inline: 4px; }
}

/* ============================================================ THE FILM ===
   Every beat is full-width, single column. Nothing splits. */
.beat { padding: var(--sc-8) var(--sc-gutter); }
.beat__inner { max-width: var(--sc-maxw); margin-inline: auto; }
/* A flow section directly after a pinned act takes reduced top padding: the
   stage above already needs a full viewport to scroll off (devices.md §8). */
.beat--after-pin { padding-block: var(--sc-6) var(--sc-8); }

/* ------------------------------------------------------ pinned stages --
   The three story beats (hero, tension, range) are pinned acts. The engine
   finds [data-sc-stage], adds .sc-stage (position: sticky, 100svh, overflow
   clip) and sets the act's height from data-sc-span. NOTHING here may set
   `position` on a stage — that exact trap already broke the close once
   (see #close below). Padding lives on an inner wrapper, never on the act
   element: a padded act shrinks the sticky travel and offsets the pin.
   padding-block / padding-inline, never the shorthand (CLAUDE.md). */
.hero-stage, .tension-stage, .substance-stage, .range-stage {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.hero-stage { justify-content: flex-end; }
.stage__inner {
  width: 100%;
  max-width: var(--sc-maxw);
  margin-inline: auto;
  padding-block: calc(var(--sc-7) + 4.5rem) var(--sc-8); /* top clears the fixed bar */
  padding-inline: var(--sc-gutter);
}

/* ------------------------------------------------------------- beat one --
   Hero. Corner-anchored, kinetic. No scrub footage exists for Westslope
   itself, so the ground is the brand canvas rather than full-bleed video —
   an honest substitution, not a claim of footage that doesn't exist. */
.hero__mark {
  position: absolute;
  right: clamp(-4rem, -2vw, 1rem);
  bottom: clamp(-2rem, -4vh, 2rem);
  width: clamp(16rem, 34vw, 26rem);
  height: auto;
  opacity: 0.07;
  pointer-events: none;
}
.hero__headline {
  font-family: var(--sc-font-display);
  font-size: clamp(2.4rem, 1.6rem + 4.4vw, 5.4rem);
  line-height: 0.98;
  letter-spacing: var(--sc-track-tight);
  max-width: 18ch;
  text-wrap: balance;
}
.hero__headline-line--new .sc-split--line { color: var(--wl-accent-light); }
/* The objection: the customer's own excuse, in the old-site voice (Times,
   italic), sized as the subject of the first frame rather than a caption to
   it. A strike draws across from p 0.14 to 0.30 as headline line one arrives,
   and the quote falls back to a ghost so the answer owns the frame. */
.hero__objection {
  font-family: var(--wl-old-font);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.9rem, 1.1rem + 2.6vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--sc-ink);
  max-width: 22ch;
  text-wrap: balance;
  margin-bottom: var(--sc-6);
  --strike: clamp(0, calc((var(--sc-p, 0) - 0.14) / 0.16), 1);
  opacity: calc(1 - var(--strike) * 0.72) !important; /* beats the engine's inline 1 once struck */
}
.hero__objection-text {
  position: relative;
  background-image: linear-gradient(var(--wl-accent-light), var(--wl-accent-light));
  background-repeat: no-repeat;
  background-size: calc(var(--strike) * 100%) 3px;
  background-position: 0 56%;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
@media (prefers-reduced-motion: reduce) {
  .hero__objection { opacity: 0.28 !important; }
  .hero__objection-text { background-size: 100% 3px; }
}
html:not(.js) .hero__objection-text { background-size: 100% 3px; }
/* The hero inner is the only stage whose reserved (not-yet-visible) headline
   plus a display-scale objection can outgrow a short desktop viewport. */
.hero-stage .stage__inner { padding-block: calc(var(--sc-7) + 4.5rem) var(--sc-7); }
@media (max-height: 760px) and (min-width: 900px) {
  .hero__objection { font-size: clamp(1.9rem, 1rem + 2.2vw, 2.8rem); margin-bottom: var(--sc-5); }
  .hero__sub { margin-top: var(--sc-5); }
}

/* scroll cue: centred at the foot of the hero stage, gone by p 0.11 */
.hero__scroll {
  position: absolute;          /* the stage itself is the engine's sticky box */
  left: 0; right: 0;           /* margin-centred: the engine owns cued elements' transform */
  bottom: max(1.5rem, env(safe-area-inset-bottom));
  width: max-content;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sc-2);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
  line-height: 1;
}
.hero__scroll-arrow {
  display: inline-block;
  font-size: 1.1rem;
  animation: wl-bounce 1.6s ease-in-out infinite;
}
@keyframes wl-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce) { .hero__scroll-arrow { animation: none; } }
html:not(.js) .hero__scroll { display: none; }
.hero__sub {
  margin-top: var(--sc-6);
  color: var(--sc-ink-soft);
  font-size: var(--sc-t-base);
  max-width: 44ch;
}

/* old-site pastiche chrome — reused only inside the close now */
.old-chrome__nav {
  font-family: var(--wl-old-font);
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  color: var(--wl-old-link);
  display: flex;
  gap: var(--sc-3);
  margin-bottom: var(--sc-5);
  flex-wrap: wrap;
}
.old-chrome__nav span::after { content: "|"; margin-left: var(--sc-3); color: var(--wl-old-ink); opacity: .4; }
.old-chrome__nav span:last-child::after { content: none; }
.old-chrome__badge {
  display: inline-block;
  margin-top: var(--sc-5);
  padding: var(--sc-2) var(--sc-3);
  background: var(--wl-old-red);
  color: #fff;
  font-family: var(--wl-old-font);
  font-weight: 700;
  font-size: 0.72rem;
  transform: rotate(-2deg);
}

.new-chrome__mark { width: 34px; height: auto; margin-bottom: var(--sc-4); }
.new-chrome__tag {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
  margin-bottom: var(--sc-3);
  display: block;
}

/* ------------------------------------------------------------- beat two --
   Tension. Two published figures, one at a time, each blooming from 0 under
   scroll (data-sc-count keyed to the act). The number is the image.       */
.stat__heading { font-size: var(--sc-t-3xl); margin-bottom: var(--sc-6); color: var(--sc-ink); }
/* Three stats stack as rows (numeral left, line right) and each one holds
   once it lands, so the whole column is on screen by the end of the act. */
.stats { display: flex; flex-direction: column; gap: var(--sc-4); width: 100%; }
.stat {
  display: grid;
  grid-template-columns: minmax(7ch, auto) 1fr;
  column-gap: var(--sc-6);
  align-items: baseline;
  border-top: 1px solid var(--sc-hairline);
  padding-top: var(--sc-4);
}
.stat:first-child { border-top: none; padding-top: 0; }
.stat__num {
  font-family: var(--sc-font-display);
  font-size: clamp(3.5rem, 1.5rem + 6.5vw, 8rem);
  line-height: 0.9;
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  font-variant-numeric: tabular-nums;
  grid-row: 1 / span 2;
}
.stat__unit { color: var(--wl-accent-light); font-size: 0.55em; margin-left: 0.06em; }
.stat__line { color: var(--sc-ink); font-family: var(--sc-font-display); font-size: var(--sc-t-xl); line-height: 1.1; text-wrap: pretty; }
.stat__src {
  margin-top: var(--sc-2);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}

/* ----------------------------------------------------------- beat three --
   Substance. Pinned: the heading assembles, then the four steps arrive in
   order. Flat, structural, plain-labelled. No icon tiles.                  */
.method__heading { font-size: var(--sc-t-2xl); max-width: 14ch; margin-bottom: var(--sc-6); }
.method { display: flex; flex-direction: column; gap: var(--sc-5); max-width: 40rem; }
.method__item { border-top: 1px solid var(--sc-hairline); padding-top: var(--sc-4); }
.method__item:first-child { border-top: none; padding-top: 0; }
.method__label {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  /* This beat sits entirely on the canvas now (no split-column old ground
     left to worry about), so the on-dark ramp step applies directly:
     --wl-accent-light measured ~7.4:1 on canvas. */
  color: var(--wl-accent-light);
  display: block;
  margin-bottom: var(--sc-2);
}
.method__body { color: var(--sc-ink-soft); max-width: 44ch; }

/* ------------------------------------------------------------ beat four --
   Range. A skeptical line gives way to three real capability lines.        */
.range__old {
  font-family: var(--wl-old-font);
  font-style: italic;
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.8rem);
  color: var(--sc-ink-soft);
  max-width: 22ch;
  margin-bottom: var(--sc-8);
}
.range__lead {
  display: block;
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
  margin-bottom: var(--sc-4);
}
.range { display: flex; flex-direction: column; gap: var(--sc-4); }
.range__line {
  font-family: var(--sc-font-display);
  font-size: clamp(1.5rem, 1rem + 2vw, 2.8rem);
  letter-spacing: var(--sc-track-snug);
  line-height: 1.05;
  color: var(--sc-ink);
  max-width: 22ch;
}
.range__note { color: var(--sc-ink-soft); max-width: 42ch; margin-top: var(--sc-6); }
/* Short desktop windows (a laptop with the bookmarks bar, a split screen):
   the pinned stage is 100svh and clips, so the stack has to fit in ~700px.
   The skeptic line fades out by p 0.35 but still holds its space, so its
   margin is the first thing to shrink. */
@media (max-height: 760px) {
  .range__old { font-size: clamp(1.1rem, 1rem + 0.6vw, 1.4rem); margin-bottom: var(--sc-5); }
  .range__line { font-size: clamp(1.3rem, 1rem + 1.4vw, 2.1rem); }
  .range { gap: var(--sc-3); }
  .range__note { margin-top: var(--sc-4); font-size: var(--sc-t-sm); }
  .method__heading { font-size: var(--sc-t-xl); margin-bottom: var(--sc-4); }
  .method { gap: var(--sc-3); }
  .method__item { padding-top: var(--sc-3); }
  .substance-stage .new-chrome__tag { display: none; }
  .substance-stage .stage__inner { padding-block: calc(var(--sc-3) + 4rem) var(--sc-5); }
  .stat__heading { font-size: var(--sc-t-2xl); margin-bottom: var(--sc-4); }
  .stats { gap: var(--sc-3); }
  .stat { padding-top: var(--sc-3); }
  .stat__num { font-size: clamp(2.8rem, 1.2rem + 4vw, 5rem); }
  .stat__line { font-size: var(--sc-t-lg); }
}

/* ------------------------------------------------------------ beat five --
   Silence. Deliberately near-empty.                                        */
.silence { min-height: 50vh; display: flex; align-items: center; justify-content: center; }
.silence span {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}

/* ================================================================ CLOSE ==
   The rebuild. One pinned act, one full-bleed stage — the peak and the
   close are the same beat. This is the first and only place the full old-
   site pastiche appears: it tears apart, outward, off the frame, while the
   real build grows to fill the stage. Every --wl-tear-*/--wl-grow-* rule is
   driven purely by the act's own --sc-p (published by the engine) via
   calc() — no extra rAF loop for the pieces themselves.                    */
#close { position: relative; }
/* No `position` declared here on purpose: the engine finds this element via
   its [data-sc-stage] attribute and adds the .sc-stage class to it, which
   is what makes it position:sticky (scrollcraft.css). A plain `position:
   relative` at equal specificity, later in the cascade, silently wins over
   that and the whole act scrolls away instead of pinning — scrollcraft.css
   warns about exactly this trap in its own comments. Sticky already is a
   positioned element, so .close-stage__old/__new's position:absolute below
   still resolves against it with nothing declared here. */
.close-stage {
  min-height: 100svh;
  overflow: clip;
  display: flex;
  align-items: center;
  padding: var(--sc-8) var(--sc-gutter);
  background: var(--sc-canvas);
}
.close-stage__old,
.close-stage__new {
  position: absolute;
  inset: 0;
  padding: var(--sc-8) var(--sc-gutter);
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* stretch is the flex default on the cross axis (here: width) — any
     child with no explicit width of its own, like the badge and the old
     nav row, was silently blown out to the full width of the stage. */
  align-items: flex-start;
}
/* The old and new panels are both full-bleed and stacked (no second column
   to hold the old panel to its own half now), so the old panel's own
   background has to fade with it — its children tearing away individually
   was not enough; the beige ground behind them just sat there for the
   whole act. Same --sc-p calc() pattern as .tear, timed to finish a beat
   after the last fragment is gone (t1 0.58) so nothing pops. */
.close-stage__old {
  background: var(--wl-old-bg);
  color: var(--wl-old-ink);
  /* The old panel paints ABOVE the new one. Both are full-bleed absolute
     overlays and the new one comes later in the DOM, so without this the
     new side's 0.08-floor copy and its hero frame showed through the beige
     ground for the whole entry. As the old panel's opacity runs to 0 the
     new side is simply what is left underneath. */
  z-index: 2;
  --panel-local: clamp(0, calc((var(--sc-p) - 0.05) / 0.55), 1);
  opacity: calc(1 - var(--panel-local));
}
@media (prefers-reduced-motion: reduce) {
  .close-stage__old { opacity: 0; }
}
.close-stage__new { background: transparent; color: var(--sc-ink); z-index: 1; }

/* the tearing fragments of the old site — fly outward off the frame, since
   there is no second column to receive them now. */
.tear {
  --t0: 0;
  --t1: 0.3;
  --local: clamp(0, calc((var(--sc-p) - var(--t0)) / max(var(--t1) - var(--t0), 0.001)), 1);
  opacity: calc(1 - var(--local));
  transform:
    translate3d(calc(var(--local) * var(--tear-x, -60px)), calc(var(--local) * var(--tear-y, 14px)), 0)
    rotate(calc(var(--local) * var(--tear-r, -6deg)));
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  .tear { opacity: 0; transform: none; }
}

/* the new build grows in, centred, replacing the torn-away frame.
   A pinned stage is fully visible a viewport before its own --sc-p leaves 0
   (see devices.md, "Ground or greet"), so a hard 0 here would show a blank
   stage for that whole entry. The 0.08 floor keeps a faint presence the
   whole time; the canvas colour is the rest of the ground. */
.grow {
  --t0: 0.1;
  --t1: 0.45;
  --local: clamp(0, calc((var(--sc-p) - var(--t0)) / max(var(--t1) - var(--t0), 0.001)), 1);
  opacity: calc(0.08 + var(--local) * 0.92);
  transform: translate3d(0, calc((1 - var(--local)) * 16px), 0);
}
@media (prefers-reduced-motion: reduce) {
  .grow { opacity: 1; transform: none; }
}

.old-body { font-family: var(--wl-old-font); max-width: 30ch; margin-top: var(--sc-4); color: color-mix(in oklab, var(--wl-old-ink) 80%, transparent); }

/* The 2011 hero banner. A beveled box, a photo that never loaded, a caption
   with two exclamation marks. Everything here is period-correct on purpose
   and nothing is a real business. */
.old-hero {
  width: min(100%, 34rem);
  margin-top: var(--sc-5);
  font-family: var(--wl-old-font);
}
.old-hero__img {
  position: relative;
  height: clamp(7rem, 22vh, 12rem);
  border: 2px inset #8f8f86;
  background: #d9d9d1;
  overflow: hidden;
}
/* A 320px JPEG stretched to fill the banner: blurry and the wrong aspect,
   the way a 2011 upload looked. Browser upscaling does the blur. */
.old-hero__img img { width: 100%; height: 100%; object-fit: fill; display: block; }
.old-hero__welcome {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  font-family: var(--wl-old-font); font-weight: 700; font-size: clamp(1.1rem, 2.4vw, 1.7rem);
  color: #fff200; text-shadow: 2px 2px 0 #1b1b18, -1px -1px 0 #1b1b18; white-space: nowrap;
  letter-spacing: 0.02em;
}
.old-hero__caption { display: block; margin-top: var(--sc-2); font-size: 0.85rem; font-style: italic; color: var(--wl-old-ink); }

/* The rebuilt hero: a mockup of a fictional contractor homepage inside a
   plain frame. No URL bar, no browser dots: the frame only gives the mock an
   edge. Type inside is sized in container units so the composition holds at
   any frame width. */
/* Written with the parent so it outranks `.close-stage__new > * { position:
   relative }` below, which otherwise wins on source order and drops the
   frame into the column at the left, over the headline. */
.close-stage__new > .close__frame {
  position: absolute;
  right: var(--sc-gutter);
  bottom: clamp(4.5rem, 14vh, 8rem);
  width: clamp(18rem, 40vw, 38rem);
  container-type: inline-size;
  border: 1px solid var(--sc-hairline-strong);
  border-radius: var(--sc-r-md);
  overflow: hidden;
  box-shadow: var(--sc-e3), var(--sc-edge);
  background: #0b1116;
}
.mock { position: relative; aspect-ratio: 16 / 10; color: var(--sc-ink); overflow: hidden; background: #0b1116; }
/* The engine's own stylesheet positions the poster and the scrub clip
   absolute/inset 0/cover inside the nearest positioned ancestor, which is
   .mock, so they fill the frame and not the stage. Nothing here restyles
   [data-sc-scrub] or .sc-stage__poster (mechanism); the poster only gets
   its cover fit restated so it also paints correctly before the engine
   mounts. */
.mock__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mock__scrim, .mock__nav, .mock__copy { z-index: 2; }
.mock__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(11,17,22,0.92) 0%, rgba(11,17,22,0.55) 48%, rgba(11,17,22,0) 80%);
}
.mock__nav {
  position: absolute; inset: 0 0 auto 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 4cqw 5cqw 0;
  font-family: var(--sc-font-mono); font-size: 2.1cqw; letter-spacing: var(--sc-track-wide); text-transform: uppercase;
}
.mock__brand { color: var(--sc-ink); }
.mock__navcta { color: var(--wl-accent-light); border-bottom: 1px solid currentColor; padding-bottom: 0.15em; }
.mock__copy {
  position: absolute; left: 5cqw; right: 30cqw; bottom: 7cqw;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2.4cqw;
}
.mock__kicker { font-family: var(--sc-font-mono); font-size: 1.9cqw; letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--wl-accent-light); }
.mock__h1 { font-family: var(--sc-font-display); font-size: 8cqw; line-height: 0.98; letter-spacing: var(--sc-track-tight); max-width: 12ch; text-wrap: balance; }
.mock__cta {
  font-family: var(--sc-font-text); font-weight: 700; font-size: 2.3cqw;
  background: var(--wl-accent-deep); color: var(--sc-ink);
  padding: 1.6cqw 3.2cqw; border-radius: 3px;
}

@media (max-width: 1100px) {
  .close-stage__new > .close__frame { width: clamp(16rem, 36vw, 30rem); bottom: clamp(4rem, 10vh, 6rem); }
}

.close-stage__new .new-chrome__mark { width: 40px; }
.close__headline {
  font-size: clamp(2rem, 1.5rem + 2.6vw, 3.6rem);
  line-height: 1.0;
  margin: var(--sc-4) 0 var(--sc-6);
  max-width: 16ch;
  text-wrap: balance;
}
.close__cta {
  display: inline-block;
  width: fit-content;
  background: var(--wl-accent-deep);
  color: var(--sc-ink);
  font-family: var(--sc-font-text);
  font-weight: 700;
  font-size: var(--sc-t-base);
  padding: var(--sc-4) var(--sc-6);
  border-radius: var(--sc-r-sm);
  box-shadow: var(--sc-e2);
  transition: transform var(--sc-d-fast) var(--sc-ease-out), box-shadow var(--sc-d-fast) var(--sc-ease-out);
}
.close__cta:hover { transform: translateY(-2px); box-shadow: var(--sc-e3); }
.close__cta:active { transform: translateY(0) scale(0.98); }
@media (prefers-reduced-motion: reduce) {
  /* data-sc-magnet drifts the CTA toward the pointer every frame — real,
     continuous, pointer-driven motion, which reduced-motion guidance treats
     the same as autoplay. Freeze it at rest. */
  .close__cta { transform: none !important; }
}

/* the one rare camo moment, per Cory's "very rare, specific positions only"
   rule: a sliver low in the stage, nowhere else on the page. */
.close__camo {
  position: absolute;
  inset: auto 0 0 0;
  height: 34%;
  background-image: url("assets/camo-slash.jpg");
  background-size: cover;
  background-position: center 70%;
  opacity: 0.14;
  mask-image: linear-gradient(to top, black, transparent);
  pointer-events: none;
  z-index: 0;
}
.close-stage__new > * { position: relative; z-index: 1; }

.close__foot {
  position: absolute;
  left: var(--sc-gutter);
  right: var(--sc-gutter);
  bottom: var(--sc-5);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  color: var(--sc-ink-soft);
  z-index: 1;
}

@media (max-width: 860px) {
  .close-stage__old, .close-stage__new { padding: var(--sc-7) var(--sc-gutter); }
  .close__foot { position: static; margin-top: var(--sc-6); flex-direction: column; align-items: flex-start; gap: var(--sc-2); }
  /* On a phone the frame joins the column under the CTA, full width, and
     the screenshot is cropped to its top band so the whole close still fits
     one 667px screen. */
  .close-stage__new > .close__frame { position: relative; width: 100%; max-width: 30rem; margin-top: var(--sc-5); bottom: auto; right: auto;
    flex: 0 0 clamp(6rem, 18vh, 11rem); height: clamp(6rem, 18vh, 11rem); overflow: hidden; } /* fixed band so flex never crushes it */
  .old-hero__img { height: clamp(5rem, 16vh, 8rem); }
}

/* ---------------------------------------------------------- mobile pass -- */
@media (max-width: 860px) {
  .beat { padding: var(--sc-7) var(--sc-gutter); }
  .beat--after-pin { padding-block: var(--sc-5) var(--sc-7); }
  .stage__inner { padding-block: calc(var(--sc-6) + 4rem) var(--sc-7); }
  .stat__heading { font-size: var(--sc-t-2xl); margin-bottom: var(--sc-4); }
  .stats { gap: var(--sc-3); }
  .stat { padding-top: var(--sc-3); column-gap: var(--sc-4); }
  .stat__num { font-size: 3rem; }
  .stat__line { font-size: var(--sc-t-lg); }
  /* Four steps plus a heading in one 667px stage: tighter stack, smaller
     body, no less content. */
  .method__heading { font-size: var(--sc-t-xl); margin-bottom: var(--sc-3); }
  .method { gap: var(--sc-3); }
  .method__item { padding-top: var(--sc-2); }
  .method__body { line-height: 1.45; }             /* still 16px; only the leading tightens */
  .substance-stage .new-chrome__tag { display: none; } /* the heading carries itself here */
  .substance-stage { justify-content: flex-start; }    /* anchor under the bar, never behind it */
  .substance-stage .stage__inner { padding-block: calc(var(--sc-3) + 4rem) var(--sc-5); }
  .range__old { margin-bottom: var(--sc-6); }
  .range__note { margin-top: var(--sc-5); }
  .hero__mark { opacity: 0.05; }
}

/* No-JS safety net. scrollcraft.css hides [data-sc-in], [data-sc-stagger]
   children and [data-sc-cue] unconditionally ("pre-paint state so nothing
   flashes before the first read()") with no html.js gate of its own — fine
   once the engine mounts, but with script blocked or failed nothing ever
   adds .sc-in or writes a cue's inline opacity, and this real, indexable
   page would ship most of its copy permanently invisible. This file loads
   after scrollcraft.css, so equal-specificity rules here win by source
   order and restore the plain, visible state whenever html carries no .js
   class — the class only <head>'s own inline script can add. */
html:not(.js) [data-sc-in],
html:not(.js) [data-sc-stagger] > *,
html:not(.js) [data-sc-cue] {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------------- the offer --
   Full-bleed band under the rebuild. Riverbed surface, a single accent rule
   across the top, three display-size facts on a hairline grid, one CTA. */
.offer {
  position: relative;
  isolation: isolate;
  background: var(--sc-canvas);
  border-top: 3px solid var(--wl-accent-deep);
  color: var(--sc-ink);
  overflow: hidden;
}
/* camo ground: the pattern reads, but every text pair is measured against
   the darkest plausible spot under it, so a canvas scrim stays on top. */
.offer__camo {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to bottom, color-mix(in oklab, var(--sc-canvas) 90%, transparent), color-mix(in oklab, var(--sc-canvas) 76%, transparent)),
    url("assets/camo-slash.jpg");
  background-size: auto, cover;
  background-position: center, center 40%;
  pointer-events: none;
  z-index: -1;
}
.offer__inner { position: relative; }
.offer__big .sc-nums { font-variant-numeric: tabular-nums; }
/* secondary copy over camo: brighter than ink-soft so it clears AA on the pattern's lightest spot */
.offer .offer__note, .offer .offer__promise, .offer .site-foot { color: color-mix(in oklab, var(--sc-ink) 88%, var(--sc-canvas)); }
.offer__inner {
  max-width: var(--sc-maxw);
  margin-inline: auto;
  padding-block: var(--sc-8) var(--sc-7);
  padding-inline: var(--sc-gutter);
}
.offer__headline {
  font-size: var(--sc-t-3xl);
  line-height: 0.95;
  margin: 0 0 var(--sc-7);
  text-wrap: balance;
}
.offer__facts {
  list-style: none;
  margin: 0 0 var(--sc-6);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--sc-hairline);
  border-bottom: 1px solid var(--sc-hairline);
}
.offer__fact {
  padding-block: var(--sc-6);
  padding-inline: 0 var(--sc-6);
}
.offer__fact + .offer__fact { border-left: 1px solid var(--sc-hairline); padding-inline: var(--sc-6); }
.offer__big {
  font-family: var(--sc-font-display);
  font-size: clamp(3.5rem, 1.5rem + 6.5vw, 8rem);
  line-height: 0.9;
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  font-variant-numeric: tabular-nums;
  margin: 0 0 var(--sc-3);
}
.offer__dash { color: var(--wl-accent-light); margin-inline: 0.02em; }
.offer__unit { color: var(--wl-accent-light); font-size: 0.45em; margin-left: 0.08em; }
.offer__what {
  font-family: var(--sc-font-display);
  font-size: var(--sc-t-lg);
  line-height: 1.15;
  color: var(--sc-ink);
  margin: 0;
  text-wrap: pretty;
}
.offer__note {
  color: var(--sc-ink-soft);
  max-width: 52ch;
  margin: 0 0 var(--sc-7);
  text-wrap: pretty;
}
.offer__act { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sc-4) var(--sc-6); }
.offer__cta {
  display: inline-block;
  background: var(--wl-accent-deep);
  color: var(--sc-ink);
  font-family: var(--sc-font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.4rem);
  letter-spacing: 0.02em;
  line-height: 1;
  padding: var(--sc-4) var(--sc-7);
  border-radius: var(--sc-r-sm);
  box-shadow: var(--sc-e2);
  transition: transform var(--sc-d-fast) var(--sc-ease-out), box-shadow var(--sc-d-fast) var(--sc-ease-out);
}
.offer__cta:hover { transform: translateY(-2px); box-shadow: var(--sc-e3); }
.offer__cta:active { transform: translateY(0) scale(0.98); }
.offer__promise { margin: 0; color: var(--sc-ink-soft); max-width: 36ch; }
.site-foot {
  max-width: var(--sc-maxw);
  margin-inline: auto;
  padding-block: var(--sc-5);
  padding-inline: var(--sc-gutter);
  border-top: 1px solid var(--sc-hairline);
  display: flex;
  justify-content: space-between;
  gap: var(--sc-4);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}
@media (prefers-reduced-motion: reduce) { .offer__cta { transform: none !important; } }
@media (max-width: 860px) {
  .offer__inner { padding-block: var(--sc-7) var(--sc-6); }
  .offer__headline { margin-bottom: var(--sc-6); }
  .offer__facts { grid-template-columns: 1fr; }
  .offer__fact { padding-block: var(--sc-5); padding-inline: 0; }
  .offer__fact + .offer__fact { border-left: none; border-top: 1px solid var(--sc-hairline); padding-inline: 0; }
  .offer__big { font-size: clamp(3rem, 2rem + 6vw, 4.5rem); }
  .offer__cta { display: block; text-align: center; width: 100%; }
  .offer__act { flex-direction: column; align-items: stretch; }
  .offer__promise { max-width: none; }
  .site-foot { flex-direction: column; gap: var(--sc-2); }
}

/* ==========================================================================
   SUBPAGES — web-design.html and ai-automation.html
   Same design system as the homepage, deliberately: they are the same site,
   not two new systems. The difference is register, not palette — subpages
   run mostly as document flow with one pinned act each, because these are
   pages people READ. The homepage does the performing.

   Contrast, computed against the ground each colour actually renders on
   (--sc-canvas #090E0B unless stated):
     --sc-ink          #F5F7F7  17.4:1  body and headings
     --sc-ink-soft     #9CA68F   7.7:1  secondary copy, labels, sources
     --wl-accent-light #E2895C   7.4:1  small accent text, numerals, rules
   Nothing below paints accent-as-background under mist except the close CTA
   and the active tab, which both use --wl-accent-deep (#AD4F25, 4.98:1).

   Layout rule from CLAUDE.md: modifiers set vertical padding with
   padding-block, never the `padding` shorthand — the shorthand resets
   left/right to 0 and beats the wrapper padding-inline on source order,
   which is how nine text elements ended up flush to the screen edge once.
   ========================================================================== */

/* --------------------------------------------------------- shared open -- */
.page-open { padding-block: calc(var(--sc-8) + 4.5rem) var(--sc-7); }
.page-open__tag,
.spine__tag,
.five__tag {
  display: block;
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
  margin-bottom: var(--sc-4);
}
.page-open__objection {
  font-family: var(--wl-old-font);
  font-style: italic;
  font-size: var(--sc-t-lg);
  color: var(--sc-ink-soft);
  margin-bottom: var(--sc-4);
  max-width: 34ch;
}
.page-open__headline {
  font-size: var(--sc-t-3xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  text-wrap: balance;
  max-width: 18ch;
}
.page-open__sub {
  margin-top: var(--sc-5);
  font-size: var(--sc-t-lg);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: 48ch;
  text-wrap: pretty;
}

/* shared section headings on subpages */
.why__heading, .gauge__heading, .proof__heading,
.plain__heading, .five__heading, .verticals__heading, .limits__heading {
  font-size: var(--sc-t-2xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  text-wrap: balance;
  max-width: 20ch;
}
.why__lead, .gauge__lead, .verticals__lead, .proof__note, .plain__test,
.why__after, .limits__after {
  margin-top: var(--sc-4);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: var(--sc-measure);
  text-wrap: pretty;
}

/* ================================================ web-design · THE WHY ==
   The lead cell spans the grid and carries the 6 to 45 percent jump, which
   is the strongest figure on the page. The other three sit beneath it.
   Every figure is credited in mono; nothing here is uncited. */
.why__grid {
  margin-top: var(--sc-7);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--sc-6) var(--sc-5);
}
.why__cell { border-top: 1px solid var(--sc-hairline); padding-block: var(--sc-4) 0; }
.why__cell--lead {
  grid-column: 1 / -1;
  border-top: 2px solid var(--wl-accent-light);
}
.why__num {
  font-family: var(--sc-font-display);
  font-weight: 400;              /* Bebas Neue ships one weight; never synthesize */
  font-size: var(--sc-t-2xl);
  line-height: 1;
  color: var(--sc-ink);
  display: flex;
  align-items: baseline;
  gap: 0.1em;
}
.why__cell--lead .why__num { font-size: var(--sc-t-3xl); }
.why__unit { font-size: 0.5em; color: var(--wl-accent-light); }
.why__arrow {
  font-family: var(--sc-font-text);
  font-size: 0.42em;
  color: var(--wl-accent-light);
  padding-inline: 0.4em;
}
.why__line {
  margin-top: var(--sc-3);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink);
  max-width: 34ch;
  text-wrap: pretty;
}
.why__cell--lead .why__line { font-size: var(--sc-t-lg); max-width: 40ch; }
.why__src {
  margin-top: var(--sc-3);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  color: var(--sc-ink-soft);
  text-transform: uppercase;
}
.why__gloss {
  margin-top: var(--sc-4);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: 52ch;
  text-wrap: pretty;
}
.why__gloss em { color: var(--sc-ink); font-style: italic; }

/* ============================================= web-design · THE SPINE ==
   The peak of this page: a rule connecting five steps that reveal in order.
   Document flow, not a pinned stage — see the long note in web-design.html
   for why the pinned version had to go (it clipped step 05 off a phone).
   The rule is a plain static line: its job is to connect the nodes, not to
   report progress, so there is no scroll-driven transform that could strand
   it half-drawn. */
.spine__heading {
  font-size: var(--sc-t-2xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  text-wrap: balance;
  max-width: 22ch;
}
.spine {
  position: relative;
  margin-top: var(--sc-6);
  padding-left: var(--sc-6);
  display: flex;
  flex-direction: column;
  gap: var(--sc-4);
}
.spine__rule {
  position: absolute;
  left: 0;
  top: 0.35em;
  bottom: 0.35em;
  width: 2px;
  background: color-mix(in oklab, var(--wl-accent-light) 55%, transparent);
}
.spine__step { position: relative; max-width: 52ch; }
/* The node on the rule for each step. */
.spine__step::before {
  content: "";
  position: absolute;
  left: calc(var(--sc-6) * -1 - 3px);
  top: 0.5em;
  width: 8px;
  height: 8px;
  background: var(--wl-accent-light);
  border-radius: 50%;
}
.spine__n {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  color: var(--wl-accent-light);
}
.spine__name {
  font-family: var(--sc-font-display);
  font-weight: 400;
  font-size: var(--sc-t-xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  margin-top: 2px;
}
.spine__body {
  margin-top: var(--sc-2);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  text-wrap: pretty;
}
/* Step 5 is the differentiator — nobody local claims an automated gate — so
   it gets the weight rather than a decorative flourish. */
.spine__step--last .spine__name { color: var(--wl-accent-light); }
.spine__step--last .spine__body { color: var(--sc-ink); }

/* This act is document flow, not a pinned stage — see the note in
   web-design.html. There is nothing to fit inside a clipped 100svh box, so
   the short-window shrink blocks that used to live here are gone. Type is
   tightened only where the measure would otherwise get long. */
@media (min-width: 900px) {
  .spine__body { max-width: 62ch; }
  .spine__step { max-width: 62ch; }
}

/* ============================================= web-design · THE GAUGE == */
.gauge__list {
  margin-top: var(--sc-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 0;
}
.gauge__row { border-top: 1px solid var(--sc-hairline); padding-block: var(--sc-4); }
.gauge__term {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
}
.gauge__def {
  margin: var(--sc-2) 0 0;
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: 44ch;
  text-wrap: pretty;
}

/* ============================================= web-design · THE PROOF ==
   Sample builds, not clients. No outcome numbers appear in this beat by
   design: a fictional company cannot have a real result (PAGE-MAP.md). */
.proof__grid {
  margin-top: var(--sc-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--sc-5);
}
.proof__card {
  border-top: 2px solid var(--sc-hairline-strong);
  padding-block: var(--sc-4) 0;
}
.proof__trade {
  display: block;
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}
.proof__name {
  display: block;
  margin-top: var(--sc-2);
  font-size: var(--sc-t-xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
}
.proof__what {
  margin-top: var(--sc-3);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  text-wrap: pretty;
}

/* ======================================== ai-automation · WHAT IT IS == */
.plain__cols {
  margin-top: var(--sc-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--sc-5);
}
.plain__not, .plain__is {
  /* No hairline here on purpose: four consecutive beats on this page carried
     the same rule-plus-label treatment and the peak (the trade panel) stopped
     reading as the peak. Three short sentences do not need structure. */
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  text-wrap: pretty;
}
.plain__not strong { color: var(--sc-ink); }
.plain__is {
  color: var(--sc-ink);
  font-size: var(--sc-t-lg);
}
.plain__test em { color: var(--sc-ink); font-style: italic; }

/* ========================================== ai-automation · THE FIVE == */
.five__list {
  margin-top: var(--sc-6);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: var(--sc-6) var(--sc-5);
}
.five__item { border-top: 1px solid var(--sc-hairline); padding-block: var(--sc-4) 0; }
.five__n {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  color: var(--wl-accent-light);
}
.five__name {
  font-family: var(--sc-font-display);
  font-weight: 400;
  font-size: var(--sc-t-lg);
  line-height: var(--sc-leading-tight);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  margin-top: 2px;
  text-wrap: balance;
}
.five__body {
  margin-top: var(--sc-3);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  text-wrap: pretty;
}

/* ==================================== ai-automation · THE VERTICALS ==
   The peak of this page. Selection-driven rather than tear-driven so it
   echoes the homepage close without copying it. Panels are visible in the
   markup and collapsed by script.js — with JS off, all five render stacked
   rather than vanishing. */
.verticals { padding-block: var(--sc-8); padding-inline: var(--sc-gutter); }
.verticals .beat__inner { max-width: var(--sc-maxw); margin-inline: auto; }
.vert { margin-top: var(--sc-6); }
.vert__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sc-2);
  border-bottom: 1px solid var(--sc-hairline);
  padding-bottom: var(--sc-4);
}
.vert__tab {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
  background: transparent;
  border: 1px solid var(--sc-hairline-strong);
  padding-block: 0.85rem;
  padding-inline: var(--sc-4);
  cursor: pointer;
  min-height: 44px;
}
.vert__tab[aria-selected="true"] {
  background: var(--wl-accent-deep);   /* mist on deep = 4.98:1 */
  border-color: var(--wl-accent-deep);
  color: var(--sc-accent-ink);
}
@media (hover: hover) {
  .vert__tab:hover { color: var(--sc-ink); border-color: var(--sc-ink); }
  .vert__tab[aria-selected="true"]:hover { color: var(--sc-accent-ink); }
}
.vert__panel { padding-block: var(--sc-5) 0; }
/* With JS off every panel shows, so each needs its own visible heading. With
   JS on only one panel is present and the tab already names it. */
.vert__panel-name {
  font-family: var(--sc-font-display);
  font-weight: 400;
  font-size: var(--sc-t-xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
}
.js .vert__panel-name {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.vert__rows { margin-top: var(--sc-4); }
.vert__row {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr);
  gap: var(--sc-2) var(--sc-5);
  border-top: 1px solid var(--sc-hairline);
  padding-block: var(--sc-4);
}
.vert__row dt {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--wl-accent-light);
}
.vert__row dd {
  margin: 0;
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: 58ch;
  text-wrap: pretty;
}
/* The payoff row reads as ink, not soft. */
.vert__row:last-child dd { color: var(--sc-ink); }
@media (max-width: 720px) {
  .vert__row { grid-template-columns: 1fr; }
  .vert__tab { flex: 1 1 auto; }
}

/* ========================================= ai-automation · THE LIMITS ==
   Short and blunt, and the reason the rest of the page is believable. */
.limits__list {
  margin-top: var(--sc-5);
  display: flex;
  flex-direction: column;
  gap: 0;
  max-width: var(--sc-measure);
}
.limits__item {
  /* Plain bold sentences, no rules — same reason as .plain__not above. */
  padding-block: var(--sc-3);
  font-size: var(--sc-t-lg);
  font-weight: 600;
  line-height: var(--sc-leading-body);
  color: var(--sc-ink);
  text-wrap: pretty;
}

/* ------------------------------------------------- shared subpage close -- */
.page-close__stage { display: flex; flex-direction: column; justify-content: center; }
.page-close__inner { display: flex; flex-direction: column; align-items: flex-start; }
.page-close__mark { width: clamp(64px, 9vw, 120px); height: auto; }
.page-close__headline {
  margin-top: var(--sc-5);
  font-size: var(--sc-t-3xl);
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  color: var(--sc-ink);
  text-wrap: balance;
  max-width: 16ch;
}
.page-close__sub {
  margin-top: var(--sc-4);
  font-size: var(--sc-t-lg);
  line-height: var(--sc-leading-body);
  color: var(--sc-ink-soft);
  max-width: 46ch;
  text-wrap: pretty;
}
.page-close__cta {
  margin-top: var(--sc-6);
  display: inline-block;
  background: var(--wl-accent-deep);
  color: var(--sc-accent-ink);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-sm);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  padding-block: 1.15rem;
  padding-inline: var(--sc-6);
  min-height: 44px;
}
@media (hover: hover) {
  .page-close__cta:hover { background: var(--sc-ink); color: var(--sc-canvas); }
}
.page-close__next {
  margin-top: var(--sc-5);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}
.page-close__next a {
  color: var(--wl-accent-light);
  border-bottom: 1px solid color-mix(in oklab, var(--wl-accent-light) 55%, transparent);
  padding-bottom: 2px;
}
@media (hover: hover) {
  .page-close__next a:hover { color: var(--sc-ink); border-color: var(--sc-ink); }
}

/* Same clipped-stage trap as the spine above, same cause: the close stack
   measured 848px against an 800px stage at 1440x800 — the mark cut off the
   top — because the display type scales on viewport WIDTH while the stage
   is bounded by HEIGHT. 780px was too late a guard; every laptop is taller
   than that and still too short for this stack. */
@media (max-height: 1000px) {
  .page-close__headline { font-size: var(--sc-t-2xl); }
  .page-close__sub { font-size: var(--sc-t-base); }
  .page-close__cta { margin-top: var(--sc-5); }
  .page-close__mark { width: clamp(52px, 7vw, 84px); }
}
@media (max-height: 860px) and (min-width: 900px) {
  .page-close__headline { font-size: var(--sc-t-xl); margin-top: var(--sc-4); }
  .page-close__cta { margin-top: var(--sc-4); }
  .page-close__next { margin-top: var(--sc-4); }
  .page-close__mark { width: 56px; }
}

.site-foot--page { border-top: 1px solid var(--sc-hairline); }

/* ------------------------------------------------------- reduced motion --
   CLAUDE.md: killing `animation` reverts paused elements to their natural
   (visible) state, so no element's only opacity:0 may live in a plain rule.
   Every hidden element on these two pages is hidden by [data-sc-in] /
   [data-sc-cue], both of which the html:not(.js) block above restores, and
   the spine rule is now a plain static line with no scroll-driven transform
   to strand half-drawn. Nothing further to pin open here. */
