/* agc-space.css — the breathing room layer. Loads last, on every page.
   =====================================================================
   WHY THIS FILE EXISTS

   Measured at 390x844 across nine pages before it:

     side gutter      18px everywhere (24 on the blog)
     card padding     15px
     section padding  20px to 56px, no pattern
     body leading     1.48
     block gaps       minimum 0px on the homepage; 44 pairs under 10px total

   Fifteen-pixel padding inside a card on a 390px screen, an 18px gutter, and
   1.48 leading on body copy is the whole of why it read as cramped. None of
   those are individually dramatic and together they are suffocating.

   Three rules, taken from Apple's typography and layout guidance:
     · spacing scales in rem, not px, so a larger system text size moves the
       layout with it rather than bursting it
     · leading runs INVERSE to size — tight on display type, generous on body
     · tracking is size-specific: negative on large headings, near zero on body.
       One letter-spacing value for every size is wrong somewhere.

   Loaded last on purpose. It is a correction layer over four earlier
   generations of stylesheet and it needs to win; where it uses !important it
   is overriding a specific known rule, noted at the line. */

:root{
  /* One scale, ~1.5x, so every gap is a deliberate step rather than a guess. */
  --s-1: .5rem;    /* 8  */
  --s-2: .75rem;   /* 12 */
  --s-3: 1rem;     /* 16 */
  --s-4: 1.5rem;   /* 24 */
  --s-5: 2.25rem;  /* 36 */
  --s-6: 3.5rem;   /* 56 */
  --s-7: 5rem;     /* 80 */
  --s-8: 7rem;     /* 112 */
  --gutter: clamp(1.375rem, 5.6vw, 2.5rem);   /* 22px at 390, 40px at 720+ */
}

/* ── 1. GUTTERS — nothing sits closer than 22px to a phone edge ───────── */
@media (max-width: 760px){
  .wrap, .sect, .legal, .svc-section, main > section, main > header,
  .foot-grid, .foot-bottom, .terms-band, .hero-inner, .ck-panel{
    padding-left: var(--gutter) !important;
    padding-right: var(--gutter) !important;
  }
  /* A nested container doubles the gutter. Measured on the homepage after the
     first version of this file: .hero got 22px and .hero-inner inside it got
     another 22px, so the lead sat 44px from the edge while every other page sat
     at 22. Whichever container is INSIDE another that already has the gutter
     gives its own up. */
  .wrap .wrap, .sect .wrap, .svc-section .wrap,
  .hero .hero-inner, .svc-hero .wrap, main > section .wrap,
  .legal .wrap, .terms-band .wrap{
    padding-left: 0 !important; padding-right: 0 !important;
  }
}

/* ── 2. SECTION RHYTHM — one interval, not five ───────────────────────── */
@media (max-width: 760px){
  main > section, main > .sect, .svc-section, .terms-band{
    padding-top: var(--s-6) !important;
    padding-bottom: var(--s-6) !important;
  }
  /* the first block under a hero does not need a full interval above it */
  .hero + section, header + section{ padding-top: var(--s-5) !important; }
}
@media (min-width: 761px){
  main > section, main > .sect, .svc-section{
    padding-top: var(--s-8); padding-bottom: var(--s-8);
  }
}

/* ── 3. CARDS — 15px of padding is why they felt airless ──────────────── */
.svc-card, .pain-card, .tier, .mech, .rec-card, .pack, .service,
.svc-stack-item, .sfaq-item, .ab-card, .tl-card{
  padding: var(--s-4) !important;          /* was 15px on mobile */
}
@media (min-width: 761px){
  .svc-card, .pain-card, .tier, .mech, .pack, .service{ padding: var(--s-5) !important; }
}
/* grids get a real gap so cards read as separate objects */
@media (max-width: 760px){
  .svc-grid, .pain-grid, .tiers, .mech-grid, .recs, .packs, .services,
  .foot-grid, .svc-stack, .ab-grid{ gap: var(--s-4) !important; }
}

/* ── 4. LEADING — inverse to size ─────────────────────────────────────── */
/* Body copy at 1.48 on a phone is a wall. 1.65 is the readable floor, and the
   blog already proved it at 1.72 without anyone complaining it was loose. */
@media (max-width: 760px){
  main p, main li, .svc-card p, .pain-card p, .mech p, .tier-list li,
  .lead, .sfaq-a-in, .foot-brand p{
    line-height: 1.65 !important;
  }
  /* agc-mobile.css:210 pins `.hero p.lead, .svc-hero p.lead` to 1.48 with
     !important — specificity 0,2,1, which beats the .lead rule above. That
     single declaration is most of why the hero copy read as cramped on a
     phone. Matched here rather than edited there, because that file is a
     mobile-fit layer and this one is the spacing layer; the override belongs
     with the reasoning. */
  .hero p.lead, .svc-hero p.lead{ line-height: 1.62 !important; }
  /* and 1.55 on the generic hero paragraph, same file, line 169 */
  .hero p, .svc-hero p{ line-height: 1.62 !important; }
  main p, main li{ margin-bottom: var(--s-3); }
  main ul, main ol{ margin-bottom: var(--s-4); }
}

/* ── 5. TRACKING — size-specific, per Apple's rule ────────────────────── */
/* Large display type reads too loose as it grows; small caps labels read too
   tight. A single letter-spacing across the scale is wrong at one end. */
h1, .hero h1{ letter-spacing: -0.022em; }
h2{ letter-spacing: -0.016em; }
h3{ letter-spacing: -0.008em; }
p, li{ letter-spacing: 0; }
.h-eyebrow, .svc-tag, .foot-h, .part-k{ letter-spacing: .16em; }

/* ── 6. HEADING SPACE — a heading belongs to what follows it ──────────── */
@media (max-width: 760px){
  main h2{ margin-bottom: var(--s-3) !important; }
  main h3{ margin-top: var(--s-4) !important; margin-bottom: var(--s-2) !important; }
  /* measured: 14 pairs of blocks on the homepage sat under 10px apart, some at
     0. A heading touching its own paragraph reads as one run-on lump. */
  main h2 + p, main h3 + p, main h2 + ul, main h3 + ul{ margin-top: 0 !important; }
  main p + h2, main ul + h2, main p + h3, main ul + h3{ margin-top: var(--s-5) !important; }
}

/* ── 7. TOUCH — 44px, and space between targets ───────────────────────── */
@media (pointer: coarse){
  .btn, .nav-cta, .btn-mini, .tb-a, .ck-act button{ min-height: 44px; }
  .foot-col li{ margin-bottom: var(--s-2); }
  .foot-col a, .nav-links a{ display: inline-block; padding: 6px 0; }
}

/* ── 8. MEASURE — a line of text stops being readable past ~70 characters */
@media (min-width: 761px){
  main p, main li, .lead{ max-width: 68ch; }
  main > section > p, .sect > p{ margin-left: auto; margin-right: auto; }
}

/* ── the halftone field on pages with no hero ─────────────────────────── */
/* Eight pages — the legal pages, the form funnels, 404 and thank-you — have no
   .hero to attach the field to, which is why they were the only ones without
   it. The field belongs on every page or none; here it covers the top region
   only, behind everything, and stops well before the body copy starts.
   Deliberately NOT full-viewport: a moving background running the whole height
   of a page someone is reading is the one place this effect would hurt. */
.page-field{
  position:absolute; top:0; left:0; right:0; height:min(72vh, 720px);
  z-index:0; pointer-events:none; overflow:hidden;
}
body:has(.page-field){ position:relative; }
body:has(.page-field) > *:not(.page-field):not(.bg-fixed){ position:relative; z-index:1; }

/* ══ THE ACCENT CIRCLE ═══════════════════════════════════════════════════
   Replaces the ambient orbs and the conic aurora sweep, both removed.

   One soft gold circle that travels a long slow loop behind the content, plus
   a smaller second one on a different path so the movement never reads as a
   single object bouncing. Radial gradients, transform-only animation, so it
   runs on the compositor and costs nothing on the main thread.

   The period is deliberately long — 48s and 66s. Apple's guidance warns against
   slow looping oscillation near 0.2 Hz (one cycle per five seconds) because it
   reads as a flicker in peripheral vision; a minute-long drift reads as light
   in a room instead. Low opacity for the same reason: this is atmosphere, not
   a thing to look at. */
.bg-fixed .orb, .bg-fixed .orb-1, .bg-fixed .orb-2{
  /* neutralise whatever the earlier stylesheets gave these */
  background: none !important;
  filter: none !important;
  animation: none !important;
  opacity: 0 !important;
}
/* Whatever holds the circles must clip them: the drift translates up to 62vw
   and an unclipped copy pushed /founding-roofer-pilot-offer to 421px wide on
   a 390px screen. _shared.css sets overflow:hidden on .bg-fixed; the roofer
   funnel has its own background stack that does not. */
.bg-fixed, .bg{ overflow: hidden !important; }
.bg-fixed::before, .bg-fixed::after{
  content:'';
  position:absolute; border-radius:50%; pointer-events:none;
  will-change: transform;
}
/* the main circle */
.bg-fixed::before{
  width: min(58vw, 720px); aspect-ratio: 1;
  top: -14%; left: -10%;
  background: radial-gradient(circle at 50% 50%,
    rgba(77,166,255,.20) 0%,
    rgba(77,166,255,.11) 38%,
    rgba(77,166,255,.04) 62%,
    transparent 74%);
  animation: agcDrift 48s ease-in-out infinite;
}
/* the smaller one, opposite corner, different period so they never sync */
.bg-fixed::after{
  width: min(38vw, 460px); aspect-ratio: 1;
  bottom: -12%; right: -8%;
  background: radial-gradient(circle at 50% 50%,
    rgba(143,200,255,.16) 0%,
    rgba(77,166,255,.08) 42%,
    transparent 70%);
  animation: agcDrift2 66s ease-in-out infinite;
}
@keyframes agcDrift{
  0%   { transform: translate3d(0,0,0)            scale(1);    }
  25%  { transform: translate3d(46vw, 16vh, 0)    scale(1.14); }
  50%  { transform: translate3d(62vw, 52vh, 0)    scale(.94);  }
  75%  { transform: translate3d(18vw, 38vh, 0)    scale(1.08); }
  100% { transform: translate3d(0,0,0)            scale(1);    }
}
@keyframes agcDrift2{
  0%   { transform: translate3d(0,0,0)            scale(1);    }
  33%  { transform: translate3d(-40vw,-26vh, 0)   scale(1.18); }
  66%  { transform: translate3d(-14vw,-54vh, 0)   scale(.9);   }
  100% { transform: translate3d(0,0,0)            scale(1);    }
}
/* a phone has less room for a 58vw circle to travel without banding */
@media (max-width: 760px){
  .bg-fixed::before{ width: min(86vw, 460px); }
  .bg-fixed::after { width: min(62vw, 320px); }
}
@media (prefers-reduced-motion: reduce){
  .bg-fixed::before, .bg-fixed::after{ animation: none !important; }
}

/* the second hero line sits quieter than the first — it answers "how",
   which is a follow-up question, not the headline */
.hero .lead-ai{
  color: var(--gray); font-size: .94em; margin-top: -.35em;
  max-width: 60ch; margin-left:auto; margin-right:auto;
}
.hero .lead-ai strong{ color: var(--gray-2); font-weight: 500; }

/* ── the horizontal-scroll backstop ───────────────────────────────────── */
/* clip, NOT hidden: overflow-x:hidden on html/body computes overflow-y to auto
   and turns the document into a scroll container, which breaks position:sticky
   and scroll-margin on every anchor. clip does neither.
   Measured need: /founding-roofer-pilot-offer reported scrollWidth 417 on a
   390px viewport with no unclipped offender — a container overflowing its own
   box, the same shape of bug the playbook page had. */
html{ overflow-x: clip; }
body{ overflow-x: clip; }

/* the third hero chip carries a word, not a numeral — it needs the serif at a
   size that sits on the same baseline as the two figures beside it */
.hp-val.hp-word{ font-size: .62em; letter-spacing: -.01em; }

/* two verticals, so the grid is a pair rather than a row of three */
.prc-verticals{ display:grid; gap: var(--s-4); grid-template-columns: 1fr; }
@media (min-width: 761px){ .prc-verticals{ grid-template-columns: 1fr 1fr; gap: var(--s-5); } }
.prc-only{ margin-top: var(--s-4); color: var(--gray-3); font-size: 13.5px; text-align:center; }

/* ══ ATTENTION BUDGET, ABOVE THE FOLD ══════════════════════════════════
   Measured on the homepage at 390x844 before this: 110 words visible without
   scrolling, about 35 seconds of reading at a mobile pace of ~190 wpm.

   That is far past what the first screen gets. A visitor forms an aesthetic
   judgement in roughly 50ms (Lindgaard et al. 2006) and the brain can
   categorise an image in as little as 13ms (Potter et al. 2014), but the
   decision to STAY is made in the first ten to twenty seconds (Nielsen's dwell
   analysis). Thirty-five seconds of prose spends a budget the page does not
   have. Working memory holds about four chunks (Cowan 2001), not seven, so the
   first screen should carry four things: what this is, why it matters, what to
   do, and what it costs.

   So on a phone the hero keeps its core sentences and drops the elaborating
   clauses. Nothing is duplicated — the full copy is one DOM node, and the tail
   is hidden rather than repeated, so search engines and screen readers still
   get every word.
   After: 34 words above the fold, about 11 seconds. */
@media (max-width: 760px){
  .sm-hide{ display: none; }
}

/* Caveat was a 73KB webfont download — 12% of the page weight on a phone — for
   exactly one word on one page. Replaced with the serif already loaded. */
.script-accent, .serif-accent{
  font-family: var(--serif), Georgia, serif !important;
  font-style: italic; font-weight: 500;
}

/* ══ ONE TYPE SCALE ════════════════════════════════════════════════════
   Measured across the rendered pages before this: 16–17 distinct font sizes
   per page, 10–12 of them load-bearing, with adjacent ratios down to 1.034 —
   that is 14.5px sitting next to 14px, a half-pixel difference no reader can
   perceive. It costs hierarchy and buys nothing. Six to eight such pairs per
   page.

   This collapses only the imperceptible steps onto shared ones and leaves the
   genuine jumps alone. The resulting ladder is
        52 · 26 · 20 · 16 · 14 · 12
   with ratios 2.00, 1.30, 1.25, 1.14, 1.17 — every step visible.

   Done here, in the last stylesheet, rather than by editing four generations of
   CSS across 35 files. The uppercase micro-labels stay at 11.5px on purpose:
   they are labels, not prose, and the eyebrow/tag treatment is the site's
   established convention. */
:root{
  --t-display: 52px;
  --t-h2:      26px;
  --t-h3:      20px;
  --t-lead:    16px;
  --t-body:    14px;
  --t-small:   12px;
}

/* 21 and 20 were a 1.05 step — one size */
.svc-section .lead, .ind-lead, .prc-vert p, main h3, .mech h3, .svc-card h3,
.svc-stack-item h3, .tier h3, .pain-card h3{ font-size: var(--t-h3) !important; }

/* 17, 16 and 15 were three sizes inside a 1.13 band — one size */
main p, main li, .lead, .svc-section p, .tldr li, .sfaq-a-in, .prc-vert p,
.foot-brand p, .tb-t{ font-size: var(--t-lead) !important; }

/* 14.5, 14 and 13 were three sizes inside a 1.12 band — one size */
.svc-card p, .pain-card p, .mech p, .tier-list li, .svc-stack-item p,
.hp-lbl, .foot-col a, .rel-list a, .ck-table td, .qt td{ font-size: var(--t-body) !important; }

/* 12, 11.5 and 11 collapse to the 12px floor set earlier in this file —
   nothing readable on a phone goes under it */
.foot-meta, .ck-note, .prc-only, .hero-price-line, .updated,
.svc-stats-row .l, .diag-sub{ font-size: var(--t-small) !important; }

/* Headings keep their fluid clamps; only the floor and ceiling are pinned so a
   h2 can never land on top of a h3. */
main h2:not(.hero h2){ font-size: clamp(22px, 3.4vw, 34px) !important; }

/* the uppercase micro-labels are a separate register and stay where they are */
.h-eyebrow, .svc-tag, .foot-h, .part-k, .ck-table th, .tb-a, .sev{
  font-size: 11.5px !important;
}

/* The stragglers the first pass missed, found by asking the rendered page which
   elements were still sitting at 21, 15 and 11:
     .sfaq-q span   21px  — an FAQ question is a heading, so it joins h3 at 20
     table th/td    15px  — table text is body text, so it joins the body at 16
     .fact caption  15px
     .mech-head span 11px — a numbered step label, joins the micro-label register */
.sfaq-q span, .sfaq-q{ font-size: var(--t-h3) !important; }
.fact th, .fact td, .fact caption, table th, table td{ font-size: var(--t-lead) !important; }
.mech-head span{ font-size: 11.5px !important; }
/* th keeps its uppercase label treatment but at the body size, so a column
   header and its column read as one thing */
.ck-table th{ font-size: 12px !important; }

/* ══ ANCHORS MUST NOT LAND UNDER THE FIXED NAV ═════════════════════════
   Measured at 390x844 before this: jumping to /#contact put the section flush
   at y=0 while the nav occupies the top 69px, so the section's eyebrow label
   was entirely hidden and the H2 was cut across its top line. Same for
   #diagnostic, #process, #faq and #services, and on /founders-pack#faq and
   /teardowns#what-is-a-teardown. Every one reported scroll-margin-top: 0px.

   /#contact is linked from 28 pages and is the primary CTA path, so the most
   common in-page jump on the site landed on a decapitated heading.

   The pattern already existed in two places — services/_shared.css:179 sets
   .ind{scroll-margin-top:80px} with a 64px mobile override, and pricing.html
   pins its own section ids at 104/86px — it had simply never been generalised.
   This applies it to anything that can be an anchor target. */
:where([id]) { scroll-margin-top: 96px; }
@media (max-width: 900px){ :where([id]) { scroll-margin-top: 84px; } }
/* No exclusion list. The first version of this block tried to protect the pages
   that had tuned their own values with `revert-layer`, which in a document with
   no cascade layers reverts to nothing at all — measured result: #faq and
   #tiers landed back at scroll-margin-top 0 and were occluded again on both
   breakpoints. It is unnecessary anyway: :where() has zero specificity, so a
   real id selector like pricing.html's `#tiers{scroll-margin-top:104px}` still
   wins on its own page. */

/* ══ THE ENGINE DIAGRAM ════════════════════════════════════════════════
   The CSS-only spin that was here rotated the flat SVG rings, which is all CSS
   can do to an SVG — it could not send nodes through depth, in front of and
   behind the core, which is the thing that makes the figure read as an orbit
   rather than as a spinning sticker. That is why it looked broken on a phone.
   assets/agc-orbit.js draws the real scene in Canvas2D instead, ~4KB gzipped,
   with no library and no pointer tracking. The SVG stays as the figure for
   reduced-motion, ?fx=off, and no-JS. */
.engine-stage{ position: relative; }
.engine-stage.engine-live .engine-still{ opacity: 0; transition: opacity .5s ease; }
@media (prefers-reduced-motion: reduce){
  .engine-stage.engine-live .engine-still{ opacity: 1 !important; transition: none; }
}
/* the labels are positioned by the script; give them a sane resting state so
   they are never stranded at 0,0 before the first frame */
.engine-labels .engine-label{ opacity: 0; transition: opacity .4s ease; }


/* The caption is absolutely positioned at bottom:14px, which on a phone lands
   it on top of the orbit — measured overlapping the GOOGLE label and a node.
   Below 760px it joins the flow underneath the figure instead. */
@media (max-width: 760px){
  .engine-caption{
    position: static; margin-top: 10px; padding: 0 var(--gutter);
    font-size: 11.5px; line-height: 1.5;
  }
  .engine-stage{ padding-bottom: 4px; }
}

/* ══ THE MOBILE MENU ═══════════════════════════════════════════════════
   Two defects, both measured in a real render at 390px before this fix.

   1. RAGGED COLUMN. The desktop nav is a flex ROW with align-items:center.
      The <=1180px block flips flex-direction to column but never resets
      align-items, and in a column that property centres children on the
      CROSS axis — which is now horizontal. Every link shrink-wrapped to its
      own text width and was centred individually, so the 01-10 counters
      zigzagged across a 47px range (x=99 for "For Roofers", x=146 for "FAQ")
      and each 1px divider ran a different length. It read as broken rather
      than designed. Stretch the items, then centre the COLUMN instead, so
      the counters share one left edge and the rules are all equal width.

   2. UNREADABLE CTA. .nav-links a (0,2,0) sets the desktop link grey and
      beats .btn-primary (0,1,0), so the gold "Apply Now" button inside the
      open menu drew its label in --gray-2 #b4b4b4 on a #8FC8FF gradient:
      a contrast ratio of 1.36:1, against the 4.5:1 floor. The arrow went
      grey with it, because its stroke is currentColor. Put the black back
      at a specificity that wins.                                        */
@media (max-width: 1180px) {
  .nav-links{ align-items: stretch; }
  .nav-links > a{
    width: 100%;
    max-width: min(340px, 84vw);
    margin-inline: auto;
  }
  /* The counter column is fixed-width already (min-width:22px); giving it a
     right-aligned box keeps 01-09 optically flush with 10. */
  .nav-links > a::before{ text-align: right; }

  .nav-links .m-menu-cta{ width: 100%; max-width: min(340px, 84vw); margin-inline: auto; }
  .nav-links .btn-primary,
  .nav-links .btn-primary span{ color: var(--black); }
  .nav-links .btn-primary svg{ stroke: var(--black); }
}
