/* ============================================================
   APPLE-STYLE THEME (2026-07-31). EVERY PAGE, loaded LAST.

   2026-07-31 (second pass): the owner asked for all 54 routes, not just the
   homepage. This file is now linked from every page and from the generator,
   and it covers the inner-page components too (breadcrumbs, prose, steps, FAQ,
   hub cards, the scope planner, price cards, contact meta). It is still one
   file, still last, still scoped to `body.ap`: removing the class or the
   <link> returns any page to dark.

   Owner: "make it like you would think apple.com would make it, I love how
   easy and clean their websites look."

   What Apple actually does, measured rather than remembered, and applied here:
   - LIGHT. #fff against #f5f5f7, alternating. Nothing is dark.
   - Type carries everything. One display weight (600), tight negative
     tracking, and a very large size jump between headline and body.
   - No borders. No glass. No glow. Grouping is done with whitespace and a
     pale grey tile, never with a line around a box.
   - Few words per screen, and a lot of air between them.
   - One accent, a single blue, used for links and one pill button.
   - Big rounded corners (18 to 28px) on tiles and on the hero image.
   - A slim translucent bar, tiny nav type, no mega dropdown shouting.

   Same discipline as refine.css and migrate.css: ONE file, loaded last,
   scoped to body.ap on the homepage. Delete the <link> and the site is back
   to dark exactly as it was. It overrides tokens rather than editing them, so
   no other page can be affected.
   ============================================================ */

body.ap {
  /* Apple's greys, and the brand blue kept from the existing palette so this
     is a change of surface, not a change of identity. */
  --ap-paper: #ffffff;
  --ap-tile: #f5f5f7;
  --ap-tile-2: #ffffff;
  --ap-ink: #1d1d1f;
  --ap-ink-2: #5c5c61;          /* 7.0:1 on white, 6.5:1 on the #f5f5f7 tile.
                                   #6e6e73 was Apple's exact grey but only cleared
                                   AA on white, and half this site's muted text sits
                                   on the tile. */
  --ap-hair: #d2d2d7;
  --ap-blue: #0066cc;           /* 5.6:1 on white, Apple's link blue */
  --ap-blue-hover: #0055aa;
  --ap-gold: #8a6417;           /* the brand gold, darkened to clear AA */
  --ap-r: 18px;
  --ap-r-lg: 28px;
  --ap-ease: cubic-bezier(.28, .11, .32, 1);

  /* REDEFINE THE BASE PALETTE, do not chase components.
     styles.css, theme-gold.css and migrate.css all paint from these tokens.
     Overriding the tokens here fixes whole families of text at once; the first
     pass chased individual selectors and axe kept finding more. Every value
     clears 4.5:1 on both #fff and the #f5f5f7 tile. */
  --heading: #1d1d1f;
  --text: #1d1d1f;
  --muted: #5c5c61;
  --faint: #6b6b70;
  --line: #d2d2d7;
  --line-strong: #c7c7cc;
  --glass: #f5f5f7;
  --glass-2: #eceef2;
  --glass-brd: transparent;
  --glass-brd2: transparent;
  --bg: #ffffff;
  --bg-2: #f5f5f7;
  --panel: #f5f5f7;
  --panel-2: #ffffff;
  --shadow: none;
  --shadow-lg: none;
  --glow-blue: none;
  --glow-cta: none;
  /* migrate.css tokens (homepage) */
  --mg-hair: #d2d2d7;
  --mg-hair-2: #c7c7cc;
  --mg-ink-2: #5c5c61;
  --mg-navy: #0066cc;
  --mg-gold: #8a6417;
  --mg-ok: #1d7a4c;
  --mg-tile: #f5f5f7;

  background: var(--ap-paper);
  color: var(--ap-ink);
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -.012em;
}

/* Kill every dark-theme device on this page: the ambient layers, the canvas,
   the glass and the glows. */
body.ap .bg, body.ap #fx, body.ap .rh-fade { display: none !important; }
body.ap .card, body.ap .mg-panel, body.ap .glass {
  background: var(--ap-tile) !important; border-color: transparent !important;
  box-shadow: none !important; -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
}

/* ---------- Typography ---------- */
body.ap h1, body.ap h2, body.ap h3, body.ap .h3 { color: var(--ap-ink); font-weight: 600; }
body.ap h1 { font-size: clamp(2.6rem, 1.2rem + 4.6vw, 4.4rem); line-height: 1.05; letter-spacing: -.035em; }
body.ap h2 { font-size: clamp(2rem, 1.2rem + 2.8vw, 3.2rem); line-height: 1.08; letter-spacing: -.03em; }
body.ap h3, body.ap .h3 { font-size: 1.25rem; letter-spacing: -.019em; line-height: 1.3; }
body.ap p, body.ap .lead, body.ap .muted { color: var(--ap-ink-2); }
body.ap .lead { font-size: clamp(1.125rem, 1rem + .6vw, 1.4rem); line-height: 1.4; letter-spacing: -.018em; color: var(--ap-ink); }
/* Apple's section label is blue text and nothing else: no pill, no ring, no
   uppercase tracking. */
body.ap .eyebrow, body.ap .rh-eyebrow {
  color: var(--ap-blue); font-size: 1.1875rem; font-weight: 600;
  letter-spacing: -.014em; text-transform: none;
  background: none !important; border: 0 !important; outline: 0 !important;
  padding: 0 !important; border-radius: 0 !important; box-shadow: none !important;
}
body.ap .eyebrow::before, body.ap .eyebrow::after { display: none !important; }

/* ---------- Header: 48px, translucent, tiny type, no shouting ---------- */
body.ap .site-header {
  background: rgba(255, 255, 255, .78); border-bottom: 1px solid transparent;
  -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
  box-shadow: none;
}
body.ap .site-header.is-stuck, body.ap .site-header[data-stuck] { border-bottom-color: rgba(0,0,0,.09); }
body.ap .site-header .nav { min-height: 52px; }
/* The mark carried a glow to sit on near-black. On white it is a grey halo. */
body.ap .brand-word, body.ap .brand-mark { color: var(--ap-ink); text-shadow: none; filter: none; }
body.ap .brand, body.ap .brand-mark, body.ap .brand-word { box-shadow: none; }
body.ap .brand-mark path { filter: none; }
body.ap .brand-word-accent { color: var(--ap-gold); }
body.ap .nav-link, body.ap .nav-link > span { color: var(--ap-ink); font-size: .8125rem; font-weight: 400; opacity: .88; }
body.ap .nav-link:hover, body.ap .nav-link:hover > span { opacity: 1; }
body.ap .nav-caret { border-color: var(--ap-ink-2); }
body.ap .mega {
  background: rgba(255,255,255,.96); border-color: var(--ap-hair);
  -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 20px 40px -24px rgba(0,0,0,.28);
}
body.ap .mega a, body.ap .mega-h { color: var(--ap-ink); }
body.ap .mega a:hover { background: var(--ap-tile); }

/* ---------- Buttons: one blue pill, everything else is a link ---------- */
body.ap .btn {
  border-radius: 980px; font-weight: 400; font-size: 1.0625rem; letter-spacing: -.012em;
  padding: 12px 22px; box-shadow: none; border: 0;
}
body.ap .btn-primary, body.ap .rh-btn-primary { background: var(--ap-blue); color: #fff; }
body.ap .btn-primary:hover, body.ap .rh-btn-primary:hover { background: var(--ap-blue-hover); }
body.ap .btn-ghost, body.ap .rh-btn-gold {
  background: transparent; color: var(--ap-blue); padding: 12px 4px;
}
body.ap .btn-ghost:hover, body.ap .rh-btn-gold:hover { background: transparent; text-decoration: underline; }
body.ap .btn-ghost svg, body.ap .rh-btn-gold svg { width: 15px; height: 15px; }
body.ap .btn:focus-visible { outline: 2px solid var(--ap-blue); outline-offset: 3px; }

/* ---------- Hero: Apple's product page. Copy centred on white, then the
     artwork below it as a contained, rounded picture rather than a dark
     full-bleed environment. The markup is untouched; the visual layer stops
     being absolutely positioned and becomes the second row of a grid. ---------- */
body.ap .rh {
  display: grid; grid-template-columns: minmax(0, 1fr); min-height: 0;
  background: var(--ap-paper); padding: clamp(56px, 3rem + 4vw, 88px) 0 0; text-align: center;
}
body.ap .rh-inner { order: 1; padding: 0 22px; transform: none; }
body.ap .rh-visual {
  order: 2; position: relative; inset: auto; height: auto;
  width: 100%; max-width: 1120px; margin: clamp(40px, 2rem + 3vw, 64px) auto 0;
  padding: 0 22px;
}
body.ap .rh-visual::after { display: none; }   /* the dark readability scrim */
/* The artwork is 2400x1051 (16:7), recomposed so the ribbon runs edge to edge,
   so a 16:7 frame shows the whole picture and crops nothing. Do not change this
   ratio without re-cropping the asset: the old art was right-weighted and left
   a dead black half, which is what made the tile read as a hole in the page. */
body.ap .rh-fallback {
  position: relative; inset: auto; aspect-ratio: 16 / 7;
  border-radius: var(--ap-r-lg); overflow: hidden;
  background-position: center center !important;
}
/* Apple lets hero media run wider than the text column. Below 1600px the tile
   matches the 1180px content width; above it the picture gets room instead of
   sitting stranded in the middle of a 4K page. */
@media (min-width: 1600px) {
  body.ap .rh-visual { max-width: 1400px; }
}
body.ap .rh-copy { max-width: 1000px; margin: 0 auto; text-align: center; transform: none; }
body.ap .rh-eyebrow { display: block; margin: 0 0 8px; }
/* Apple caps the HEADLINE, not the column: the sub-copy is allowed to be wider
   and the measure is set per element. text-shadow was there to lift type off a
   dark ribbon; on white it reads as a smudge. */
/* The measure is 20ch, not 17ch, and the two work as layers. At 17ch the
   headline broke to FOUR lines at every width from 768px up and stranded "on."
   alone on the last one, which is the one thing Apple never ships. Measured
   with `ttp-orphan.mjs` across 8 widths x 6 candidates:
     17ch            4 lines, orphan at every width
     20ch            3 balanced lines, no orphan from 768px up
     20ch + balance  3 lines, no orphan at ANY width, 390px included
   So 20ch alone is the fix for desktop and `text-wrap: balance` is what covers
   the phone. Browsers without balance (pre-Chrome 114 / Safari 17.5 / FF 121)
   ignore it and still get the 20ch result, which is why the measure changed
   rather than leaning on balance by itself. Shortens the h1 block 296px -> 222px.
   Re-run ttp-orphan.mjs if this measure or the headline copy changes. */
body.ap .rh h1 {
  max-width: 20ch; margin: 0 auto; text-shadow: none; text-wrap: balance;
  font-size: clamp(2.6rem, 1.2rem + 4.6vw, 4.4rem); line-height: 1.05; letter-spacing: -.035em;
}
body.ap .rh h1 .rh-blue { color: var(--ap-ink); text-shadow: none; }
/* FEWER WORDS is the Apple move, and the page already had the mechanism. The
   `.rh-trim` clauses were built to collapse under 900px; here they collapse at
   every width, so the hero reads as one short paragraph instead of eight lines.
   Nothing is lost: the spans are only hidden by CSS, so the full sentence is
   still in the HTML for search engines, and `#what` carries the long form. */
body.ap .rh-trim { display: none; }
body.ap .rh-keep-sm { display: inline; }
body.ap .rh-lead {
  max-width: 40ch; margin: 20px auto 0; color: var(--ap-ink-2);
  font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem); line-height: 1.45; letter-spacing: -.014em;
}
body.ap .rh-cta { justify-content: center; gap: 26px; margin-top: 26px; }
body.ap .rh-ticker {
  order: 3; position: relative; margin: clamp(40px, 2rem + 2vw, 60px) auto 0;
  color: var(--ap-ink-2); font-size: .75rem; letter-spacing: .04em; text-transform: none;
  background: none; border: 0;
}
body.ap .rh-ticker span { color: var(--ap-ink-2); }
body.ap .rh-ticker i { background: var(--ap-hair); }

/* On a phone Apple keeps the picture but gives the words the whole screen
   first, so the artwork sits below the fold rather than behind the type. */
@media (max-width: 899px) {
  body.ap .rh { padding-top: 40px; }
  /* 3:2 keeps 66% of a 16:7 picture; 4:3 kept only 58% and cut the composition
     in half. The focal point is 62%, measured from the artwork's own brightness
     centroid (0.59): the window then runs 21% to 86% and holds both the blue
     sweep entering on the left and the gold crest. The base rule sets
     `center center !important`, so this override needs !important too. */
  body.ap .rh-fallback {
    aspect-ratio: 3 / 2; border-radius: 20px;
    background-position: 62% center !important;
  }
  body.ap .rh-copy { max-width: none; }
}

/* ---------- Sections: alternating white and #f5f5f7, lots of air ---------- */
body.ap .section, body.ap .section-tight { background: var(--ap-paper); padding-block: clamp(72px, 3.5rem + 5vw, 120px); }
body.ap #systems, body.ap #services, body.ap #plans { background: var(--ap-tile); }
body.ap #systems .card, body.ap #services .card, body.ap #plans .card { background: var(--ap-tile-2) !important; }
/* SECTION RHYTHM on inner pages. A generated page is 11 to 13 sections long and
   every one of them was white, so it read as one endless sheet: the other half
   of "the pages look very empty and plain". Apple never runs more than two
   panels of the same surface together. Banding every third section gives the
   page a pulse without turning into stripes, and a card on a tinted band flips
   to white so it does not disappear into it.
   `:not([id])` keeps the homepage's hand-tuned bands (#systems, #services,
   #plans) out of the count; they are already deliberate. */
body.ap main .section:not([id]):nth-of-type(3n),
body.ap main .section-tight:not([id]):nth-of-type(3n) { background: var(--ap-tile); }
body.ap main .section:not([id]):nth-of-type(3n) > .container > .card,
body.ap main .section:not([id]):nth-of-type(3n) .card,
body.ap main .section-tight:not([id]):nth-of-type(3n) .card { background: #ffffff; }
/* Apple caps the HEADING, never the column. A 24ch column squeezed the h2
   into six words a line and it read as a poem. */
body.ap .section-head { max-width: 100%; margin-left: auto; margin-right: auto; text-align: center; }
body.ap .section-head h2 { max-width: 18ch; margin-left: auto; margin-right: auto; }
body.ap .section-head .lead, body.ap .section-head p { max-width: 44ch; margin-left: auto; margin-right: auto; }

/* ---------- Cards: borderless tiles, generous padding, big radius ---------- */
body.ap .card {
  border-radius: var(--ap-r); padding: 34px 30px;
  transition: transform .35s var(--ap-ease);
}
body.ap .card:hover { transform: translateY(-4px); background: var(--ap-tile) !important; }
body.ap #systems .card:hover, body.ap #services .card:hover, body.ap #plans .card:hover { background: #fff !important; }
body.ap .card .ico, body.ap .card > svg, body.ap .mg-row > svg, body.ap .mg-list .card > svg {
  color: var(--ap-ink); background: none !important; border: 0 !important; box-shadow: none !important;
}

body.ap .link-card { background: var(--ap-tile) !important; border: 0 !important; }

/* ---------- The credibility strip under the hero ---------- */
body.ap .svc-strip { background: var(--ap-paper); border: 0; }
body.ap .rh-cats { border: 0; }
body.ap .rh-cat { border: 0 !important; }
body.ap .rh-cat svg { color: var(--ap-ink); }
body.ap .rh-cat strong { color: var(--ap-ink); }
body.ap .rh-cat span { color: var(--ap-ink-2); }

/* ---------- Migrated pieces, relit for a white page ---------- */
body.ap .mg-panel { border-radius: var(--ap-r-lg); padding: 8px 30px 16px; }
body.ap .mg-row, body.ap .mg-list .card, body.ap .mg-table th, body.ap .mg-table td { border-top-color: var(--ap-hair); }
body.ap .mg-table tbody tr:last-child td { border-bottom-color: var(--ap-hair); }
body.ap .mg-row .t, body.ap .mg-list .card .h3 { color: var(--ap-ink); }
body.ap .mg-row .s, body.ap .mg-list .card p, body.ap .mg-table caption { color: var(--ap-ink-2); }
body.ap .mg-row .state { color: #1d7a4c; }
body.ap .mg-table td svg { color: #1d7a4c; }
body.ap .mg-list .card { background: none !important; }
body.ap .mg-list .card:hover { background: none !important; transform: none; }
body.ap .mg-flat .card { background: var(--ap-tile) !important; }

/* ---------- Recent Work: Apple shows the product, big and unframed ---------- */
/* padding 0: the generic card padding above would otherwise inset the
   screenshot, and Apple runs the picture to the edge of its tile. */
body.ap .work-card { background: var(--ap-tile) !important; border-radius: var(--ap-r-lg); overflow: hidden; padding: 0; }
body.ap .work-card:hover { transform: none; }
body.ap .work-shot { border-bottom: 1px solid var(--ap-hair); }
body.ap .work-result { color: var(--ap-ink); }

/* ---------- Footer ---------- */
body.ap .site-footer, body.ap footer { background: var(--ap-tile); border-top: 1px solid var(--ap-hair); color: var(--ap-ink-2); }
body.ap .site-footer a, body.ap footer a { color: var(--ap-ink-2); }
body.ap .site-footer a:hover, body.ap footer a:hover { color: var(--ap-ink); }
body.ap .footer-h { color: var(--ap-ink); }

/* ---------- Mobile action bar ---------- */
body.ap .mobile-bar {
  background: rgba(255,255,255,.92); border-top: 1px solid var(--ap-hair);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
}
body.ap .mobile-bar .btn-primary { background: var(--ap-blue); color: #fff; }
/* The call button is .mobile-bar-call, not .btn-ghost: it was built from the
   dark theme's glass tokens and all but vanished on a white bar. */
body.ap .mobile-bar-call {
  color: var(--ap-ink) !important; background: var(--ap-tile) !important;
  border: 1px solid var(--ap-hair) !important;
}
body.ap .mobile-bar-call:hover { color: var(--ap-ink) !important; }
body.ap .mobile-bar-call svg { color: var(--ap-ink); }
/* The quote button used --baby, a pale blue built to glow on near-black. On
   white it reads as disabled. */
body.ap .mobile-bar-quote { background: var(--ap-blue) !important; color: #fff !important; }
body.ap .mobile-bar-quote svg { color: #fff; }
body.ap .mobile-bar-btn { font-weight: 500; }
/* The hamburger is three <span> bars. Only the BARS take the ink colour: an
   earlier attempt set background-color on the button too and turned the whole
   control into a solid black square. */
body.ap .nav-toggle { background: none; }
body.ap .nav-toggle span { background: var(--ap-ink); }

/* ---------- The closing band Apple would make plain ---------- */
body.ap .cta-band { background: var(--ap-tile); border: 0; }

/* ---------- Motion: slower, fewer, transform and opacity only ---------- */
body.ap .rise, body.ap [data-reveal] { }
body.ap [data-reveal].rv-in, body.ap .rv-in {
  transition: opacity .8s var(--ap-ease), transform .8s var(--ap-ease);
}

@media (prefers-reduced-motion: reduce) {
  body.ap *, body.ap *::before, body.ap *::after { transition: none !important; animation: none !important; }
}

/* ---------- Alignment: Apple centres a section and everything in it ---------- */
body.ap .section .center,
body.ap .section > .container > .center,
body.ap .section p.center { text-align: center; }
body.ap .section .center .btn { margin-inline: 4px; }
/* The trailing action row inherited a left edge from the Apple-plain finish,
   which reads as a mistake under a centred heading. */
body.ap .section .container > div[style*="margin-top"],
body.ap .section .container > p.center { display: flex; flex-wrap: wrap; gap: 10px 26px; justify-content: center; align-items: center; }

/* The systems panel sits on the grey band, so it needs to be the white card. */
body.ap #systems .mg-panel { background: var(--ap-tile-2) !important; }

/* Card icons: Apple keeps them small and inline with the text block. */
body.ap .card .ico { width: auto; height: auto; margin-bottom: 16px; }
body.ap .card .ico svg { width: 26px; height: 26px; }

/* ---------- Contrast repairs ----------
   These are dark-theme colours that survived onto a white page because their
   original rules are more specific than a plain body.ap selector (several are
   scoped to body.story-dark). axe caught all of them at 4.5:1; every value
   below was chosen to clear AA on the surface it actually sits on, not
   guessed. */
body.ap .footer-h,
body.ap .site-footer .footer-h,
body.ap footer .footer-h { color: var(--ap-ink) !important; }
body.ap .footer-links a,
body.ap .site-footer a,
body.ap footer a { color: var(--ap-ink-2) !important; }
body.ap .footer-links a:hover,
body.ap .site-footer a:hover { color: var(--ap-ink) !important; }
/* The tagline sits on the translucent bar, which blends to about #e1e1e3, so
   the mid grey only reached 3.9:1. */
body.ap .brand-tagline { color: #43434a !important; text-shadow: none !important; }
body.ap .footer-bottom, body.ap .footer-bottom span, body.ap #year { color: var(--ap-ink-2) !important; }
body.ap .footer-chev { border-color: var(--ap-ink-2) !important; }
/* body.story-dark sets the hero eyebrow to a near-white; on paper it vanished. */
body.ap .rh .rh-eyebrow, body.story-dark.ap .rh-eyebrow { color: var(--ap-blue) !important; }
body.ap .rh-ticker span, body.ap .rh-ticker { color: var(--ap-ink-2) !important; }
body.ap .muted, body.ap .card p, body.ap .lead { color: var(--ap-ink-2); }
body.ap .section-head .lead { color: var(--ap-ink-2) !important; }

/* ---------- The overscroll colour ----------
   styles.css sets `html { background-color: var(--bg) }` deliberately, so the
   rubber-band area is brand navy rather than white. That also stops the body
   background from propagating, which left a near-black strip below the fold on
   this light page. :has() scopes the override to the homepage only, so no
   other page loses its dark overscroll. */
html:has(body.ap) { background-color: #ffffff; }

/* ============================================================
   INNER PAGES (added 2026-07-31 when the theme went sitewide).
   These components live in content.css and theme-gold.css and only exist on
   the 47 generated pages plus the inner root pages, so none of it can affect
   the homepage. Same rule as above: colour is chosen against the surface the
   text actually sits on, then checked with axe, never guessed.
   ============================================================ */

/* ---------- Page hero on inner pages ----------
   OWNER 2026-08-01: "all the other pages do not look the same, the text is not
   centralized like it is on the first page... does not have that quality Apple
   feel". This SUPERSEDES the left-aligned hero shipped on 2026-07-31.

   What was wrong is measurable, not a matter of taste: 52 of 53 routes had a
   left-aligned hero and ZERO hero CTAs, so every inner page opened with type
   crammed into the left 55% and a dead white right half, then offered nowhere
   to go. `ttp-thin.mjs` reports it.

   Apple centres the hero on every page it ships, long-form included, and only
   then left-aligns the prose underneath. Both halves matter. Centring the hero
   is what makes a page look designed; centring paragraphs would wreck them, so
   the prose column below stays left-aligned and is merely CENTRED IN THE PAGE
   (see "Long-form prose"), which is what removes the empty right half. */
body.ap main .hero:not(.rh) {
  text-align: center;
  padding: clamp(44px, 2rem + 3vw, 76px) 0 clamp(28px, 1.5rem + 1.5vw, 44px);
}
/* The generator writes `style="max-width:62ch"` on .hero-copy and inline beats a
   stylesheet, so this needs !important. 62ch at h1 size is what wrapped the
   headline to four lines against an empty right half. */
body.ap main .hero:not(.rh) .hero-copy { max-width: none !important; margin-inline: auto; }
body.ap main .hero:not(.rh) h1 {
  max-width: 20ch; margin-inline: auto; text-wrap: balance;
  letter-spacing: -.03em; line-height: 1.06;
}
body.ap main .hero:not(.rh) .eyebrow { display: block; margin-bottom: 10px; }
body.ap main .hero:not(.rh) .lead, body.ap main .hero:not(.rh) > p {
  max-width: 46ch; margin-inline: auto; text-wrap: pretty;
}
/* Breadcrumbs are a centred trail above the eyebrow, not a left-gutter anchor. */
body.ap main .hero:not(.rh) .crumbs ol { justify-content: center; }
/* Every inner hero now ends in the same two choices the homepage offers. */
body.ap main .hero:not(.rh) .hero-cta {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 22px; margin-top: 26px;
}

/* ---------- Breadcrumbs ---------- */
body.ap .crumbs, body.ap .crumbs a, body.ap .crumbs span { color: var(--ap-ink-2); }
body.ap .crumbs a:hover { color: var(--ap-ink); }

/* ---------- Long-form prose ---------- */
/* THE EMPTY RIGHT HALF. `content.css` caps .prose at 72ch with no auto margin,
   so on a 1180px container every long-form section hugged the left gutter and
   left roughly a third of the page blank all the way down. Centring the COLUMN
   while the text inside it stays left-aligned is how Apple sets long-form, and
   it is the single change that stops these pages reading as unfinished. */
body.ap .prose { color: var(--ap-ink-2); margin-inline: auto; }
/* .prose was not the only offender. A DOM sweep across seven page types found
   every capped block sitting hard against the left gutter with 300 to 700px of
   dead white beside it: the answer card, the trust note, the FAQ list, the step
   list, stacks and grids. They are centred as a family here rather than one at a
   time. `.split` children are deliberately excluded: that layout IS two columns
   and centring its card would collapse the pairing. */
body.ap main .container > .answer-card,
body.ap main .container > .trust-note,
body.ap main .container > .faq-list,
body.ap main .container > .steps,
body.ap main .container > .stack-2,
body.ap main .container:not(.split) > .grid,
body.ap main .container:not(.split) > .card,
body.ap main .container > .center.muted { margin-inline: auto; }
/* The two-column split stays two columns, but its cells were vertically centred,
   so on /about the side card floated 130px below the paragraph it belongs beside
   and left a hole under itself. Top-align the pair and they read as one block. */
body.ap main .container.split { align-items: start; }
/* The section title is the one centred element in a prose block: it matches the
   homepage's centred section heads, and the paragraph under it stays left so it
   is still readable. */
body.ap .section > .container > .prose > h2:first-child,
body.ap .section-tight > .container > .prose > h2:first-child {
  text-align: center; max-width: 22ch; margin-inline: auto;
  margin-bottom: clamp(24px, 1rem + 1.5vw, 40px); text-wrap: balance;
}
body.ap .prose h2, body.ap .prose h3, body.ap .prose h4, body.ap .prose strong { color: var(--ap-ink); }
body.ap .prose a { color: var(--ap-blue); text-decoration-color: rgba(0, 102, 204, .38); }
body.ap .prose a:hover { text-decoration-color: currentColor; }
body.ap .prose blockquote, body.ap .answer-card {
  background: var(--ap-tile) !important; border: 0 !important; border-radius: var(--ap-r);
  color: var(--ap-ink);
}
body.ap .answer-card strong, body.ap .answer-card b { color: var(--ap-ink); }

/* ---------- Steps, checklists, feature lists ---------- */
body.ap .steps li, body.ap .check-list li, body.ap .feature-list li { color: var(--ap-ink-2); }
body.ap .steps li strong, body.ap .check-list li strong, body.ap .feature-list li strong { color: var(--ap-ink); }
body.ap .step-n {
  background: var(--ap-blue) !important; color: #fff !important;
  border: 0 !important; box-shadow: none !important;
}
/* The tick markers are a background SVG with the colour baked into the data
   URI, so a `color` override does nothing. The whole background is replaced
   with the same tick in a green that reads on white. */
body.ap .check-list li::before, body.ap .feature-list li::before {
  background: #e8f5ee url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%231d7a4c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/12px no-repeat !important;
  border-color: #bfe2ce !important;
}
body.ap .check-list svg, body.ap .feature-list svg { color: #1d7a4c; }
body.ap .pill svg { color: var(--ap-ink-2); }

/* ---------- FAQ ---------- */
body.ap .faq-item {
  background: none !important; border: 0 !important;
  border-top: 1px solid var(--ap-hair) !important; border-radius: 0 !important;
}
body.ap .faq-list > .faq-item:last-child { border-bottom: 1px solid var(--ap-hair) !important; }
body.ap .faq-item summary, body.ap .faq-item h3 { color: var(--ap-ink); }
body.ap .faq-a, body.ap .faq-a p { color: var(--ap-ink-2); }

/* ---------- Hub and related link cards ---------- */
body.ap .link-card {
  background: var(--ap-tile) !important; border: 0 !important;
  border-radius: var(--ap-r); box-shadow: none !important;
}
body.ap .link-card:hover { background: #eceef2 !important; transform: translateY(-3px); }
body.ap .link-card h3, body.ap .link-card strong { color: var(--ap-ink); }
body.ap .link-card p, body.ap .link-card span { color: var(--ap-ink-2); }
body.ap .link-card svg { color: var(--ap-ink); }

/* ---------- Trust note and muted cards ---------- */
body.ap .trust-note, body.ap .card-muted {
  background: var(--ap-tile) !important; border: 0 !important; border-radius: var(--ap-r);
  color: var(--ap-ink-2);
}
body.ap .trust-note strong, body.ap .card-muted strong { color: var(--ap-ink); }

/* ---------- Scope planner (contact page) ---------- */
body.ap .scope-planner, body.ap .scope-summary, body.ap .scope-note, body.ap .scope-help {
  background: var(--ap-tile) !important; border: 0 !important; border-radius: var(--ap-r);
  color: var(--ap-ink-2);
}
body.ap .scope-q, body.ap .scope-opt-label { color: var(--ap-ink); }
body.ap .scope-opt {
  background: #fff !important; border: 1px solid var(--ap-hair) !important; border-radius: 12px;
}
body.ap .scope-opt:hover { border-color: var(--ap-blue) !important; }
body.ap .scope-opt-note, body.ap .scope-factors { color: var(--ap-ink-2); }
body.ap .scope-opt input:checked + .scope-opt-body,
body.ap .scope-opt:has(input:checked) { border-color: var(--ap-blue) !important; background: #f0f6ff !important; }

/* ---------- Forms ---------- */
body.ap input, body.ap select, body.ap textarea {
  background: #fff !important; color: var(--ap-ink) !important;
  border: 1px solid var(--ap-hair) !important; border-radius: 12px;
}
body.ap input::placeholder, body.ap textarea::placeholder { color: #8e8e93; }
body.ap input:focus, body.ap select:focus, body.ap textarea:focus {
  border-color: var(--ap-blue) !important; outline: 2px solid rgba(0,102,204,.25); outline-offset: 0;
}
body.ap label { color: var(--ap-ink); }
body.ap .form-note, body.ap .form-status { color: var(--ap-ink-2); }

/* ---------- Pricing and plan cards ---------- */
body.ap .price-card { background: var(--ap-tile) !important; border: 0 !important; border-radius: var(--ap-r-lg); }
body.ap .price-tag, body.ap .price-card h3 { color: var(--ap-ink); }
body.ap .tag, body.ap .pill {
  background: var(--ap-tile) !important; color: var(--ap-ink-2) !important;
  border: 1px solid var(--ap-hair) !important;
}

/* ---------- Contact meta and the closing band ---------- */
body.ap .contact-meta, body.ap .contact-meta a { color: var(--ap-ink-2); }
body.ap .contact-meta a:hover { color: var(--ap-blue); }
body.ap .cta-band {
  background: var(--ap-tile) !important; border: 0 !important; color: var(--ap-ink);
}
body.ap .cta-band h2 { color: var(--ap-ink); }
body.ap .cta-band p { color: var(--ap-ink-2); }

/* ---------- Inner-page hero band and section alternation ----------
   Generated pages have no hero image, so the first band should be white and
   the alternation should start after it. */
body.ap .page-hero, body.ap .hero:not(.rh) { background: var(--ap-paper); }
body.ap .section--alt, body.ap .section-alt { background: var(--ap-tile); }

/* ---------- Tables inside content ---------- */
body.ap .prose table { border-collapse: collapse; }
body.ap .prose th, body.ap .prose td { border-top: 1px solid var(--ap-hair); color: var(--ap-ink-2); }
body.ap .prose th { color: var(--ap-ink); }

/* ---------- Anything still painted from the dark palette ---------- */
/* The 01..04 numerals. #d2d2d7 was 1.4:1 and #86868b only 3.3:1 on the tile;
   axe treats them as normal text because they are not large enough to qualify
   for the 3:1 allowance. #6b6b70 clears 4.5:1 and still reads as quiet. */
body.ap .value-num { color: #6b6b70 !important; }
body.ap hr { border-color: var(--ap-hair); }
body.ap ::selection { background: rgba(0, 102, 204, .18); color: var(--ap-ink); }

/* ---------- The .grad accent inside inner-page headlines ----------
   It was a pale sky blue built to glow on near-black; on white it drops to
   about 2:1. Apple does not colour half a headline anyway, so it becomes ink
   and the emphasis comes from the sentence, not the paint. */
body.ap h1 .grad, body.ap h2 .grad, body.ap .grad {
  color: var(--ap-ink) !important;
  background: none !important; -webkit-background-clip: initial !important;
  background-clip: initial !important; -webkit-text-fill-color: currentColor !important;
  text-shadow: none !important;
}
/* A touch more room: 20ch left single words stranded on their own line. */
body.ap main .hero:not(.rh) h1 { max-width: 24ch; }

/* ---------- Sitewide link colour ----------
   Body links inherited the dark theme's #6fa5ef, which is 2.3:1 on a white or
   #f5f5f7 surface. Every in-content link now takes the one accent blue.
   EVERY branch needs `:not(.btn)`. The first branch had it and the rest did not,
   on the assumption that the button rules were more specific; they are not.
   `body.ap .card p a` is two classes and two elements, which beat `.btn-primary`,
   so the 404's "Get in touch" button rendered #0066cc text on a #0066cc fill: a
   solid blue pill with no readable label, live on the site. Any button dropped
   inside a card, prose block, answer card, lead or FAQ answer would have done
   the same, so the exclusion belongs on all of them, not just the one found. */
body.ap main a:not(.btn):not(.link-card):not(.crumbs a),
body.ap .prose a:not(.btn), body.ap .muted a:not(.btn),
body.ap .answer-card a:not(.btn), body.ap .card p a:not(.btn),
body.ap .lead a:not(.btn), body.ap .trust-note a:not(.btn),
body.ap .faq-a a:not(.btn) {
  color: var(--ap-blue);
}
body.ap main a:not(.btn):hover { color: var(--ap-blue-hover); }

/* ---------- Contact meta list ----------
   The markup is a plain <ul><li><span>, not .contact-meta, so the earlier rule
   never matched and the dark theme's near-white text sat on a grey tile at
   1.08:1. */
body.ap .contact-meta li, body.ap .contact-meta li span,
body.ap .contact-meta li strong, body.ap .contact-meta a {
  color: var(--ap-ink) !important;
}
body.ap .contact-meta li > span:first-child { color: var(--ap-ink-2) !important; }
body.ap .contact-meta svg { color: var(--ap-ink-2); }
body.ap .contact-meta a:hover { color: var(--ap-blue) !important; }
/* Belt and braces for any list inside a light card that still paints from the
   dark palette. */
body.ap .card li, body.ap .card li span, body.ap .card li strong { color: var(--ap-ink); }
body.ap .card li .muted, body.ap .card .muted { color: var(--ap-ink-2); }
body.ap .pay-note, body.ap .form-note { color: var(--ap-ink-2); }

/* ---------- Mobile nav panel ----------
   2026-08-02. The dark-to-light pass of 2026-07-31 covered every page surface
   but MISSED this one: `.mobile-menu` in styles.css hardcodes
   `background: rgba(8,13,26,.98)`, while its children paint from tokens this
   file redefined to light values. The result was light-grey text on near-black:
   `.mob-q` at 2.81:1 and `.mob-call` at 3.35:1, both failing WCAG AA (4.5:1).

   Caught by scripts/qa-a11y.mjs on its first run. Real, not an animation
   artifact: stable at 500ms, at 3s and under prefers-reduced-motion.

   Owner decision (2026-08-02): make the panel LIGHT to match the site, rather
   than lighten the text and keep one dark surface on an otherwise light site.

   The panel sits directly under .site-header, so it uses the same translucent
   white + blur treatment, only more opaque because page content scrolls
   underneath it. */
body.ap .mobile-menu {
  background: rgba(255, 255, 255, .96);
  border-bottom: 1px solid rgba(0, 0, 0, .09);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
}
body.ap .mob-q { color: var(--ap-ink); }
/* The outcome rows were glass-on-dark. On white that reads as an invisible
   box, so they become the same pale tile used everywhere else in this theme. */
body.ap .mob-outcome {
  background: var(--ap-tile);
  border: 1px solid var(--ap-hair);
  color: var(--ap-ink);
}
body.ap .mob-outcome:hover, body.ap .mob-outcome:focus-visible {
  border-color: var(--ap-blue); color: var(--ap-ink);
}
body.ap .mob-outcome .mob-arrow { color: var(--ap-ink-2); }
body.ap .mob-outcome:focus-visible { outline: 2px solid var(--ap-blue); outline-offset: 2px; }
/* .mob-call is a .btn-ghost: transparent with --ap-blue text, which is 5.6:1
   on white. It failed only because the panel behind it was near-black. */
body.ap .mob-links { border-top: 1px solid var(--ap-hair); }
body.ap .mob-links a { color: var(--ap-ink-2); }
body.ap .mob-links a[aria-current="page"] { color: var(--ap-blue); }
body.ap .mob-links a:hover { color: var(--ap-ink); }
body.ap .mob-links a:focus-visible { outline: 2px solid var(--ap-blue); outline-offset: 2px; }
