/* ═══════════════════════════════════════════════════════════════════════════
   pages.css — interior page styles (/services/, /how-it-works/, /proof/,
   /about/, /start/).

   HAND-WRITTEN. site.css is generated output from tools/extract_css_js.py and
   must not be edited; everything new lives here. Loaded after site.css so it
   wins specificity ties against the extracted legacy rules.

   Brand values are the :root custom properties declared at the top of
   site.css — --navy #111f44, --deep #1c2a60, --mid #192f67, --orange #f5780a,
   --orange2 #ff9d3d, --blue #5aa8ff, --white #e8edf5, --dim #86a3be — plus the
   three legacy families: Barlow Condensed (headings), Barlow (body),
   Share Tech Mono (labels). Nothing here invents a colour or a font.

   Layout constraints inherited from the legacy shell:
     • #nav is position:fixed, 80px tall (site.css:325).
     • .nav-badge-img is position:fixed at left:0/top:0, 400×600 rendered at
       height:120px → it occupies the top-left 80×120px of every viewport,
       40px BELOW the nav bar. Top clearance must clear 120px, not 80px.
     • The desktop .nav-links only exist at ≥1501px (site.css:484).
     • The homepage offsets itself with #space{padding-top:170px}; there is
       deliberately no global `main` rule here, which would double that.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* One place to retune interior page rhythm. */
  --page-gutter: clamp(24px, 5vw, 88px);
  --page-max: 980px;         /* content column; wider than this leaves half of
                               every card empty at 1600px */
  --measure: 52ch;          /* ≈71 rendered characters of Barlow — measured */
  --nav-clear: 152px;       /* 80px nav + 40px badge overhang + breathing room */
  --hairline: rgba(45, 140, 255, 0.16);
}

/* ─────────────────────────────────────────────────────────────────────────
   1. PAGE HEAD — top clearance for the fixed nav + brand mark
   ───────────────────────────────────────────────────────────────────────── */

.page-head {
  padding: var(--nav-clear) var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
}

.page-head .eyebrow {
  margin-bottom: 18px;
}

.page-head h1 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(40px, 5.4vw, 68px);
  line-height: 1.02;
  letter-spacing: -0.5px;
  color: var(--white);
  max-width: 18ch;
  margin-bottom: 26px;
}

.page-head h1 em {
  font-style: normal;
  color: var(--orange);
}

/* Stub pages (Tasks 7–10 have not built them yet) render a bare <h1> straight
   into <main> with no .page-head wrapper. Without this they hide behind the
   nav exactly like the services page did. Scoped to a DIRECT child of <main>:
   the homepage has zero direct-child <h1> elements, so it is untouched. */
main > h1 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(40px, 5.4vw, 68px);
  line-height: 1.02;
  color: var(--white);
  /* margin, not padding, so the element's own box clears the nav — a padded
     box still reports getBoundingClientRect().top === 0 and reads as an
     overlap in any automated check. */
  margin: var(--nav-clear) auto 40px;
  padding: 0 var(--page-gutter);
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
}

/* ─────────────────────────────────────────────────────────────────────────
   2. SHARED TEXT PRIMITIVES
   ───────────────────────────────────────────────────────────────────────── */

/* Small mono/caps label. Deliberately mirrors the legacy .section-label
   (site.css:498) — same family, size, tracking, colour and 20px leading rule —
   so interior pages read as the same site as the homepage. */
.eyebrow {
  font-family: 'Share Tech Mono', monospace;
  font-size: 13px;
  letter-spacing: 4px;
  line-height: 1.5;
  color: var(--orange);
  text-transform: uppercase;
  display: flex;
  /* flex-start (not center) so the leading rule stays on the first line when
     the eyebrow wraps to three lines at 390px. */
  align-items: flex-start;
  gap: 12px;
}

.eyebrow::before {
  content: '';
  flex: 0 0 auto;
  width: 20px;
  height: 1px;
  margin-top: 0.75em;
  background: var(--orange);
}

/* Readable measure. Full-bleed prose at 1600px is unreadable; --measure keeps
   every run of body copy inside roughly 65–75 characters. */
.lede {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: clamp(17px, 1.3vw, 20px);
  line-height: 1.65;
  color: var(--dim);
  max-width: var(--measure);
}

/* ─────────────────────────────────────────────────────────────────────────
   2b. SERVICES PAGE INTRO
   Added 2026-09-06. The ladder used to open cold on a price list. A visitor
   who does not already know Billy had no reason to care what the rungs cost.
   This primes the sequence the rungs are built from — discovery, analysis,
   delivery — so the list below reads as one method sold in pieces rather than
   as a menu of unrelated products.
   ───────────────────────────────────────────────────────────────────────── */

.page-intro {
  padding: 30px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
}

.page-intro .eyebrow {
  margin-bottom: 18px;
}

.page-intro p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: clamp(16px, 1.15vw, 18px);
  line-height: 1.72;
  color: var(--dim);
  max-width: var(--measure);
  margin-bottom: 18px;
}

/* The three words the whole page hangs on. Given the display face and the
   orange so it reads as a claim, not as another sentence. */
.page-intro-thread {
  font-family: 'Barlow Condensed', sans-serif !important;
  font-weight: 700 !important;
  font-size: clamp(26px, 3vw, 38px) !important;
  line-height: 1.1 !important;
  letter-spacing: 0.5px;
  color: var(--orange) !important;
  text-transform: uppercase;
  margin: 30px 0 24px !important;
  padding-left: 16px;
  border-left: 3px solid var(--orange);
}

/* The lede keeps its own spacing when it follows the intro rather than an h1. */
.page-head-tight {
  padding-top: 8px;
}


/* ─────────────────────────────────────────────────────────────────────────
   ORANGE DISPLAY OUTLINE
   Added 2026-09-06, then reworked twice. Both dead ends are recorded because
   each looks obviously correct until you measure it.

   DEAD END 1 — -webkit-text-stroke. text-stroke is centred on the glyph path,
   so with paint-order:stroke fill the inner half is covered by the fill and
   only half the width survives outside. A 0.9px stroke leaves ~0.45px, which
   is sub-pixel and antialiases to a grey-blue fringe against the navy.
   Magnified at 1x it reads as blur, not as an edge, and going heavier only
   makes a thicker grey fringe.

   DEAD END 2 — a WHITE outline. Eight 1px shadow copies do produce a genuinely
   crisp white edge, and it fails WCAG 1.4.3. axe measures the letter boundary
   as orange-against-white: 2.36:1. This is not fixable by choosing a different
   light colour. --orange sits at 0.33 luminance, so any lighter colour would
   need luminance 1.65 to reach 4.5:1 and pure white is 1.0. Every one of the
   six pages dropped from 100 to 95-96.

   WHAT SHIPPED — the same eight-copy technique in --type-outline (#060b18),
   which clears 4.5:1 against the orange at 7.09:1. It defines the letterform
   against the lightened navy rather than haloing it. Subtler than white, and
   it is the only version that both renders as a real edge and passes.

   WHERE IT APPLIES. 28px and up only. The outline is a fixed 1px, so its
   weight relative to the letterform grows as the type shrinks: 2.6% at 38px
   reads as a crisp edge, 4.2% at 24px starts filling the counters, and 5% at
   20px closes them and swallows the "+" on the trust badges.

   Backdrops were checked by sampling rendered pixels rather than computed CSS:
   every orange element sits on navy between 0.013 and 0.032 luminance,
   including the nav at every scroll position, so no light-backdrop case
   arises anywhere on the site.
   ───────────────────────────────────────────────────────────────────────── */

.page-intro-thread,          /* 38px */
.rung-price,                 /* 38px */
.rung-featured .rung-head h2,/* 32px — only the featured rung is orange; the
                                other six are --white and must not pick up an
                                outline at all */
.nav-acronym,                /* 31px */
.about-stat-num,             /* 30px */
.lp-price {                  /* 28px */
  text-shadow:
     1px  0   0 var(--type-outline),
    -1px  0   0 var(--type-outline),
     0    1px 0 var(--type-outline),
     0   -1px 0 var(--type-outline),
     1px  1px 0 var(--type-outline),
    -1px  1px 0 var(--type-outline),
     1px -1px 0 var(--type-outline),
    -1px -1px 0 var(--type-outline);
}

/* ─────────────────────────────────────────────────────────────────────────
   3. THE LADDER
   ───────────────────────────────────────────────────────────────────────── */

.ladder {
  padding: 56px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

/* Each rung is a card with a visible boundary. Seven of these used to run
   together as one undifferentiated scroll. */
.rung {
  position: relative;
  background: linear-gradient(180deg, rgba(25,47,103, 0.9) 0%, rgba(28,42,96, 0.9) 100%);
  border: 1px solid var(--hairline);
  border-left: 3px solid rgba(45, 140, 255, 0.45);
  padding: 30px clamp(20px, 3vw, 38px) 32px;
  /* The site-wide CTA is /services/#teardown; without this the fixed nav eats
     the top of whichever rung you jump to. */
  scroll-margin-top: 152px;
}

/* The Teardown is the intended entry point — it should not look like the other
   six. Orange rail, orange hairline, lifted off the page, and a ribbon that
   says so out loud. */
.rung-featured {
  border-color: rgba(245, 120, 10, 0.45);
  border-left-color: var(--orange);
  background: linear-gradient(180deg, rgba(40, 24, 10, 0.9) 0%, rgba(28,42,96, 0.92) 60%);
  box-shadow: 0 0 0 1px rgba(245, 120, 10, 0.18), 0 20px 48px rgba(0, 0, 0, 0.5);
  padding-top: 44px;
}

/* A real element carrying real copy from ladder.py — NOT content:'' on a
   pseudo-element, which is invisible to translation and to the a11y tree.
   Pulled out of flow so it sits on the card's top edge without the 44px of
   padding-top above having to be recomputed against its height. */
.rung-ribbon {
  position: absolute;
  top: 0;
  left: -3px;
  font-family: 'Share Tech Mono', monospace;
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--navy);
  background: var(--orange);
  padding: 4px 14px 4px 12px;
}

/* Name left, price right, on one baseline — so all seven prices land in the
   same vertical column and can be scanned in one pass down the page. */
.rung-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: 28px;
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--hairline);
}

.rung-head h2 {
  grid-column: 1;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(26px, 2.5vw, 34px);
  line-height: 1.1;
  letter-spacing: 0.5px;
  color: var(--white);
}

.rung-featured .rung-head h2 {
  color: var(--orange2);
}

/* The single most important text on the site. */
.rung-price {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  justify-self: end;
  text-align: right;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 800;
  font-size: clamp(30px, 3vw, 42px);
  line-height: 1;
  letter-spacing: 0.5px;
  color: var(--orange);
  white-space: nowrap;
}

.rung-featured .rung-price {
  color: var(--orange2);
  text-shadow: 0 0 22px rgba(245, 120, 10, 0.35);
}

.rung-meta {
  grid-column: 1;
  font-family: 'Share Tech Mono', monospace;
  font-size: 11.5px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 8px;
}

.rung-summary {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.65;
  color: var(--white);
  max-width: var(--measure);
  margin-bottom: 24px;
}

/* Section labels inside a card. Mono/caps like .eyebrow but dimmed — orange is
   reserved for the eyebrow, the price and the CTA so the prices stay loudest. */
.rung-label {
  font-family: 'Share Tech Mono', monospace;
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.rung-label::before {
  content: '';
  flex: 0 0 auto;
  width: 14px;
  height: 1px;
  background: rgba(134,163,190, 0.6);
}

/* site.css starts with `* { margin:0; padding:0 }`, so lists need everything
   restored explicitly. */
.rung-deliverables {
  list-style: none;
  max-width: var(--measure);
  margin-bottom: 24px;
}

.rung-deliverables li {
  position: relative;
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 16px;
  line-height: 1.55;
  color: var(--white);
  padding-left: 22px;
  margin-bottom: 8px;
}

.rung-deliverables li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.62em;
  width: 7px;
  height: 1px;
  background: var(--orange);
}

.rung-acceptance {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-style: italic;
  font-size: 16px;
  line-height: 1.6;
  color: var(--dim);
  max-width: var(--measure);
  padding-left: 14px;
  border-left: 1px solid rgba(245, 120, 10, 0.35);
}

/* Optional per-rung link to a published paper. Deliberately NOT a .btn: the
   page already ends in one and a second orange block inside a card would read
   as the rung's own call to action, which it is not — /start/ is. Matches the
   prose-link treatment used by `.sample .sample-note a` on /proof/, so the same
   artefact looks like the same object on both pages. Sits outside the orange
   rule of .rung-acceptance above because it is a different kind of statement:
   that one is a promise, this one is a door. */
.rung-paper {
  font-family: 'Barlow', sans-serif;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.6;
  max-width: var(--measure);
  margin-top: 22px;
}

.rung-paper a {
  color: var(--orange);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 120, 10, 0.45);
  transition: color 0.2s, border-color 0.2s;
}

.rung-paper a:hover,
.rung-paper a:focus {
  color: var(--orange2);
  border-bottom-color: var(--orange2);
}

.rung-paper a:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

/* ─────────────────────────────────────────────────────────────────────────
   4. PAGE CTA + BUTTON
   ───────────────────────────────────────────────────────────────────────── */

.page-cta {
  /* width-minus-gutters, capped at the content column, centred — so it lines
     up with .ladder above it at every width. */
  margin: 64px auto 88px;
  width: calc(100% - 2 * var(--page-gutter));
  max-width: var(--page-max);
  padding: 40px clamp(20px, 3vw, 44px) 44px;
  background: var(--deep);
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--orange);
}

.page-cta h2 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.1;
  color: var(--white);
  margin-bottom: 14px;
}

.page-cta p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.65;
  color: var(--dim);
  max-width: var(--measure);
  margin-bottom: 28px;
}

/* Without this, every CTA on the site is a default user-agent blue underlined
   link on a navy background. */
.btn {
  display: inline-block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--navy);
  background: var(--orange);
  border: 1px solid var(--orange);
  padding: 16px 34px;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}

.btn:hover,
.btn:focus {
  background: var(--orange2);
  border-color: var(--orange2);
  transform: translateY(-1px);
}

.btn:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

/* ─────────────────────────────────────────────────────────────────────────
   5. CURRENT NAV ITEM
   Both navs carry the .is-current hook (and aria-current); site.css does
   nothing with either. Scoped to .is-current only so no other nav internals
   are restyled.

   BOTH is load-bearing: .nav-links is display:none below 1501px, which is not
   just phones — it is every laptop and tablet under 1500px. A desktop-only
   indicator would leave most real viewports with no current-page marker at all.
   ───────────────────────────────────────────────────────────────────────── */

.nav-links a.is-current {
  position: relative;
  color: var(--orange);
}

.nav-links a.is-current::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -8px;
  height: 2px;
  background: var(--orange);
}

/* The Start item is both .cta-link and, on /start/, .is-current. site.css sets
   its colour with !important, so mark it with a ring instead of a bar. */
.nav-links a.cta-link.is-current {
  background: var(--orange2);
  box-shadow: 0 0 0 2px rgba(245, 120, 10, 0.45), 0 0 18px rgba(245, 120, 10, 0.35);
}

.nav-links a.cta-link.is-current::after {
  display: none;
}

/* ── The same treatment in the hamburger menu, which owns every viewport
      below 1501px. site.css sets `#nav-mobile-menu a { color: var(--white) }`
      at specificity (1,0,1); `#nav-mobile-menu a.is-current` is (1,1,1), so it
      wins without !important. ── */

#nav-mobile-menu a.is-current {
  position: relative;
  color: var(--orange);
}

#nav-mobile-menu a.is-current::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -10px;
  height: 3px;
  background: var(--orange);
}

/* .cta-link's colour is !important in site.css here too, so the current Start
   item gets the ring rather than the orange text + bar. */
#nav-mobile-menu a.cta-link.is-current {
  background: var(--orange2);
  box-shadow: 0 0 0 3px rgba(245, 120, 10, 0.5), 0 0 24px rgba(245, 120, 10, 0.4);
}

#nav-mobile-menu a.cta-link.is-current::after {
  display: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   5b. FOOTER LINK
   The footer's mailto: was rendering as a default user-agent blue underlined
   link on navy — the same defect .btn had. Colour only; the footer's markup
   and layout are untouched.
   ───────────────────────────────────────────────────────────────────────── */

footer a {
  color: var(--orange);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 120, 10, 0.4);
  transition: color 0.2s, border-color 0.2s;
}

footer a:hover,
footer a:focus {
  color: var(--orange2);
  border-bottom-color: var(--orange2);
}

footer a:focus-visible {
  outline: 2px solid var(--orange2);
  outline-offset: 3px;
}

/* ─────────────────────────────────────────────────────────────────────────
   6. RESPONSIVE
   Verified at 1600×1200, 390×844 and 844×390.
   ───────────────────────────────────────────────────────────────────────── */

/* Below ~760px the price cannot share a row with the engagement name without
   either wrapping mid-figure or crushing the name. Stack them, price first —
   it stays the loudest thing in the card. */
@media (max-width: 760px) {
  .rung-head {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
  }

  .rung-head h2 {
    grid-column: 1;
    grid-row: 2;
    font-size: 27px;
    margin-top: 2px;
  }

  .rung-price {
    grid-column: 1;
    grid-row: 1;
    justify-self: start;
    text-align: left;
    font-size: 34px;
    white-space: normal;
  }

  .rung-meta {
    grid-row: 3;
  }

  .btn {
    display: block;
    text-align: center;
    padding: 17px 20px;
  }

  .page-head h1 {
    max-width: none;
  }
}

/* Landscape phones (844×390): 152px of top padding is 39% of the viewport
   height. The nav badge is still 120px tall, so this is as tight as it goes. */
@media (max-height: 520px) and (orientation: landscape) {
  .page-head {
    padding-top: 140px;
  }

  main > h1 {
    margin-top: 140px;
  }

  .ladder {
    padding-top: 40px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   7. HOMEPAGE REPOSITION (Direction C)
   The homepage is legacy markup styled by site.css, which is generated and
   must not be edited. These are the classes the repositioned hero, the three
   proof points and the ladder preview introduce — every one of them would
   otherwise render as unstyled default text on navy.

   Section padding mirrors #services / #contact in site.css: 140px on the left
   so content clears the fixed rocket rail, 80px elsewhere.
   ───────────────────────────────────────────────────────────────────────── */

/* Replaces the legacy inline style="color:#1a70e0" on the hero subhead's last
   sentence. #1a70e0 on --navy is ~3.4:1; --blue is ~5.9:1 and is already the
   brand's accent. Its own line, because it is the promise, not an aside. */
.hero-sub-accent {
  display: block;
  margin-top: 12px;
  color: var(--blue);
  font-weight: 400;
}

/* The timebox under the priced CTA. Same fadeUp cadence as the rest of the
   hero (site.css runs .mission-tag/.hero-h1/.hero-sub/.hero-cta at
   0.3s/—/0.7s/0.9s), so it lands one beat after the button. */
.hero-cta-note {
  margin-top: 14px;
  font-family: 'Share Tech Mono', monospace;
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0;
  animation: fadeUp 0.9s ease 1.1s forwards;
}

/* site.css appends '↓' to .hero-cta because the legacy CTA scrolled down the
   same page. This one navigates to /services/#teardown. */
.hero-cta::after {
  content: '→';
}

/* ── Three proof points ─────────────────────────────────────────────────── */

#proof-points {
  position: relative;
  z-index: 3;
  background: var(--navy);
  border-top: 1px solid rgba(45, 140, 255, 0.1);
  padding: 64px 80px 64px 140px;
}

.proof-points {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(28px, 3.2vw, 56px);
  list-style: none;
  margin: 0;
  padding: 0;
}

.proof-point {
  border-top: 2px solid var(--orange);
  padding-top: 20px;
}

/* Sentence case, not the site's usual uppercase: two of the three headings are
   full clauses and uppercase makes them unreadable at this size. */
.proof-point h3 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(22px, 2.1vw, 28px);
  line-height: 1.15;
  letter-spacing: 0.3px;
  color: var(--white);
  margin-bottom: 12px;
}

.proof-point p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 16px;
  line-height: 1.7;
  color: var(--dim);
  margin: 0;
}

/* ── Ladder preview ─────────────────────────────────────────────────────── */

#ladder-preview {
  position: relative;
  z-index: 3;
  background: var(--navy);
  border-top: 1px solid rgba(45, 140, 255, 0.1);
  padding: 80px 80px 80px 140px;
}

/* site.css sets .section-h2 to clamp(44px,5.5vw,72px) uppercase, sized for
   two-word headings. This one is a sentence. */
#ladder-preview .section-h2 {
  font-size: clamp(32px, 3.8vw, 52px);
  max-width: 22ch;
  color: var(--white);
  margin-bottom: 18px;
}

.section-lede {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.7;
  color: var(--dim);
  max-width: 62ch;
  margin-bottom: 40px;
}

.ladder-preview-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  list-style: none;
  margin: 0 0 40px;
  padding: 0;
}

/* The whole card is the link — a VP scanning prices should not have to find a
   4-word target. */
.ladder-preview-item a {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: 24px 22px 22px;
  text-decoration: none;
  background: linear-gradient(180deg, rgba(25,47,103, 0.9) 0%, rgba(28,42,96, 0.9) 100%);
  border: 1px solid var(--hairline);
  border-left: 3px solid rgba(45, 140, 255, 0.45);
  transition: border-color 0.2s, transform 0.2s;
}

.ladder-preview-item a:hover,
.ladder-preview-item a:focus {
  border-color: rgba(245, 120, 10, 0.45);
  border-left-color: var(--orange);
  transform: translateY(-2px);
}

.ladder-preview-item a:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

.lp-name {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(19px, 1.7vw, 23px);
  line-height: 1.1;
  letter-spacing: 0.4px;
  color: var(--white);
}

.lp-price {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 800;
  font-size: clamp(24px, 2.2vw, 32px);
  line-height: 1;
  letter-spacing: 0.5px;
  color: var(--orange);
  margin-top: auto;
}

.lp-duration {
  font-family: 'Share Tech Mono', monospace;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--dim);
}

/* ── Contact section, form removed ──────────────────────────────────────── */

/* #contact is a 1fr 1fr grid and .form-side is a stretched flex column that
   used to hold a ~700px form. With the form replaced by one link, the intro
   strip and the CTA sat at the top of an 800px-tall empty cell. Centring the
   grid item puts the single conversion link opposite the heading it answers. */
#contact .form-side {
  align-self: center;
}

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

/* Matches site.css's own homepage breakpoint (768px), not this file's 760px,
   so these sections change gear on the same line as #services and #contact. */
@media (max-width: 768px) {
  /* site.css pins .mission-tag absolutely with white-space:nowrap. The tag now
     carries the positioning statement, and #space is overflow:hidden — left as
     nowrap it gets clipped mid-phrase on every phone. Kept absolute: #space is
     a flex row and returning this to flow would squeeze .hero-content. */
  .mission-tag {
    white-space: normal;
    /* Aligned with .hero-content's own 80px indent (+ #space's 24px) so it
       clears .nav-badge-img, which is position:fixed over the top-left
       80×120px of the viewport. At left:24px the first line renders behind
       the badge. */
    left: 104px;
    right: 16px;
    top: 86px;
    align-items: flex-start;
    /* 3px of tracking on a 56-character line needs ~560px. Tightened so the
       positioning statement fits two lines above the h1 instead of four. */
    font-size: 11px;
    letter-spacing: 1.5px;
    line-height: 1.7;
  }

  /* The ::before rule is a flex item with no flex-basis; once the text wraps it
     would otherwise be squashed to nothing. */
  .mission-tag::before {
    flex: 0 0 20px;
    margin-top: 8px;
  }

  .hero-cta::after {
    content: none;
  }

  /* #hero-photo-wrap is 68% wide, absolute, mix-blend-mode:screen. At 390px
     that box is the same box as .hero-sub, and a screen blend lightens the
     backdrop until --dim body copy stops resolving — including the clause that
     carries the whole repositioning ("now building the AI systems…"). The photo
     is z-index 5 and .hero-content is z-index 10, so a scrim on the copy sits
     between them: the photo still reads as atmosphere, the promise reads as
     text. Desktop is untouched — there the copy and the photo don't overlap. */
  .hero-content {
    background: linear-gradient(
      to right,
      rgba(17,31,68, 0.93) 0%,
      rgba(17,31,68, 0.88) 72%,
      rgba(17,31,68, 0.74) 100%
    );
    padding-top: 18px;
    padding-bottom: 22px;
  }

  #proof-points,
  #ladder-preview {
    padding: 48px 24px;
  }

  .proof-points,
  .ladder-preview-list {
    grid-template-columns: 1fr;
  }

  #ladder-preview .section-h2 {
    max-width: none;
  }

  .lp-price {
    font-size: 30px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   8. HOW IT WORKS
   site.css contains no element-level rules at all past its opening
   `* { margin:0; padding:0 }` reset, so every bare <h2>, <h3>, <p>, <ul> and
   <a> on an interior page renders as user-agent default — Times-ish sizing
   with zero leading, list markers clipped by the padding reset, and inline
   links as default blue underline on navy. Everything below exists to stop
   that; no colour or family is invented.
   ───────────────────────────────────────────────────────────────────────── */

/* Shared column geometry with .ladder above, so every section on every
   interior page stacks on the same left edge as the .page-head. */
.timeline,
.requirements,
.one-person {
  padding: 56px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
}

/* site.css:764 already owns `.timeline { display: flex; flex-direction: column }`
   for the legacy homepage career timeline, and it would apply here by accident.
   It happens to look identical today because the steps space themselves with
   padding rather than margins — but this page should not inherit its formatting
   context from an unrelated homepage rule, so say block out loud. */
.timeline {
  display: block;
}

/* Section headings. One step down from .page-head h1, one step up from the
   .rung h2 inside a card. */
.timeline > h2,
.requirements > h2,
.data-boundary > h2,
.one-person > h2 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(27px, 3vw, 38px);
  line-height: 1.1;
  letter-spacing: 0.3px;
  color: var(--white);
  margin-bottom: 24px;
}

/* Body copy, held to --measure like every other run of prose on the site.
   `:not(.lede)` is load-bearing: a bare `.data-boundary p` scores (0,1,1) and
   would outrank `.lede` at (0,1,0), silently flattening the two ledes on this
   page back to 17px body text. */
.timeline p,
.data-boundary p:not(.lede),
.one-person p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.7;
  color: var(--white);
  max-width: var(--measure);
  margin-bottom: 18px;
}

.timeline p:last-child,
.data-boundary p:last-child,
.one-person p:last-child {
  margin-bottom: 0;
}

.data-boundary .lede {
  margin-bottom: 8px;
}

/* Inline prose links — matches the footer treatment already in §5b. */
.timeline a,
.requirements a,
.data-boundary a,
.one-person a {
  color: var(--orange);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 120, 10, 0.4);
  transition: color 0.2s, border-color 0.2s;
}

.timeline a:hover,
.timeline a:focus,
.requirements a:hover,
.requirements a:focus,
.data-boundary a:hover,
.data-boundary a:focus,
.one-person a:hover,
.one-person a:focus {
  color: var(--orange2);
  border-bottom-color: var(--orange2);
}

/* ── The day-by-day rail ────────────────────────────────────────────────── */

/* A hairline rail down the left with an orange node per step, so the four
   steps read as a sequence rather than four unrelated paragraphs. */
.timeline-step {
  position: relative;
  padding: 0 0 30px 30px;
  border-left: 1px solid var(--hairline);
}

/* The rail should stop at the last node, not run past it. Keeping the border
   at 1px and only clearing its colour avoids a 1px horizontal shift. */
.timeline-step:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}

.timeline-step::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 9px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--orange);
  /* Punches a hole in the rail behind the node. */
  box-shadow: 0 0 0 3px var(--navy);
}

.timeline-step h3 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(21px, 2vw, 26px);
  line-height: 1.15;
  letter-spacing: 0.4px;
  color: var(--white);
  margin-bottom: 10px;
}

/* ── What I need from you ───────────────────────────────────────────────── */

/* The reset killed both the marker indent and the marker itself, so the dash
   is drawn — same treatment as .rung-deliverables. */
.requirements ul {
  list-style: none;
  max-width: var(--measure);
}

.requirements li {
  position: relative;
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.6;
  color: var(--white);
  padding-left: 24px;
  margin-bottom: 12px;
}

.requirements li:last-child {
  margin-bottom: 0;
}

.requirements li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.68em;
  width: 9px;
  height: 1px;
  background: var(--orange);
}

/* ── Where your data goes ───────────────────────────────────────────────── */

/* This is the section that answers the question nobody in this market asks
   out loud, so it is built as a bounded panel — a published posture — rather
   than four more paragraphs of prose. Geometry copied from .page-cta so the
   two boxes on the page align. */
.data-boundary {
  margin: 60px auto 0;
  width: calc(100% - 2 * var(--page-gutter));
  max-width: var(--page-max);
  padding: 36px clamp(20px, 3vw, 40px) 40px;
  background: var(--deep);
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--orange);
  /* /how-it-works/#data-handling is quotable in an email; the fixed nav would
     otherwise eat the heading. */
  scroll-margin-top: 152px;
}

.data-boundary h3 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(20px, 1.9vw, 24px);
  line-height: 1.2;
  letter-spacing: 0.4px;
  color: var(--orange2);
  margin: 28px 0 10px;
}

/* ── "You're one guy." ──────────────────────────────────────────────────── */

.one-person {
  padding-bottom: 4px;
}

/* ─────────────────────────────────────────────────────────────────────────
   9. ABOUT
   NOTE on .about-photo: site.css already contains `.about-photo-frame`,
   `.about-photo-wrap` etc. for the legacy homepage section, so a naive
   substring check for ".about-photo" in the CSS passes whether or not this
   class is styled. It needs real rules, and these are them.
   ───────────────────────────────────────────────────────────────────────── */

.about-body {
  padding: 48px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
}

/* Contains the floated portrait so it can never overlap the .page-cta below,
   whatever the prose length ends up being. */
.about-body::after {
  content: '';
  display: table;
  clear: both;
}

/* The source file is 1182×1330. Left to itself it renders full-bleed and the
   page opens with a 1300px-tall face. Capped, cropped to 3:4 and floated so
   the credibility copy stays the first thing read; object-position keeps the
   head in frame under the crop. */
.about-photo {
  float: right;
  width: clamp(200px, 26vw, 300px);
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 22%;
  margin: 6px 0 24px 40px;
  background: rgba(25,47,103, 0.6);
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--orange);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

.about-body h2 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(24px, 2.4vw, 32px);
  line-height: 1.1;
  letter-spacing: 0.3px;
  color: var(--white);
  margin: 38px 0 14px;
}

/* :not(.lede) for the same specificity reason as §8. */
.about-body p:not(.lede) {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.7;
  color: var(--white);
  max-width: var(--measure);
  margin-bottom: 18px;
}

.about-body .lede {
  margin-bottom: 22px;
}

.about-body p:last-child {
  margin-bottom: 0;
}

/* Below ~700px the 200px floor on the portrait plus its 40px gutter leaves
   roughly 100px for the sentence beside it. Unfloat it and let it sit above
   the copy, small enough to stay a portrait rather than a billboard. */
@media (max-width: 700px) {
  .about-photo {
    float: none;
    display: block;
    width: 190px;
    margin: 0 0 26px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   10. PROOF
   Two work samples, deliberately. The page is thin at launch because there is
   nothing honest to put in it yet, so the samples are built as cards rather
   than prose — two bounded artefacts read as "here is what exists", where two
   loose paragraphs read as "here is what is missing".
   ───────────────────────────────────────────────────────────────────────── */

.work-samples {
  padding: 52px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 26px;
}


/* Track divider on /proof/. The page now carries four published reports across
   two audiences; without a divider a defense buyer reads two commercial reports
   first and concludes the page is not for them. Sits outside .sample so it
   reads as a section label rather than another card. */
.sample-track {
  font-family: 'Share Tech Mono', monospace;
  font-size: 12px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--orange);
  margin: 22px 0 -8px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline);
}

.sample-track:first-child {
  margin-top: 0;
}

/* Same card as .rung on /services/ — same rail, same hairline, same gradient,
   so a visitor arriving from the ladder recognises the object. */
.sample {
  background: linear-gradient(180deg, rgba(25,47,103, 0.9) 0%, rgba(28,42,96, 0.9) 100%);
  border: 1px solid var(--hairline);
  border-left: 3px solid rgba(45, 140, 255, 0.45);
  padding: 30px clamp(20px, 3vw, 38px) 32px;
}

.sample h2,
.sample h3 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(24px, 2.4vw, 32px);
  line-height: 1.12;
  letter-spacing: 0.4px;
  color: var(--white);
  max-width: 28ch;
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--hairline);
}

.sample p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.7;
  color: var(--white);
  max-width: var(--measure);
  margin-bottom: 18px;
}

.sample p:last-child {
  margin-bottom: 0;
}

/* The aside that claims the sample as evidence. Same treatment as
   .rung-acceptance — italic, dimmed, orange rule — because it plays the same
   role: the sentence you are being asked to hold me to.

   Scoped as `.sample .sample-note` at (0,2,0) on purpose: a bare
   `.sample-note` is (0,1,0) and loses the colour to `.sample p` at (0,1,1)
   above, which would leave this paragraph the same --white as the body copy. */
.sample .sample-note {
  font-style: italic;
  color: var(--dim);
  padding-left: 14px;
  border-left: 1px solid rgba(245, 120, 10, 0.35);
}

/* A sample can carry a second .sample-note holding the route to obtain it. Left
   alone, `.sample p`'s 18px margin-bottom breaks the orange rule into two
   separately-boxed quotes with a gap between them, which reads as two unrelated
   asides. Moving that space inside the first box keeps the rail continuous, so
   the claim and the ask are visibly one thing. */
.sample .sample-note:not(:last-child) {
  margin-bottom: 0;
  padding-bottom: 14px;
}

/* The ask itself. Not a .btn — the page already has one in .page-cta and a
   second orange block would compete with it — but not body prose either:
   un-italicised and one weight up, because it is the only thing on this page a
   reader can act on. Colour/underline match the prose links in §8. */
.sample .sample-note a {
  font-style: normal;
  font-weight: 400;
  color: var(--orange);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 120, 10, 0.45);
  transition: color 0.2s, border-color 0.2s;
}

.sample .sample-note a:hover,
.sample .sample-note a:focus {
  color: var(--orange2);
  border-bottom-color: var(--orange2);
}

.sample .sample-note a:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

/* Two-up before the single-column collapse — four cards at 900px leaves each
   one narrower than its own price. */
@media (min-width: 769px) and (max-width: 1180px) {
  .ladder-preview-list {
    grid-template-columns: repeat(2, 1fr);
  }

  .proof-points {
    grid-template-columns: 1fr;
    gap: 30px;
  }

  #proof-points,
  #ladder-preview {
    padding-left: 100px;
    padding-right: 48px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   11. START — DIRECT CONTACT + THE CONTACT FORM

   This is the only page on the site where a referral converts, and the only
   one with interactive controls. site.css contains no element-level rules for
   input / textarea / select / button / label at all — its legacy form styles
   are scoped to `.field`, `.f-row` and `.contact-form`, none of which this
   markup uses — so without everything below the form renders as user-agent
   default: white boxes on navy, 13px system type, and a focus ring the same
   colour as the page.

   Two inheritance traps this section exists to close:
     • `text-transform` and `letter-spacing` INHERIT into a nested control. The
       field labels are mono/uppercase/tracked and each one WRAPS its input, so
       without an explicit reset the visitor's typed name renders as spaced
       capitals. Same for the placeholder.
     • site.js:62-68 writes #cf-status's colour, background and border as
       INLINE styles (green on success, red on failure). Inline wins over any
       stylesheet, so this section styles only that element's geometry and type
       — a `border-left` accent here would be erased by the inline `border`
       shorthand, and a colour would never apply at all.
   ───────────────────────────────────────────────────────────────────────── */

/* Shared column geometry with .page-head above and .ladder / .timeline on the
   other interior pages, so every section on the site stacks on one left edge. */
.direct-contact,
.contact-form-section {
  padding: 48px var(--page-gutter) 0;
  max-width: calc(var(--page-max) + 2 * var(--page-gutter));
  margin-inline: auto;
}

/* Last section on the page — it owns the gap down to the footer. */
.contact-form-section {
  padding-bottom: 88px;
}

/* Same step as the section headings on /how-it-works/. */
.direct-contact > h2,
.contact-form-section > h2 {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(27px, 3vw, 38px);
  line-height: 1.1;
  letter-spacing: 0.3px;
  color: var(--white);
  margin-bottom: 20px;
}

.direct-contact p {
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.7;
  color: var(--white);
  max-width: var(--measure);
}

/* Prose link treatment from §5b/§8. A bare mailto: on navy is default
   user-agent blue-on-near-black — the address is the fallback conversion path
   on this page, so it cannot be the least readable thing on it. */
.direct-contact a {
  color: var(--orange);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 120, 10, 0.4);
  transition: color 0.2s, border-color 0.2s;
}

.direct-contact a:hover,
.direct-contact a:focus {
  color: var(--orange2);
  border-bottom-color: var(--orange2);
}

.direct-contact a:focus-visible {
  outline: 2px solid var(--orange2);
  outline-offset: 3px;
}

/* ── The form ───────────────────────────────────────────────────────────── */

/* 640px, not the 980px content column: at --page-max a two-up .field-row gives
   each input ~480px, which is four times the widest value anyone types into
   "Phone" and reads as a database screen rather than a note to a person. */
#contact-form {
  display: flex;
  flex-direction: column;
  gap: 22px;
  max-width: 640px;
}

/* Every label WRAPS its control, so this is `block` rather than a flex column:
   as a flex container the label text and the .req asterisk beside it become
   two separate flex items and the asterisk drops onto its own line. */
#contact-form label {
  display: block;
  font-family: 'Share Tech Mono', monospace;
  /* 12px against the legacy .field label's 11px. Same family, tracking and
     case, one step up, because these are the labels a stranger fills in on a
     phone rather than decoration on a homepage. */
  font-size: 12px;
  letter-spacing: 2px;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--blue);
}

.req {
  color: var(--orange);
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

#contact-form input[type="text"],
#contact-form input[type="email"],
#contact-form input[type="tel"],
#contact-form textarea,
#contact-form select {
  display: block;
  width: 100%;
  margin-top: 8px;
  /* 46px here, 48px below 700px: the whole control is the touch target. */
  min-height: 46px;
  padding: 12px 14px;
  background: rgba(25,47,103, 0.85);
  /* Deliberately louder than the 0.1–0.16 hairlines used everywhere else on the
     site, and louder than the legacy .field input's rgba(...,0.15). The fill is
     only 1.08:1 against the page, so the border IS the control — measured, it
     needs 0.65 alpha to clear the 3:1 WCAG 1.4.11 floor for the boundary of an
     interactive element (0.28 measured 1.47:1, 0.15 is worse still). A field a
     visitor cannot find is not a decorative hairline problem. */
  border: 1px solid rgba(45, 140, 255, 0.65);
  color: var(--white);
  font-family: 'Barlow', sans-serif;
  font-weight: 400;
  /* 16px is a floor, not a preference — mobile Safari zooms the viewport on
     focus for anything smaller and never zooms back out. */
  font-size: 16px;
  line-height: 1.4;
  /* Undo what the mono label inherits into its own control. */
  text-transform: none;
  letter-spacing: normal;
  transition: border-color 0.2s, background 0.2s;
}

/* 0.85 alpha measures 4.79:1 against the field fill — the placeholder is the
   worked example of what to write here, so it has to be readable. Still well
   short of the 15:1 that typed text gets, so it never reads as a filled value.
   (The legacy .field placeholder was 0.35 alpha: 1.6:1, effectively invisible.) */
#contact-form ::placeholder {
  color: rgba(134,163,190, 0.97);
  font-weight: 300;
  text-transform: none;
  letter-spacing: normal;
}

#contact-form textarea {
  min-height: 148px;
  resize: vertical;
}

/* The closed <select> picks up the rule above, but the popup list is painted by
   the platform from the option's own background — left alone it is near-white
   text on near-white on Linux Chromium. */
#contact-form select option {
  background: #0d1530;
  color: var(--white);
}

/* Border + fill shift for any focus (pointer included); a real outline for
   keyboard focus, because a border colour change alone disappears in
   forced-colours mode and is easy to miss mid-form. */
#contact-form input:focus,
#contact-form textarea:focus,
#contact-form select:focus {
  border-color: var(--orange);
  background: rgba(25,47,103, 1);
}

#contact-form input:focus-visible,
#contact-form textarea:focus-visible,
#contact-form select:focus-visible {
  outline: 2px solid var(--orange2);
  outline-offset: 2px;
}

/* The one label that is a sentence to read rather than a field name, so it
   drops the mono/uppercase treatment. (1,1,0) beats `#contact-form label`. */
#contact-form .checkbox-label {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  font-family: 'Barlow', sans-serif;
  font-weight: 300;
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  color: var(--white);
  cursor: pointer;
}

#contact-form input[type="checkbox"] {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--orange);
  cursor: pointer;
}

/* .btn already carries the brand treatment; this only places it and gives it a
   busy state. site.js disables the button and swaps its label to "Sending…"
   during the fetch — left unstyled it stays full-strength orange and looks
   clickable while it is not. :hover is included because CSS still matches it on
   a disabled control, which would otherwise animate a dead button. */
#contact-form #cf-submit {
  align-self: flex-start;
  margin-top: 4px;
}

/* Ghosted rather than dimmed. A first attempt just dropped the fill to 40%
   orange and kept the navy label, which measured 1.8:1 — "SENT ✓" was the least
   readable thing on the page at the exact moment it was the most reassuring.
   Hollow box, --orange2 label: 6.7:1 measured against the blended fill, and
   plainly not the solid button it was a moment ago. */
#contact-form #cf-submit:disabled,
#contact-form #cf-submit:disabled:hover {
  background: rgba(245, 120, 10, 0.22);
  border-color: rgba(245, 120, 10, 0.45);
  color: var(--orange2);
  transform: none;
  cursor: progress;
}

/* Hidden until site.js has something to say; it sets display:block inline at
   the same moment it sets the colours. Geometry and type only — see the
   section header for why colour here would be dead code. */
#cf-status {
  display: none;
  margin-top: 2px;
  padding: 14px 16px;
  font-family: 'Barlow', sans-serif;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.5;
  max-width: var(--measure);
}

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

/* Two-up stops working before the ladder cards do: at 700px each half of a
   .field-row is ~300px minus gutters, and "Organization" no longer fits its own
   label. Below here every field owns a full row. */
@media (max-width: 700px) {
  .field-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }

  #contact-form input[type="text"],
  #contact-form input[type="email"],
  #contact-form input[type="tel"],
  #contact-form select {
    min-height: 48px;
  }

  /* Full-bleed submit. The 760px rule above already makes .btn a block; this
     stops the flex container shrinking it back to its text width, which on a
     390px screen is a 100px target floating at the left margin. */
  #contact-form #cf-submit {
    align-self: stretch;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   12. NAV BRAND vs. HAMBURGER — the phone-width collision
   ───────────────────────────────────────────────────────────────────────── */

/* Measured on /services/: .nav-name's right edge lands exactly on the viewport
   edge and #nav-hamburger's left edge sits 72px inside it, so the brand text
   prints straight through the button. Gaps before this fix: −72px at 320–480px,
   −55px at 500px, −35px at 520px, −15px at 540px, clear from 560px up.
   This is every page, at every phone width.

   Why it happens: .nav-logo is `position: fixed; left: 126px` with no `right`
   and no width, so its shrink-to-fit width fills all the space to the viewport
   edge (site.css:343). #nav-hamburger is `position: fixed; right: 24px`
   (site.css:421) and measures 48px wide — 22px of span + 24px padding + 2px
   border — so its left edge is always 72px from the right edge. Neither box is
   in flow, so nothing reflows: they simply overprint.

   Fixed by giving .nav-logo the max-width it never had. 96px = the hamburger's
   72px footprint + a 24px gutter. The gutter is deliberately wider than it
   looks necessary: `100vw` includes the classic scrollbar on desktop while
   `right: 24px` does not, so up to ~17px of that gutter can be eaten by a
   scrollbar before the two boxes touch. */
@media (max-width: 1500px) {
  .nav-logo {
    max-width: calc(100vw - 126px - 96px);
  }

  /* site.css only unsets nowrap at ≤768px. Without this, a max-width above that
     breakpoint would clip nothing and overflow the text visibly past the box —
     the collision would still be on screen while measuring as fixed. */
  .nav-name {
    white-space: normal;
  }
}

/* 768px, not some new number: site.css already drops .nav-name to
   clamp(13px, 3.8vw, 17px) and unsets nowrap on exactly this line, so the brand
   changes gear once instead of twice. */
@media (max-width: 768px) {
  /* nav-badge.webp is 400×600, so at the CSS height of 120px it is only 80px
     wide — measured. The legacy `left: 126px` therefore leaves 46px of dead
     gutter between the badge and the brand name, which is 13% of a 360px
     screen. Reclaiming it is what keeps the name legible instead of forcing it
     into four cramped lines. 8px of clearance from the badge is kept. */
  .nav-logo {
    left: 88px;
    max-width: calc(100vw - 88px - 96px);
  }

  /* Tracking, not type size: the name is 42 characters, so 2px of letter-
     spacing alone spends 84px of horizontal advance. Spending that on glyphs
     instead buys most of a line back without shrinking the type further —
     site.css has already dropped it to clamp(13px, 3.8vw, 17px) here. */
  .nav-name {
    letter-spacing: 0.5px;
  }
}

/* The <a class="nav-badge"> wrapping the badge image has no rule in the
   extracted stylesheet at all, so it is a zero-size inline box inside a
   `pointer-events: none` nav — the brand mark is clickable only because
   .nav-badge-img re-enables pointer events on its own pixels. Give the link the
   same fixed box as the image it wraps so the hit area is the badge, not a
   collapsed anchor. Width is explicit because the image is itself
   position:fixed and so contributes nothing to its parent's size. */
.nav-badge {
  position: fixed;
  top: 0;
  left: 0;
  width: 80px;
  height: 120px;
  z-index: 502;
  pointer-events: all;
}

/* ─────────────────────────────────────────────────────────────────────────
   13. HOMEPAGE HERO — .mission-tag vs .hero-h1 on small phones
   ───────────────────────────────────────────────────────────────────────── */

/* #space is `align-items: center` with `height: 100vh; min-height: 700px`
   (site.css:101), while .mission-tag is absolutely positioned at top: 86px and
   takes no part in that centring. Below 480px the tag wraps to two or three
   lines and .hero-content grows taller than the section's content box, so the
   centred content is pushed *up* underneath the tag. Measured overlap of the
   tag's bottom edge over .hero-h1's top edge: 70px at 320×568, 53px at 360×640,
   33px at 360×740, 16px at 390×600, 8px at 480×600. Clear at ≥540px wide and at
   ≥844px tall.

   Pre-existing — the legacy rules collide here too, so this is not a Task 6
   regression — but 360px is the narrowest common phone width.

   Pinning the content to a fixed top edge instead of centring it removes the
   dependency on content height entirely: 152px clears the tag's tallest wrap
   (top 86px + three 18.7px lines = 142px) with 10px to spare. height:auto with
   min-height:100vh keeps the hero full-screen when the copy fits and lets it
   grow when it doesn't, rather than overflowing a 700px box. */
@media (max-width: 480px) {
  #space {
    height: auto;
    min-height: 100vh;
    align-items: flex-start;
    padding-top: 152px;
  }
}

/* Legacy dead markup, migrated verbatim in Task 4:
   <div class="parallax-slow" id="stars-slow"></div> has no rule in the
   extracted stylesheet and no reference in home.js — the star field is drawn on
   #starfield's <canvas> instead, and the depth layers are #px-layer-*. Left
   unstyled it is a stray flex item in #space's flex row. Declared out of layout
   rather than deleted, so the verbatim migration stays verbatim and the element
   is still there if anyone wires it up. */
.parallax-slow {
  display: none;
}

/* ── §14 Scroll landing offset ─────────────────────────────────────────────
   #nav is a fixed 80px bar and .nav-badge-img hangs down to 120px, so anything
   scrolled to the very top of the viewport has its first line hidden behind
   them. Reported on Android Chrome: the "Depth" proof-point heading landed
   under the badge. scroll-padding-top makes anchor navigation, nav-dot
   scrollIntoView() and browser fragment jumps all land clear automatically.
   home.js's snapTo() uses window.scrollTo(), which does NOT honour this, so it
   applies the same 152px offset in JS — keep the two values in step. */
html {
  scroll-padding-top: 152px;
}

/* ── §15 Mobile fixes reported from Android Chrome, 2026-08-03 ───────────────
   Four separate defects, all mobile-only, all caused by desktop-shaped rules
   being applied to a 412px viewport. Desktop is deliberately untouched — at
   1600px the headline and photo have 53px of clearance and read correctly. */
@media (max-width: 768px) {

  /* 1. "The text below START WITH A $2,500 WORKFLOW TEARDOWN is cut off so I
        cant read it." Not clipped — washed out. #hero-photo-wrap is
        mix-blend-mode:screen and spans x=132-412, i.e. straight through the note
        at x=104-388. The §7 scrim fades to 0.74 alpha at its right edge, which
        is not enough to hold a 12px --dim line. Opaque the scrim's tail and
        brighten the note. */
  .hero-content {
    background: linear-gradient(
      to right,
      rgba(17,31,68, 0.96) 0%,
      rgba(17,31,68, 0.94) 72%,
      rgba(17,31,68, 0.90) 100%
    );
  }
  .hero-cta-note {
    color: #b9cde0;
    letter-spacing: 1.2px;
    line-height: 1.5;
  }

  /* 1b. …and the decorative scroll cue printed straight through it. The note
        wraps to two lines at this width (43 monospace characters cannot fit
        284px at 12px), so it reaches y=712, while .scroll-hint is
        position:absolute bottom:32px — which on a 780px viewport (a Pixel with
        the Chrome URL bar showing) lands at y=690. Measured 10px of overlap at
        780 and none at 915, which is why it was invisible in taller emulation.
        The cue is 9px at 30% white and purely decorative; the priced CTA
        directly above it already says what happens next. */
  .scroll-hint {
    display: none !important;
  }

  /* 2. "There is too big of a verticle space between [the last proof point] and
        [the SME section]." #atmosphere is the decorative gradient transition at
        height:50vh — 390px of empty screen on a 780px viewport, half a phone.
        It exists to blend navy into the skyline's sky, which needs far less
        room at this size. */
  #atmosphere {
    height: 140px !important;
  }

  /* 3 + 4. "the image for the 2nd hero section is sized too large / THE SME IS
        THE ENGINEER overlaps the image / a portion of the image is offscreen
        right / the image has text on it that is hard to read because of the
        overflow on the left."

        All one root cause. site.css pins #skyline-section and #skyline-stage to
        50vh, then positions .skyline-content absolutely at left:140px and
        #sme-photo-wrap absolutely at right:0 with width:65%. At 412px that is
        272px of headline overlapping 268px of photo — measured 228px of
        collision. On top of that, object-fit:cover squeezes a 1536x1024 (3:2)
        image into a 268x310 (0.86:1) box, cropping the sides, and a
        mask-image fades the left 14% — which is exactly where the photo's
        baked-in caption sits.

        Fix: stop overlaying. Let the section grow, put the headline above and
        the whole photo below at its true aspect ratio, with no crop, no left
        feather and no blend mode. Nothing is cropped and nothing overlaps.

        NB: #sme-photo's opacity is deliberately NOT touched — it starts at 0 and
        home.js's skyline observer adds .revealed to fade it in. Overriding
        opacity here would leave the photo permanently invisible. */
  #skyline-section {
    height: auto !important;
    min-height: 0 !important;
    padding: 8px 0 0 !important;
  }
  /* Flex column with explicit order, because in the markup #sme-photo-wrap
     comes BEFORE .skyline-content — static flow alone would put the photo above
     the headline. #sky-bg and #city-glow stay absolutely positioned and so are
     out of flow; they are unaffected by the ordering. */
  #skyline-stage {
    position: relative !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: flex-start !important;
  }
  .skyline-content {
    order: 1;
    position: static !important;
    top: auto !important;
    left: auto !important;
    max-width: none !important;
    padding: 0 24px 20px;
  }
  #sme-photo-wrap {
    order: 2;
    position: static !important;
    top: auto !important;
    bottom: auto !important;
    right: auto !important;
    width: 100% !important;
    height: auto !important;
    display: block !important;
  }
  #skyline-svg { order: 3; }
  #sme-photo {
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 2;
    object-fit: contain;
    object-position: center center;
    mask-image: none !important;
    -webkit-mask-image: none !important;
    mix-blend-mode: normal !important;
    filter: none;
  }
}

/* ── §16 The services CTA read as a footnote, not an invitation ──────────────
   Reported: "Where the text says: Ready to build something that works? Lets
   make that stand out it blends into the page to well."

   It did blend: site.css:619 renders it at 13px Share Tech Mono in
   rgba(200,215,235,0.45) — 45% opacity, uppercase, tracked out — sitting beside
   a full-strength orange button that swallowed all the attention. It was styled
   as a quiet label leading into the button rather than as the conversion moment
   at the end of the capabilities section.

   Rather than invent a new treatment, this adopts the SAME shape the interior
   pages already use for exactly this job (.page-cta, §5): a bounded panel on
   --deep with a hairline border and a 2px orange top edge, a headline-scale line
   in white Barlow Condensed, and the button beneath it. So the homepage and
   /services/, /how-it-works/, /proof/ and /about/ now close with the same
   recognisable block instead of four different ones. */
.services-cta {
  margin-top: 64px;
  /* was display:flex with the text and button side by side, which forced the
     text to compete with the button on the same line. Stack them. */
  display: block;
  background: var(--deep);
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--orange);
  padding: 36px clamp(20px, 3vw, 44px) 40px;
}

.services-cta-text {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  /* Same scale as .page-cta h2 so the two read as one system. */
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1.1;
  letter-spacing: 0;
  /* Drop the uppercase + 3px tracking: sentence case is what makes it read as a
     question addressed to the visitor rather than as a UI label. */
  text-transform: none;
  color: var(--white);
  margin-bottom: 22px;
  max-width: 24ch;
}

.services-cta-btn {
  /* Legacy rule already supplies the orange fill and navy label; it only needs
     to stop being a flex sibling and to be thumb-sized on a phone. */
  display: inline-block;
}

@media (max-width: 768px) {
  .services-cta {
    margin-top: 44px;
    padding: 28px 20px 32px;
  }
  .services-cta-btn {
    display: block;
    width: 100%;
    text-align: center;
    padding: 16px 20px;
  }
}
