/* ============================================================================
   AJ WEB DESIGN

   A web designer's own site has to prove the product by existing. So the page
   argues with evidence, not adjectives: a deep teal band holds one promise —
   see your website before you pay a cent — and every section under it is a
   receipt for that promise. Teal #005f73 is not a mood, it is the exact colour
   of the A/J monogram, sampled from logo.png; amber #ee9b00 is the accent AJ
   already ships on ajwebdesign.co.za, and it carries the money action and
   nothing else. Type is drawn, not defaulted: Bricolage Grotesque set large and
   tight against plain Manrope. 2px radius throughout — square edges read as
   drawn, pillowed corners read as a UI kit.

   The photographs are not photographs. They are screenshots of four client
   sites that are actually live, each shown in that client's own palette, and
   they are allowed to clash with each other and with this page. That clash is
   the argument: a template shop cannot show four sites that look nothing alike.
   ========================================================================== */

:root{
  /* grounds */
  --bg:#f4f7f7;          /* cool paper; cooler than warm off-white so teal reads true */
  --bg-alt:#e8eff0;      /* teal-tinted band for alternating sections */
  --panel:#ffffff;       /* cards, FAQ, price rows */
  --deep:#042027;        /* full-bleed dark band: hero and closing contact ONLY.
                            Pass 3 dropped the Range Wall from this list (§4.3) —
                            two stacked dark screens at the top read as "too much". */

  /* text */
  --ink:#07272e;         /* near-black with teal in it, same family as the mark */
  --ink-inv:#e7f0f1;     /* body text on --deep */
  --muted:#567075;       /* secondary text on --bg / --bg-alt */
  --muted-inv:#9db4b8;   /* secondary text on --deep */

  /* brand */
  --accent:#005f73;      /* THE brand teal */
  --accent-hover:#00485a;
  --amber:#ee9b00;       /* money action only */
  --amber-hover:#d38a00;

  /* structure */
  --line:#d5e0e1;
  --line-inv:#1b3c44;
  --radius:2px;
  --wrap:1180px;

  /* kicker colour on --deep bands only; flips with the bands, see the flip table below */
  --band-kicker:var(--amber);
}

/* --------------------------------------------------------------------------
   DARK-TO-LIGHT FALLBACK (see design brief §2). AJ is testing the dark bands
   above as a deliberate choice. If he rejects it, change exactly these five
   lines and ship the same HTML — nothing else in this file, or in any page,
   depends on the bands being dark.

     --deep:       var(--bg-alt)
     --ink-inv:    var(--ink)
     --muted-inv:  var(--muted)
     --line-inv:   var(--line)
     --band-kicker: var(--accent)
   -------------------------------------------------------------------------- */

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  font:400 1rem/1.65 'Manrope',system-ui,sans-serif;
  background:var(--bg);
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit}
ul{margin:0;padding:0;list-style:none}
p{margin:0 0 1rem}
.wrap{max-width:var(--wrap);margin-inline:auto;padding-inline:1.5rem}

h1,h2,h3{font-family:'Bricolage Grotesque',system-ui,sans-serif;margin:0 0 .6rem;color:inherit}
h1{font-weight:800;font-size:clamp(2.35rem,6.2vw,4.6rem);line-height:.98;letter-spacing:-.035em}
h2{font-weight:700;font-size:clamp(1.85rem,3.9vw,2.9rem);line-height:1.04;letter-spacing:-.025em}
h3{font-weight:600;font-size:1.22rem;letter-spacing:-.01em}

.kicker{
  font-family:'Manrope';font-weight:700;font-size:.72rem;
  letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent);
  display:flex;align-items:center;gap:.7rem;margin-bottom:.9rem;
}
.kicker::before{content:"";width:26px;height:2px;background:currentColor;flex:0 0 auto}
.deep .kicker{color:var(--band-kicker)}

.lede{color:var(--muted);font-size:1.08rem;max-width:46ch}
.deep .lede{color:var(--muted-inv)}

/* section grounds */
.section{padding:5.5rem 0}
.bg{background:var(--bg)}
.bg-alt{background:var(--bg-alt)}
.deep{background:var(--deep);color:var(--ink-inv)}
.panel{background:var(--panel)}

.section-head{margin-bottom:2.6rem;max-width:56ch}
.section-head p{font-size:1.05rem}

/* buttons */
.btn{
  display:inline-flex;align-items:center;gap:.5rem;
  font-family:'Manrope';font-weight:700;font-size:.92rem;
  padding:.85rem 1.5rem;border-radius:var(--radius);
  border:1px solid transparent;cursor:pointer;
  text-decoration:none;white-space:nowrap;
  transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
.btn-amber{background:var(--amber);color:var(--ink)}
.btn-amber:hover,.btn-amber:focus-visible{background:var(--amber-hover)}
.btn-teal{background:var(--accent);color:#fff}
.btn-teal:hover,.btn-teal:focus-visible{background:var(--accent-hover)}
.btn-ghost{background:transparent;border-color:var(--line-inv);color:var(--ink-inv)}
.btn-ghost:hover,.btn-ghost:focus-visible{border-color:var(--ink-inv)}
.bg .btn-ghost,.bg-alt .btn-ghost{border-color:var(--line);color:var(--ink)}
.bg .btn-ghost:hover,.bg-alt .btn-ghost:hover{border-color:var(--ink)}
.btn:focus-visible{outline:2px solid var(--amber);outline-offset:2px}

/* ==========================================================================
   NAV — scoped to body > nav so no in-page component can ride over it
   (the Hartman Attorneys bug the craft notes record).
   ========================================================================== */
body > nav{
  position:sticky;top:0;z-index:50;
  background:rgba(4,32,39,.92);backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line-inv);
}
.nav-row{
  display:flex;align-items:center;gap:1.6rem;
  padding-block:.8rem;min-height:64px;
}
.nav-brand{display:flex;align-items:center;gap:.6rem;text-decoration:none;color:var(--ink-inv);margin-right:auto}
.nav-brand img{width:44px;height:44px}
.nav-brand span{font-family:'Bricolage Grotesque';font-weight:600;font-size:1.05rem}

.nav-links{display:flex;align-items:center;gap:1.8rem}
.nav-links a{
  position:relative;font-size:.92rem;font-weight:600;text-decoration:none;
  color:var(--ink-inv);padding-block:.3rem;
}
.nav-links a::after{
  content:"";position:absolute;left:0;bottom:-2px;width:100%;height:2px;
  background:var(--amber);transform:scaleX(0);transform-origin:left;
  transition:transform .18s ease;
}
.nav-links a:hover::after,.nav-links a:focus-visible::after{transform:scaleX(1)}

.region-switch{display:flex;align-items:center;gap:.6rem;font-size:.72rem;font-weight:700;letter-spacing:.1em}
.region-switch a{text-decoration:none;color:var(--muted-inv);padding:.2rem .1rem}
.region-switch a[aria-current="page"]{color:var(--amber)}
.region-switch a:hover{color:var(--ink-inv)}

.nav-cta{margin-left:.4rem}
.nav-burger{
  display:none;background:none;border:0;color:var(--ink-inv);
  width:40px;height:40px;cursor:pointer;
}
.nav-burger span,.nav-burger::before,.nav-burger::after{
  content:"";display:block;height:2px;background:currentColor;margin:7px auto;width:22px;
}

.nav-drop{display:none}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{padding-block:6rem}
.hero-grid{
  display:grid;grid-template-columns:1.05fr .95fr;gap:3.5rem;align-items:center;
}
.hero-chips{display:flex;flex-wrap:wrap;gap:.8rem 1.4rem;margin-top:2rem}
.hero-chips li{
  font-size:.82rem;font-weight:600;color:var(--muted-inv);
  display:flex;align-items:center;gap:.5rem;
}
.hero-chips li::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--amber);flex:0 0 auto}
.cta-row{display:flex;flex-wrap:wrap;gap:1rem;margin-top:1.8rem}

.hero-anim{opacity:0;transform:translateY(28px);animation:fade-up .42s cubic-bezier(.2,.7,.3,1) forwards}
.hero-anim.d0{animation-delay:0ms}
.hero-anim.d1{animation-delay:80ms}
.hero-anim.d2{animation-delay:160ms}
.hero-anim.d3{animation-delay:240ms}
@keyframes fade-up{to{opacity:1;transform:translateY(0)}}

/* ==========================================================================
   HERO ILLUSTRATION — the scroll-built mock site (design brief §4.2c).

   Four pieces build in order inside a frame that never animates: nav bar →
   mock photo (AJ's own Canva graphic) → mock headline and paragraph → amber
   mock button. Each drops in from slightly above, the opposite direction to
   the hero text's fade-up beside it: the promise rises, the site drops into
   place.

   DEFAULT STATE IS ASSEMBLED. Everything below paints fully built, opacity 1,
   no transform. The scroll-driven animation is applied only inside the
   @supports block, so a browser without scroll-driven animations gets the
   finished frame through the normal cascade rather than a duplicated rule —
   and so does prefers-reduced-motion, which overrides the animation away.

   No motion library: CSS scroll-driven animation is computed off the main
   thread by the compositor. Most of this site's visitors are on phones.

   Nothing here is a real site or a link, and nothing here shifts layout:
   .hero-illustration owns a fixed 4/3 box from first paint, and the pieces
   animate opacity and transform only, inside it. The hero's left column
   (kicker/H1/lede/CTA) is a separate component and is never scroll-gated —
   the WhatsApp CTA is clickable at first paint.
   ========================================================================== */
.hero-illustration{aspect-ratio:4/3;width:100%}
.illo-frame{
  height:100%;display:flex;flex-direction:column;gap:.75rem;
  padding:.9rem;border:1px solid var(--line-inv);border-radius:var(--radius);
  /* Token-derived, never a dark literal — flips with the band (brief §2).
     Lifted enough that the frame reads as a deliberate empty browser window
     before the first scroll, rather than as a hole in the hero. */
  background:color-mix(in srgb,var(--ink-inv) 9%,transparent);
}
.illo-nav{
  display:flex;align-items:center;gap:.55rem;
  padding-bottom:.75rem;border-bottom:1px solid var(--line-inv);
}
.illo-dot{width:13px;height:13px;border-radius:50%;background:var(--muted-inv);flex:0 0 auto}
.illo-navline{
  height:5px;width:clamp(22px,3.2vw,38px);border-radius:var(--radius);
  background:color-mix(in srgb,var(--muted-inv) 55%,transparent);
}
.illo-navline:first-of-type{margin-left:auto}
.illo-image{flex:1 1 auto;min-height:0;overflow:hidden;border-radius:var(--radius)}
.illo-image picture,.illo-image img{height:100%;width:100%}
.illo-image img{object-fit:cover;object-position:center}
.illo-lines{display:flex;flex-direction:column;gap:.5rem}
.illo-lines span{display:block;border-radius:var(--radius)}
.illo-headline{height:13px;width:70%;background:var(--ink-inv)}
.illo-p{height:7px;width:92%;background:color-mix(in srgb,var(--muted-inv) 50%,transparent)}
.illo-p.illo-short{width:62%}
.illo-btn{
  display:block;height:26px;width:104px;border-radius:var(--radius);
  background:var(--amber);flex:0 0 auto;
}
/* bars grow from their left edge, so scaleX reads as "landing into place" */
.illo-nav,.illo-lines,.illo-btn{transform-origin:left center}

@keyframes illo-bar{from{opacity:0;transform:translateY(-6px) scaleX(.15)}to{opacity:1;transform:none}}
@keyframes illo-photo{from{opacity:0;transform:translateY(-10px) scale(.94)}to{opacity:1;transform:none}}

/* --------------------------------------------------------------------------
   DEVIATION FROM BRIEF §4.2c, MEASURED NOT ASSUMED — scroll() instead of view().

   The brief specifies a named view timeline on .hero-illustration with entry-
   phase ranges (entry 0% cover 25%, and so on). Built exactly that first and
   measured the animations' computed progress in Chromium at three widths, at
   scroll position 0:

     1440x900 — nav 100%, photo 100%, lines 83%, button 66%   (already built)
      768x1024 — nav 100%, photo 50%, lines 27%, button 15%   (stage 1 missed)
      375x812  — nav 14%, photo 0.3%, lines 0%, button 0%     (correct)

   The reason is structural, not a tuning error: a view timeline's entry phase
   is the element crossing INTO the viewport, and this element is the hero's
   right column — it is already inside the viewport at first paint on desktop,
   so its entry phase is spent before the visitor scrolls at all. The sequence
   AJ actually asked to see ("the site builds itself as you scroll") cannot
   happen on a view timeline for an element that starts in view.

   Smallest change that resolves it: drive the same four stages, in the same
   order, with the same two keyframes, off the root scroller's own progress
   over the first ~380px of scroll. Still native CSS scroll-driven animation,
   still compositor-side, still no library, still no pinning and no added
   scroll distance — only the timeline source changes. It behaves the same at
   every width, because page scroll is the same everywhere.
   -------------------------------------------------------------------------- */
@supports (animation-timeline:scroll()){
  .illo-nav,.illo-lines,.illo-btn{animation:illo-bar 1s linear both;animation-timeline:scroll(root block)}
  .illo-image{animation:illo-photo 1s linear both;animation-timeline:scroll(root block)}
  .illo-nav{animation-range:0px 90px}
  .illo-image{animation-range:70px 190px}
  .illo-lines{animation-range:170px 285px}
  .illo-btn{animation-range:250px 380px}
}

/* ==========================================================================
   RANGE WALL — the motif. Four clashing palettes, one component that carries
   the testimonial mechanic too (design brief §6a): the whole card is the link.
   ========================================================================== */
.range-wall{padding-block:6rem}
/* Pass 3: this section moved from .deep to .bg-alt (brief §4.3) — the hero is
   now the page's only dark band before the closing contact section. The three
   token references below moved with it. No :root value changed; the five-line
   flip documented at the top of this file is untouched and still available.
   The .95rem size is dropped: --muted on --bg-alt measures 4.54:1, which §2
   passes only at 16px or larger. This note now inherits .section-head p's
   1.05rem (measured 16.8px in the browser), which clears that floor. Anything
   smaller than 16px on this ground must use --ink instead. */
.wall-note{margin-top:.6rem;color:var(--muted);max-width:60ch}
.proof-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);margin-top:2.6rem;border:1px solid var(--line);
}
.proof{
  background:var(--c-bg);color:var(--c-ink);
  text-decoration:none;display:block;
  animation:fade-up linear both;animation-timeline:view();
  animation-range:entry 0% cover 30%;
}
.proof-shot{padding:12px}
.proof-shot img{
  /* height:auto is required here — the <img> height="900" attribute otherwise pins the
     rendered box to 900px at every width (a presentational hint with higher priority than
     aspect-ratio), so the grid-column width shrinks but the height doesn't, producing an
     extreme sliver crop instead of the intended 4:3. Reviewer finding R-1, 2026-10-01. */
  aspect-ratio:4/3;object-fit:cover;object-position:top center;border-radius:var(--radius);
  height:auto;
  transition:transform .4s ease;
}
@media (hover:hover) and (pointer:fine){
  .proof:hover .proof-shot img,.proof:focus-visible .proof-shot img{transform:scale(1.02)}
}
.proof-meta{padding:0 1.2rem 1.4rem}
.proof-meta b{font-family:'Bricolage Grotesque';font-weight:600;font-size:1.05rem;display:block;margin-bottom:.4rem}
.proof-meta p{font-size:.88rem;opacity:.85;margin-bottom:.7rem}
.proof-domain{font-size:.78rem;font-weight:700;letter-spacing:.03em;color:var(--c-accent)}
.proof:focus-visible{outline:2px solid var(--amber);outline-offset:-2px}

.proof[data-client="hartman"]{--c-bg:#ffffff;--c-ink:#1c1c1c;--c-accent:#7a5c12}
.proof[data-client="jbester"]{--c-bg:#1e2329;--c-ink:#f4f5f6;--c-accent:#ff4d4d}
.proof[data-client="liplapa"]{--c-bg:#f3f1ec;--c-ink:#16233f;--c-accent:#8a1f1f}
.proof[data-client="marlo"]{--c-bg:#0f100e;--c-ink:#f0ece1;--c-accent:#c8873f}
/* Hartman and JB's --c-accent are darkened/lightened from the brief's literal
   #fcbc45 / sampled #f90008 (measured 2.73:1 and 3.78:1 on their card grounds —
   both fail WCAG AA for the small bold caption text that uses this token).
   #7a5c12 (6.24:1 on white) and #ff4d4d (4.84:1 on #1e2329) keep the same hue
   family — still readably "gold" and "red" — while passing AA. LipLapa and
   Marlo's brief values already pass at this size and are used as specified. */

/* ==========================================================================
   REVIEW STRIP — real Google reviews, inside the Range Wall (brief §6a).

   Attributed by reviewer name only. Kern could not confirm which reviewer
   belongs to which client, so nothing is paired to a proof card. Deliberately
   has no motion: this is plain content, not part of the Range Wall reveal.
   The 1px dividers echo the "How it works" three-column rule one section down
   rather than introducing a new pattern.
   ========================================================================== */
.review-strip{margin-top:3rem;border-top:1px solid var(--line);padding-top:2.2rem}
.review-rating{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:.35rem .9rem;
  margin-bottom:1.6rem;font-size:1rem;color:var(--ink);
}
.review-stars{color:var(--accent);font-size:1.15rem;letter-spacing:.08em}
.review-rating b{font-family:'Bricolage Grotesque';font-weight:700;font-size:1.35rem}
.review-rating a{
  color:var(--accent);font-weight:700;font-size:.95rem;text-decoration:none;
  border-bottom:1px solid transparent;
}
.review-rating a:hover,.review-rating a:focus-visible{border-bottom-color:var(--accent)}
.review-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);
}
.review-grid li{background:var(--bg-alt);padding:1.5rem}
.review-grid p{font-size:1rem;line-height:1.6;color:var(--ink);margin-bottom:.9rem}
/* --ink, not --muted: 13.6px is below the 16px floor --muted needs on --bg-alt (§2) */
.review-grid span{font-size:.85rem;font-weight:700;letter-spacing:.02em;color:var(--ink)}

/* ==========================================================================
   HOW IT WORKS
   ========================================================================== */
.steps{
  display:grid;grid-template-columns:repeat(3,1fr);
  margin-top:2.6rem;
}
.step{padding:0 2rem}
.step:not(:first-child){border-left:1px solid var(--line)}
.step-bar{width:26px;height:3px;background:var(--amber);margin-bottom:1.1rem}
.step-num{
  font-family:'Bricolage Grotesque';font-weight:700;font-size:3.2rem;
  color:var(--accent);line-height:1;margin-bottom:.8rem;
}
.step p{color:var(--muted);margin-bottom:0}

/* ==========================================================================
   PRICING
   ========================================================================== */
.price-rows{display:flex;flex-direction:column;gap:1.2rem;margin-top:2.6rem}
.price-row{
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:1.8rem 2rem;
}
.price-row h3{margin-bottom:.3rem}
.price-row .price-desc{color:var(--muted);font-size:.95rem;max-width:44ch}
.price-amount{
  font-family:'Bricolage Grotesque';font-weight:800;font-size:2.1rem;color:var(--ink);
  white-space:nowrap;
}
.price-amount span{font-family:'Manrope';font-weight:700;font-size:.9rem;color:var(--muted)}
.price-row .btn{flex:0 0 auto}

/* ==========================================================================
   WHY OWNERS STAY
   ========================================================================== */
.promise-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1.8rem;margin-top:2.6rem;
}
.promise h3{color:var(--accent);margin-bottom:.5rem}
.promise p{color:var(--muted);margin-bottom:0;font-size:.95rem}

/* ==========================================================================
   WHO YOU'RE DEALING WITH
   ========================================================================== */
.who-panel{
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  display:grid;grid-template-columns:.4fr .6fr;gap:2.6rem;align-items:center;
  padding:2.6rem;margin-top:1rem;
}
/* height:auto required — same height="600" attribute-pinning bug as .proof-shot img above
   (Reviewer finding R-1, 2026-10-01): without it, height stays literal 600px at every width
   while the grid column's width responds, swinging the crop from squat to a narrow sliver
   either side of the 900px breakpoint. */
.who-photo img{border-radius:var(--radius);object-fit:cover;aspect-ratio:1/1;object-position:center 28%;width:100%;height:auto}
.who-copy p{font-size:1.02rem;color:var(--ink)}
.who-copy p:last-child{margin-bottom:0}
.who-name{font-family:'Bricolage Grotesque';font-weight:700;font-size:1.3rem;margin-bottom:.2rem}
.who-role{color:var(--muted);font-size:.9rem;margin-bottom:1.2rem}

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq-list{margin-top:2.6rem;border-top:1px solid var(--line)}
.faq-list details{border-bottom:1px solid var(--line);padding:1.3rem 0}
.faq-list summary{
  cursor:pointer;font-family:'Bricolage Grotesque';font-weight:600;font-size:1.1rem;
  display:flex;justify-content:space-between;align-items:center;gap:1rem;
  list-style:none;
}
.faq-list summary::-webkit-details-marker{display:none}
.faq-list summary::after{content:"+";font-size:1.4rem;color:var(--accent);flex:0 0 auto}
.faq-list details[open] summary::after{content:"–"}
.faq-list p{margin-top:.9rem;color:var(--muted);max-width:60ch}

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact-grid{display:grid;grid-template-columns:1fr 1fr;gap:3rem;align-items:center}
.contact-links{display:flex;flex-direction:column;gap:1rem;margin-top:2rem}
.contact-links a{
  text-decoration:none;color:var(--ink-inv);font-size:1.02rem;
  display:flex;align-items:center;gap:.6rem;
}
.contact-links a:hover{color:var(--amber)}
/* .contact-links a{color:var(--ink-inv)} above has higher specificity (class +
   element) than .btn-amber{color:var(--ink)} (one class), so without this it
   silently wins and puts pale ink-inv text on the amber button — measured
   1.94:1, a real failure, not the visible-amber-button-with-invisible-text
   bug Kern's brief flags for the live site (§2), just relocated to this one
   spot. This restores --ink text at 6.96:1 and stops hover repainting it amber-on-amber. */
.contact-links a.btn{color:var(--ink)}
.contact-links a.btn:hover{color:var(--ink)}

/* ==========================================================================
   FOOTER
   ========================================================================== */
footer{background:var(--deep);color:var(--muted-inv);border-top:1px solid var(--line-inv)}
.foot-row{
  display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;
  padding-block:2.2rem;font-size:.85rem;
}
.foot-brand{display:flex;align-items:center;gap:.6rem;color:var(--ink-inv)}
.foot-brand img{width:32px;height:32px}
.foot-links{display:flex;gap:1.4rem;flex-wrap:wrap}
.foot-links a{text-decoration:none;color:var(--muted-inv)}
.foot-links a:hover{color:var(--amber)}

/* ==========================================================================
   MOBILE STICKY WHATSAPP BAR
   ========================================================================== */
.sticky-wa{
  display:none;position:fixed;left:0;right:0;bottom:0;z-index:60;
  background:var(--amber);color:var(--ink);text-decoration:none;
  align-items:center;justify-content:center;gap:.5rem;
  height:52px;font-weight:700;font-size:.95rem;
}

/* ==========================================================================
   GEO-SUGGESTION BANNER — only ever appears if /api/geo resolves to a
   mismatched region. In local preview this stays hidden, always (see build
   handoff). Reveal state controlled entirely by JS adding .show.
   ========================================================================== */
.geo-banner[hidden]{display:none}
.geo-banner{
  background:var(--accent);color:#fff;
  display:flex;align-items:center;justify-content:center;gap:1rem;
  text-align:center;padding:.8rem 1.2rem;font-size:.88rem;
  opacity:0;transform:translateY(-8px);transition:transform .2s ease,opacity .2s ease;
}
.geo-banner.show{opacity:1;transform:translateY(0)}
.geo-banner a{color:#fff;font-weight:700;text-decoration:underline}
.geo-banner button{
  background:none;border:0;color:#fff;font-size:1.1rem;cursor:pointer;line-height:1;
  padding:.2rem .4rem;
}

/* ==========================================================================
   REDUCED MOTION — mandatory, per design brief §8.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .reveal,.hero-anim,.proof{animation:none!important;opacity:1!important;transform:none!important}
  /* The finished assembled frame, immediately — not a faster animation (§4.2c) */
  .illo-nav,.illo-image,.illo-lines,.illo-btn{animation:none!important;opacity:1!important;transform:none!important}
  .geo-banner{transition:none}
  .proof-shot img{transition:none}
  html{scroll-behavior:auto}
}

/* ==========================================================================
   VIEW TRANSITIONS — free cross-fade between the three real pages.
   ========================================================================== */
@view-transition{navigation:auto}
/* Pass 3: only the logo carries a shared name. The hero illustration is
   generated the same way on all three pages, so it needs no shared identity
   to cross-fade cleanly (brief §8). */
.nav-brand img{view-transition-name:site-logo}

/* ==========================================================================
   scroll-margin for anchored sections
   ========================================================================== */
#work,#how,#pricing,#faq{scroll-margin-top:84px}

/* ==========================================================================
   MOBILE INTENT — breakpoints per design brief §10
   ========================================================================== */
@media (max-width:900px){
  .nav-links{display:none}
  .nav-cta{display:none}
  .nav-row .region-switch{display:none}
  .nav-burger{display:block}
  .nav-drop.open{
    display:block;position:absolute;top:100%;left:0;right:0;
    background:var(--deep);border-bottom:1px solid var(--line-inv);
    padding:1.2rem 1.5rem 1.6rem;
  }
  .nav-drop .nav-links{display:flex;flex-direction:column;gap:0;margin-bottom:1rem}
  /* display:block + full width so the tap target is the whole row, not just the
     text's own width — align-items:center (inherited from the shared desktop rule)
     left items sized-to-content and centred, giving links like "FAQ" a ~28px-wide
     hit area. Reviewer finding R-2, 2026-10-01. */
  .nav-drop .nav-links a{display:block;width:100%;padding-block:.7rem;border-bottom:1px solid var(--line-inv)}
  .nav-drop .region-switch{margin-bottom:1rem}
  .nav-drop .btn-amber{display:flex;width:100%;justify-content:center}

  /* Hero goes one column and the illustration drops below the CTA row and the
     fact chips — the promise must be read before the illustration on a phone
     (§10). Same 4/3 box, smaller rendered size; the scroll mechanism is
     unchanged, because a view timeline tracks position, not pixel size. */
  .hero-grid{grid-template-columns:1fr}
  /* max-width, not full bleed: below 900 the illustration must stay subordinate
     to the promise it sits under, and 720px of mock site on a tablet reads as
     the main event. §10's "smaller rendered size", made a number. */
  .hero-illustration{order:3;margin-top:1.4rem;max-width:520px}

  .proof-grid{grid-template-columns:repeat(2,1fr)}
  .review-grid{grid-template-columns:repeat(3,1fr)}
  .steps{grid-template-columns:1fr}
  .step:not(:first-child){border-left:0;border-top:1px solid var(--line);padding-top:2rem;margin-top:0}
  .promise-grid{grid-template-columns:repeat(2,1fr)}
  .who-panel{grid-template-columns:1fr;text-align:left}
  .contact-grid{grid-template-columns:1fr}
}

@media (max-width:820px){
  .sticky-wa{display:flex}
  footer{padding-bottom:calc(52px + 1rem)}
  .nav-cta{display:none}
}

@media (max-width:760px){
  .proof-grid{
    grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:88vw;
    overflow-x:auto;scroll-snap-type:x mandatory;border-left:0;border-right:0;
  }
  .proof{scroll-snap-align:start}
  /* Review strip collapses the same way the proof grid does, one card at 85vw */
  .review-grid{
    grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:85vw;
    overflow-x:auto;scroll-snap-type:x mandatory;border-left:0;border-right:0;
  }
  .review-grid li{scroll-snap-align:start}
  .price-row{flex-direction:column;align-items:flex-start;gap:1rem}
  .price-row .btn{width:100%;justify-content:center}
}

@media (max-width:560px){
  .hero{padding-block:2.6rem}
  h1{font-size:2.35rem}
  .hero-chips{justify-content:center;text-align:center}
  .who-photo img{aspect-ratio:auto}
}
