/* Dropped Pin. See DESIGN.md before changing tokens.
   Phone first. Every media query grows upward from 390px.

   System: stamp ink on warm paper. One accent, used as a shape far more often
   than as a fill. The identity is a wordmark with a displaced tittle plus a
   maker's seal. There is no pin icon anywhere, deliberately. */

/* ── Type, self-hosted ────────────────────────────────────── */
/* Instanced from the Google Fonts latin subsets on 2026-09-03 (O2). The two
   variable files Google served were 161 KB together and put the page at about
   285 KB against a 150 KB budget. These carry only what the site sets: Overpass
   600 to 800 as one partial variable file, 28 KB, and Source Serif 4 at 400 with
   the optical size pinned at 16, 20 KB. Both faces are OFL. Recipe: fontTools
   varLib.instancer on the gstatic latin woff2, recorded in the O1 audit under
   business/audits/2026-09-03-droppedpin-craft-gap/. */
@font-face {
  font-family: "Overpass";
  font-style: normal;
  font-weight: 600 800;
  font-display: swap;
  src: url("/fonts/overpass-600-800-v2.woff2") format("woff2");
}
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/source-serif-4-400.woff2") format("woff2");
}

:root {
  /* Ground. Warm, but kept at hue 34 rather than the 40 to 100 band, because
     a low-chroma warm background in that band is the most recognisable
     machine-made-website tell there is. This reads as manila, not cream. */
  --paper:       oklch(0.958 0.008 34);
  --paper-2:     oklch(0.916 0.013 34);
  --surface:     oklch(0.995 0.003 34);
  --ink:         oklch(0.215 0.013 30);
  --ink-soft:    oklch(0.442 0.017 30);
  --hair:        oklch(0.872 0.013 34);

  /* Stamp ink. Cooler and more saturated than the brick red it replaces, so it
     reads as something pressed onto paper rather than as terracotta. */
  --stamp:       oklch(0.487 0.176 25);
  --stamp-deep:  oklch(0.383 0.147 25);
  --stamp-lift:  oklch(0.722 0.148 28);   /* stamp-coloured TEXT on --ink only */

  /* Printed-atlas palette for the drawn maps. Pale enough that the mark wins. */
  --map-water: oklch(0.892 0.042 226);
  --map-park:  oklch(0.912 0.040 142);
  --map-block: oklch(0.921 0.009 34);
  --map-road:  oklch(0.953 0.006 34);
  --map-hwy:   oklch(0.862 0.072 76);
  --map-label: oklch(0.598 0.017 30);

  --display: Overpass, system-ui, sans-serif;
  --body: "Source Serif 4", Georgia, serif;

  --step-0: 1.0625rem;
  --step-1: clamp(1.25rem, 1.1rem + 0.7vw, 1.5rem);
  --step-2: clamp(1.6rem, 1.3rem + 1.4vw, 2.1rem);
  --step-3: clamp(2.1rem, 1.6rem + 2.4vw, 3.2rem);
  --step-4: clamp(2.4rem, 1.6rem + 3.6vw, 4.3rem);

  --gut: clamp(1.25rem, 5vw, 2.5rem);
  --bandpad: clamp(3.5rem, 9vw, 6.5rem);
}

@supports not (color: oklch(0 0 0)) {
  :root {
    --paper:#f5f1ee; --paper-2:#e8ded7; --surface:#fffdfc;
    --ink:#1f1a18; --ink-soft:#5b524d; --hair:#ded3cc;
    --stamp:#a52d1d; --stamp-deep:#7a2114; --stamp-lift:#e8846b;
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--display); font-weight: 800;
  letter-spacing: -0.025em; line-height: 1.08; text-wrap: balance;
}
h1 { font-size: var(--step-4); margin: 0 0 1rem; }
h2 { font-size: var(--step-3); margin: 0 0 1.25rem; }

p { margin: 0 0 1.1rem; }
a { color: var(--stamp-deep); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--ink); color: var(--paper); padding: 0.75rem 1rem;
}
.skip:focus { left: 0; }
:focus-visible { outline: 3px solid var(--stamp); outline-offset: 3px; }

.wrap { width: min(72rem, 100% - var(--gut) * 2); margin-inline: auto; }

/* ── The wordmark ─────────────────────────────────────────── */
/* The tittle falls clean through the baseline and hangs below the word. It is
   the only piece of the identity that has to be exactly right, so it is built
   from a dotless i plus a positioned dot rather than trusted to a font. */
.wordmark {
  font-family: var(--display); font-weight: 800; letter-spacing: -0.035em;
  color: var(--ink); text-decoration: none; white-space: nowrap; line-height: 1;
}
.wm-i { position: relative; display: inline-block; }
.wm-dot {
  position: absolute; left: 50%; bottom: -0.17em;
  width: 0.2em; height: 0.2em; border-radius: 50%;
  background: var(--stamp); transform: translateX(-50%);
}
.band--ink .wordmark, .foot .wordmark { color: var(--paper); }
.band--ink .wm-dot, .foot .wm-dot { background: var(--stamp-lift); }

/* ── The seal ─────────────────────────────────────────────── */
/* Full seal carries type and needs 110px to stay legible. Below that the
   words come off and only the rings and register mark remain. */
.seal { display: block; color: var(--stamp); }
.seal--ink { color: var(--stamp-lift); }

/* ── Contour texture ──────────────────────────────────────── */
.contours { position: absolute; inset: 0; pointer-events: none;
  background-image:
    repeating-radial-gradient(circle at 78% 18%, transparent 0 38px, var(--hair) 38px 39px),
    repeating-radial-gradient(circle at 12% 88%, transparent 0 52px, var(--hair) 52px 53px);
  opacity: 0.5;
}

/* ── Nav ──────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 20;
  background: oklch(0.958 0.008 34 / 0.9);
  backdrop-filter: blur(10px);
  /* The hairline is a box-shadow, not a border, so it can appear on scroll
     without moving anything. At the top the bar is the same paper as the hero
     and reads as part of it. Once the page moves it lifts off. M3, 2026-09-03. */
  box-shadow: 0 1px 0 transparent;
  transition: box-shadow 200ms ease;
}
.nav.is-scrolled {
  box-shadow: 0 1px 0 var(--hair), 0 10px 24px -20px oklch(0.215 0.013 30 / 0.6);
}
/* 0.5rem on a phone, 1rem once there is room. The bar carries three items
   below 52rem and the primary CTA is the one that gives way first: at 1rem the
   `Free listing check` button shrank by a single pixel at 360 and wrapped to
   two lines, taking the nav from 44px to 65px tall. */
.nav__inner {
  width: min(72rem, 100% - var(--gut) * 2); margin-inline: auto;
  display: flex; align-items: center; gap: 0.5rem; min-height: 62px;
}
@media (min-width: 52rem) { .nav__inner { gap: 1rem; } }

.nav .wordmark {
  font-size: 1.15rem; margin-right: auto;
  display: inline-flex; align-items: center; min-height: 44px;
}
.nav__links { display: flex; gap: 1.75rem; }
/* min-width as well as min-height. A height floor does nothing for a short
   word: `Work` measured 33x44 when it was added to the nav. */
.nav__links a {
  font-family: var(--display); font-weight: 600; font-size: 0.9rem;
  color: var(--ink-soft); text-decoration: none; position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; min-width: 44px;
}
.nav__links a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 13px; height: 2px;
  background: var(--stamp); transform: scaleX(0); transform-origin: left;
  transition: transform 0.22s ease;
}
.nav__links a:hover { color: var(--ink); }
.nav__links a.is-active { color: var(--ink); }
.nav__links a.is-active::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) { .nav__links a::after { transition: none; } }

/* ⛔ The whole nav used to be `display: none` below 52rem, and `/work/` is
   linked from nowhere else on the home page, so the portfolio was unreachable
   on a phone. The desktop half of that fix shipped and the mobile half did not.

   Only the ROUTE link survives on a phone. The other three are hash anchors
   into a page the visitor is already scrolling, so they cost bar width and buy
   nothing. `/work/` is a separate document and is the answer to the question a
   prospect actually has, which is whether anything has been built. */
.nav__links a:not(.nav__route) { display: none; }
@media (min-width: 52rem) {
  .nav__links a:not(.nav__route) { display: inline-flex; }
}

/* ── Buttons ──────────────────────────────────────────────── */
.btn {
  display: inline-block; padding: 0.85rem 1.4rem; border-radius: 2px;
  background: var(--stamp); color: #fff; text-decoration: none;
  font-family: var(--display); font-size: 1rem; font-weight: 600;
  letter-spacing: -0.01em; border: 2px solid var(--stamp);
}
.btn:hover { background: var(--stamp-deep); border-color: var(--stamp-deep); }
/* M1, 2026-09-03. Buttons lift a pixel on hover and settle on press. The
   rungs and the who cards take the same lift, quieter, so the objects answer
   the cursor. Transform and shadow only, 160ms. */
.btn { transition: transform 160ms ease, box-shadow 160ms ease, background-color 160ms ease, border-color 160ms ease; }
.btn:hover { transform: translateY(-1px); box-shadow: 0 8px 16px -10px oklch(0.215 0.013 30 / 0.55); }
.btn:active { transform: translateY(0); box-shadow: none; transition-duration: 60ms; }
.rung, .who__points li { transition: transform 160ms ease, box-shadow 160ms ease; }
.rung:hover, .who__points li:hover { transform: translateY(-2px); box-shadow: 0 18px 32px -24px oklch(0.215 0.013 30 / 0.6); }
/* 44px, not 42. It measured 43 against a 44 target, and this audience taps
   one-handed on a phone. One pixel, but it is the primary CTA on every page. */
.btn--sm {
  padding: 0.5rem 0.95rem; font-size: 0.88rem;
  display: inline-flex; align-items: center; min-height: 44px;
}
/* The nav CTA reads `Get a free listing check` since 2026-09-03 (one verb for
   the free check everywhere, audit C3). It wrapped to two lines on Adrian's
   phone the same evening, at a width where Chrome emulation had shown 12px to
   spare, because the first version of this rule only applied below 24rem.
   Now: wherever the hash links are hidden (below 52rem) the button is compact,
   cannot shrink and cannot wrap. Measured 156px at 360 and 390. */
.nav .btn--sm { white-space: nowrap; flex-shrink: 0; }
@media (max-width: 51.99rem) {
  .nav .btn--sm { padding-inline: 0.65rem; font-size: 0.8rem; }
}
.btn--quiet { background: transparent; color: var(--ink); border-color: var(--hair); }
.btn--quiet:hover { background: transparent; border-color: var(--ink); color: var(--ink); }

/* ── Hero ─────────────────────────────────────────────────── */
.hero { position: relative; overflow: hidden;
        padding-block: clamp(2rem, 5vw, 3.5rem) var(--bandpad); }
.hero__inner { position: relative; z-index: 1; display: grid;
               gap: clamp(2.5rem, 6vw, 4rem); }
.lede { font-size: var(--step-1); color: var(--ink-soft);
        max-width: 46ch; line-height: 1.45; text-wrap: pretty; }
.hero__note { margin-top: 0.9rem; font-size: 0.9rem; color: var(--ink-soft); }
/* On a phone the two buttons stack and share one width. They used to stack at
   their own widths, so the pair had two right edges. Audit G11. */
.hero__cta { display: grid; gap: 0.75rem; margin-top: 1.75rem; }
.hero__cta .btn { text-align: center; }
@media (min-width: 46rem) {
  .hero__cta { display: flex; flex-wrap: wrap; }
}

/* ── Section heads ────────────────────────────────────────── */
/* Three head shapes on the page so no two adjacent sections open with the
   same object: a bare h2 (fix, who), h2 with a lede on the opposite edge
   (problems), and the centred h2 (contact). The story head is h2 plus the
   display-size opening line. Audit G5. */
.head--split { margin-bottom: 1.5rem; }
.head--split h2 { margin-bottom: 0.75rem; }
.head__lede {
  font-size: var(--step-1); line-height: 1.4; max-width: 40ch; margin: 0;
  color: var(--paper); opacity: 0.85; text-wrap: pretty;
}
@media (min-width: 46rem) {
  .head--split {
    display: grid; grid-template-columns: 1fr minmax(0, 36ch);
    gap: 2rem 4rem; align-items: end; margin-bottom: 2.25rem;
  }
  .head--split h2 { margin-bottom: 0; }
  .head__lede { max-width: 36ch; }
}

/* ── Map cards ────────────────────────────────────────────── */
.mapcard {
  position: relative; margin: 0; aspect-ratio: 4 / 3;
  background: var(--surface); border: 1px solid var(--hair);
  border-radius: 3px; overflow: hidden;
  box-shadow: 0 18px 40px -30px oklch(0.215 0.013 30 / 0.55);
}
.mapcard__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.mapcard__pin { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -100%); }
.mapcard__pin::after {
  content: ""; position: absolute; left: 50%; bottom: -5px;
  width: 16px; height: 5px; border-radius: 50%;
  background: oklch(0.215 0.013 30 / 0.28); transform: translateX(-50%);
}
.mapcard__pulse {
  position: absolute; left: 50%; bottom: -6px; width: 15px; height: 15px;
  margin-left: -7.5px; border-radius: 50%; border: 2px solid var(--stamp); opacity: 0;
}
.mapcard__cap {
  position: absolute; left: 50%; top: 46%; margin-top: 0.9rem;
  transform: translateX(-50%); font-family: var(--display); font-weight: 600;
  font-size: 0.78rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--ink-soft); white-space: nowrap;
}
@media (prefers-reduced-motion: no-preference) {
  .js .mapcard__pin { animation: pindrop 0.7s cubic-bezier(0.36, 0, 0.66, -0.2) both; }
  .js .mapcard__pin::after { animation: pinshadow 0.7s ease-out both; }
  .js .mapcard__cap { animation: fadeup 0.4s 0.62s ease-out both; }
  .js .mapcard__pulse { animation: ping 2.8s 1.1s ease-out infinite; }
}
@keyframes pindrop { from { transform: translate(-50%, -260%); }
                     to   { transform: translate(-50%, -100%); } }
@keyframes pinshadow { from { opacity: 0; transform: translateX(-50%) scaleX(2.4); }
                       to   { opacity: 1; transform: translateX(-50%) scaleX(1); } }
@keyframes fadeup { from { opacity: 0; transform: translateX(-50%) translateY(4px); }
                    to   { opacity: 1; transform: translateX(-50%) translateY(0); } }
@keyframes ping { 0% { transform: scale(0.5); opacity: 0.7; }
                  70%,100% { transform: scale(2.6); opacity: 0; } }

/* ── Bands ────────────────────────────────────────────────── */
.band { padding-block: var(--bandpad); }
.band--ink { background: var(--ink); color: var(--paper); }
.band--ink a { color: var(--stamp-lift); }
.band--tint { background: var(--paper-2); }
.band--contact { background: var(--ink); color: var(--paper); text-align: center; }

/* ── Issue list ───────────────────────────────────────────── */
.issues {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 0;
  font-family: var(--display); font-weight: 600; font-size: var(--step-1);
  letter-spacing: -0.015em;
}
.issues li {
  padding: 0.85rem 0 0.85rem 2rem; position: relative;
  border-bottom: 1px solid oklch(1 0 0 / 0.13);
}
/* A ringed dot, the seal reduced to its smallest honest form.
   Painted as ONE radial-gradient rather than a bordered box plus a second
   positioned dot. Two elements were concentric on paper but each rounded to
   the device pixel grid independently, so at 1x the inner dot snapped off
   centre. One shape cannot disagree with itself, and integer radii keep the
   edges crisp at any DPR.
   Vertically: padding-top, plus half a line box, minus half the mark. Anchors
   to the first line so wrapped items on a phone stay aligned. */
.issues li::before {
  content: ""; position: absolute; left: 0;
  top: calc(0.85rem + 0.8em - 6px);
  width: 12px; height: 12px;
  background: radial-gradient(circle at 50% 50%,
    var(--stamp-lift) 0 2px,
    transparent 2px 4px,
    var(--stamp-lift) 4px 6px,
    transparent 6px);
}

/* ── Offer ────────────────────────────────────────────────── */
.offer { display: grid; gap: 2.5rem; align-items: start; }
.offer__price {
  background: var(--surface); border: 1px solid var(--hair);
  border-top: 4px solid var(--stamp); border-radius: 3px; padding: 1.75rem;
}
.offer__num {
  display: block; font-family: var(--display); font-weight: 800;
  font-size: var(--step-4); line-height: 1; color: var(--stamp-deep);
  letter-spacing: -0.03em;
}
.offer__unit {
  display: block; font-family: var(--display); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.09em; font-size: 0.78rem;
  color: var(--ink-soft); margin-top: 0.45rem;
}
.offer__note { display: block; margin-top: 1rem; color: var(--ink-soft); font-size: 0.95rem; }
.offer__cta { margin-top: 1.4rem; }
/* The list takes the column it is given. It was capped at 48ch, which left the
   right third of the wrap empty at desktop and put every object in this
   section on the left edge. Audit G4. */
.offer__list { margin: 0; padding: 0; list-style: none; counter-reset: fix;
               display: grid; gap: 0; max-width: 58ch; }
.offer__list li {
  counter-increment: fix; position: relative;
  padding: 0.8rem 0 0.8rem 2.6rem; border-bottom: 1px solid var(--hair);
}
.offer__list li:first-child { border-top: 1px solid var(--hair); }
/* Two-part item, Schlitz pass 2026-09-04. `what` is the fix, `why` is the
   mechanism underneath it. Deliberately the same treatment as rung__name and
   rung__note below, because this is the same object at a different scale and
   the page should not carry two ways of saying "heading, then the quiet line
   under it". D13: better execution, no new devices.

   `display: block` on both, not a grid: the item is one column at every
   breakpoint, and the ::before counter is absolutely positioned so it does not
   participate in flow either way. */
.offer__what { display: block; }
.offer__why  { display: block; margin-top: 0.3rem;
               color: var(--ink-soft); font-size: 0.95rem; }
.offer__list li::before {
  content: counter(fix); position: absolute; left: 0; top: 0.85rem;
  width: 1.6rem; height: 1.6rem; border-radius: 50%;
  background: var(--stamp); color: #fff;
  font-family: var(--display); font-weight: 800; font-size: 0.82rem;
  display: grid; place-items: center;
}

/* ── The ladder ───────────────────────────────────────────── */
/* Four products at four prices, one line each, in the order a buyer meets
   them. Bounded objects of equal rank on the surface colour, the same object
   the $500 card already is, so this extends a device the page has rather than
   adding one. The rung the section is about carries the card's stamp rule and
   nothing else, which is what ties the two together. Not a tier table: no
   columns of features, no Bronze Silver Gold, PRODUCT.md holds.

   It replaced two <li> bullets set in the disclaimer's colour underneath the
   disclaimer, which was the one direct piece of evidence for the amateur read.
   O2, 2026-09-03, audit G1. */
.ladder {
  list-style: none; margin: 2.5rem 0 0; padding: 0;
  display: grid; gap: 0.75rem;
}
.rung {
  display: grid; grid-template-columns: 1fr auto; column-gap: 1rem; align-items: baseline;
  padding: 1rem 1.25rem 1.1rem;
  background: var(--surface); border: 1px solid var(--hair); border-radius: 3px;
}
.rung--here { border-top: 4px solid var(--stamp); padding-top: calc(1rem - 3px); }
.rung__name { font-family: var(--display); font-weight: 600; font-size: 1rem; color: var(--ink); }
.rung__price {
  font-family: var(--display); font-weight: 800; font-size: var(--step-1);
  letter-spacing: -0.02em; color: var(--stamp-deep); line-height: 1; white-space: nowrap;
  justify-self: end;
}
.rung__note { grid-column: 1 / -1; color: var(--ink-soft); font-size: 0.95rem; margin-top: 0.3rem; }
@media (min-width: 46rem) {
  .ladder { grid-template-columns: repeat(2, 1fr); gap: 1rem; }
}
@media (min-width: 60rem) {
  .ladder { grid-template-columns: repeat(4, 1fr); }
  .rung { grid-template-columns: 1fr; padding: 1.25rem 1.4rem 1.35rem; align-content: start; }
  .rung--here { padding-top: calc(1.25rem - 3px); }
  .rung__price { justify-self: start; margin-top: 0.6rem; font-size: var(--step-2); }
  .rung__note { margin-top: 0.55rem; }
}

/* The honest sentence, after the prices and small. It used to sit above them
   with its own hairline, 2.5rem below the list's last hairline, which drew two
   parallel rules with an 80px void between. One rule now, and it belongs to
   the list. Audit G2 and G3. */
.fineprint { margin: 2rem 0 0; color: var(--ink-soft); max-width: 54ch; font-size: 0.95rem; }
[hidden] { display: none !important; }

/* ── Story ────────────────────────────────────────────────── */
.story { display: grid; gap: 2.5rem; align-items: center; }
.story__copy p { max-width: 46ch; }
.story__big {
  font-family: var(--display); font-weight: 600; font-size: var(--step-2);
  line-height: 1.25; letter-spacing: -0.02em; color: var(--ink);
}
.story__map {
  position: relative; margin: 0; aspect-ratio: 3 / 4; max-height: 27rem;
  background: var(--surface); border: 1px solid var(--hair);
  border-radius: 3px; overflow: hidden;
}
.story__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.story__ghost {
  position: absolute; top: 15.5%; left: 41%;
  width: 0.8rem; height: 0.8rem; border-radius: 50%;
  border: 2px dashed var(--ink-soft); opacity: 0.6;
}
.story__pinlabel {
  position: absolute; font-family: var(--display); font-size: 0.76rem;
  font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  white-space: nowrap; color: var(--ink);
}
.story__pinlabel--wrong { top: 13.5%; left: calc(41% + 1.5rem); color: var(--ink-soft); }
.story__pinlabel--right { top: 74%; left: calc(41% + 1.6rem); color: var(--stamp-deep); }
.story__travel {
  position: absolute; top: 74%; left: 41%;
  transform: translate(-50%, -100%); line-height: 0;
}
.story--scrub .story__travel {
  top: calc(16% + 58% * var(--p, 0));
  left: calc(41% + 6% * var(--bulge, 0));
}
.story--scrub .story__pinlabel--right { opacity: var(--landed, 0); }

/* ── Who ──────────────────────────────────────────────────── */
/* On paper as of 2026-09-03 (O2). The photo and the three cards are the
   objects; the band colour no longer has to be. Audit G6. */
.who__intro { margin-bottom: 2.75rem; }
.who__photo { margin: 0 0 1.5rem; width: 13rem; max-width: 100%; }
.who__photo img {
  display: block; width: 100%; height: auto; border-radius: 3px;
  border: 1px solid var(--hair);
  box-shadow: 0 18px 40px -30px oklch(0.215 0.013 30 / 0.55);
}
.who__lead {
  font-family: var(--display); font-weight: 600; font-size: var(--step-2);
  letter-spacing: -0.02em; line-height: 1.25; max-width: 26ch; margin-bottom: 0;
}
@media (min-width: 52rem) {
  .who__intro { display: grid; grid-template-columns: 20rem 1fr; gap: 3rem; align-items: center; }
  .who__photo { width: 100%; margin: 0; }
}
.who__points { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.who__points li {
  position: relative; padding: 1.5rem 1.4rem 1.6rem;
  background: var(--surface); border: 1px solid var(--hair); border-radius: 3px;
}
.who__mark { display: block; margin-bottom: 0.9rem; color: var(--stamp); }
.who__points h3 { font-size: 1.06rem; font-weight: 600; margin: 0 0 0.45rem; color: var(--ink); }
.who__points p { margin: 0; font-size: 0.97rem; color: var(--ink-soft); }
@media (min-width: 52rem) { .who__points { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; } }

/* ── Contact ──────────────────────────────────────────────── */
.contact__lede { max-width: 44ch; margin-inline: auto; opacity: 0.9; }
.contact__mail { font-family: var(--display); font-size: var(--step-2);
                 font-weight: 800; letter-spacing: -0.025em; margin-top: 2rem; }
/* inline-block so the link takes a real tap height. As pure inline text it
   measured under 40px on a phone, which is the one place it matters most. */
.contact__mail a {
  color: var(--stamp-lift); text-underline-offset: 5px;
  display: inline-block; padding-block: 0.35rem;
}
/* A2P 10DLC opt-in disclosure. Sits directly under the published business line
   because carrier review looks for the consent experience at the point the
   number is presented. Deliberately quiet — it is a legal requirement, not a
   sales line — but it must stay readable, so opacity floors at 0.75. */
.contact__sms {
  max-width: 52ch; margin-inline: auto; margin-top: 1.25rem;
  font-size: 0.9rem; line-height: 1.6; opacity: 0.75;
}
.contact__sms a { color: inherit; text-underline-offset: 3px; }

.contact__seal { display: flex; justify-content: center; margin-top: 3rem; }

/* ── Reveal and stamp ─────────────────────────────────────── */
/* M2 and M4, 2026-09-03. One block reveal: bounded objects and list items rise
   12px and fade in as they enter, once, 60ms apart inside a group. The seal
   comes in as a stamp: slightly large and turned, then pressed flat.

   Motion contract holds. Nothing is hidden unless `reveal-ready` is on the
   root, and main.js sets that only when IntersectionObserver exists and
   reduced motion is off. No JS, old browser, or reduced motion: everything
   renders in place. */
/* The individual `translate`, `scale` and `rotate` properties, not `transform`,
   so the hover lift above keeps `transform` to itself and the two compose. */
.reveal-ready .reveal { opacity: 0; translate: 0 12px; }
.reveal-ready .reveal.is-in {
  opacity: 1; translate: 0 0;
  transition: opacity 0.45s ease-out, translate 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: var(--d, 0ms);
}
.reveal-ready .reveal--stamp { translate: 0 0; scale: 1.12; rotate: -4deg; }
.reveal-ready .reveal--stamp.is-in {
  scale: 1; rotate: 0deg;
  transition: opacity 0.3s ease-out, scale 0.35s cubic-bezier(0.2, 0.9, 0.3, 1), rotate 0.35s cubic-bezier(0.2, 0.9, 0.3, 1);
}
/* BP2 pages, 2026-09-12. Hero copy rises in reading order, work cards lift
   under the cursor, link underlines drop a step. `.js` is set inline in
   <head> before first paint, so nothing flashes from visible to hidden. */
@media (prefers-reduced-motion: no-preference) {
  .js .bp-hero__copy > * { animation: rise .55s cubic-bezier(.2,.7,.2,1) both; }
  .js .bp-hero__copy > :nth-child(2) { animation-delay: 90ms; }
  .js .bp-hero__copy > :nth-child(3) { animation-delay: 180ms; }
  .js .bp-hero__grid > :not(.bp-hero__copy) { animation: rise .6s cubic-bezier(.2,.7,.2,1) 260ms both; }
  .js .bp-reading-hero > * { animation: rise .55s cubic-bezier(.2,.7,.2,1) both; }
  .js .bp-reading-hero > :nth-child(2) { animation-delay: 90ms; }
  .js .bp-reading-hero > :nth-child(3) { animation-delay: 180ms; }
  .js .bp-reading-hero > :nth-child(4) { animation-delay: 270ms; }
  .bp-work img { transition: transform .35s cubic-bezier(.2,.7,.2,1), box-shadow .35s ease; }
  .bp-work:hover img { transform: translateY(-4px); box-shadow: 0 22px 36px -26px oklch(0.215 0.013 30 / 0.6); }
  .bp-link, .bp-work h3 { transition: text-underline-offset .18s ease, color .18s ease; }
  .bp-link:hover, .bp-work:hover h3 { text-underline-offset: .34em; }
}
.bp-link { text-underline-offset: .2em; }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .reveal-ready .reveal, .reveal-ready .reveal--stamp { opacity: 1; translate: none; scale: none; rotate: none; transition: none; }
  .btn, .rung, .who__points li, .nav { transition: none; }
  .btn:hover, .rung:hover, .who__points li:hover { transform: none; }
}

/* ── Footer ───────────────────────────────────────────────── */
.foot { padding-block: 2.25rem; font-size: 0.88rem; color: var(--ink-soft);
        border-top: 1px solid var(--hair); }
.foot__inner { display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem;
               align-items: center; justify-content: space-between; }
.foot p { margin: 0; }
.foot__small { color: var(--ink-soft); }
.foot__note { font-size: 0.8rem; color: var(--ink-soft); margin-top: 0.9rem; }

/* ── Grows up from phone ──────────────────────────────────── */
@media (min-width: 46rem) {
  .hero__inner { grid-template-columns: 1.15fr 0.85fr; align-items: center; }
  .issues { grid-template-columns: 1fr 1fr; column-gap: 3rem; }
  .offer { grid-template-columns: 20rem 1fr; gap: 3.5rem; }
  .story { grid-template-columns: 1fr 0.7fr; gap: 3.5rem; }

  /* Text inside a container drops one step once there is room. At 17px the
     list items, the card copy and the fineprint read as body copy floating on
     the page; a step down inside a bounded object is what makes the object
     read as the unit. Open prose (the story paragraphs) stays at body size.
     Phone is untouched. Audit G7. */
  .offer__list li, .who__points p, .rung__note, .offer__note { font-size: 0.95rem; }
  .fineprint { font-size: 0.92rem; }
}
