/* ════════════════════════════════════════════════════════════
   GREYHOUND DESIGNS — master template
   Structure mirrors oakharborwebdesigns.com; motion system is
   rebuilt from scratch and documented inline.
   Search for [SWAP] to find everything you change per client.
   ════════════════════════════════════════════════════════════ */

/* ─── 1. TOKENS ────────────────────────────────────────────
   Token names follow the CodeStitch convention the reference
   site uses (--primary, --headerFont, --sectionPadding …) so
   any CodeStitch component you paste in inherits your brand
   with zero edits. Motion tokens are the addition. */
:root{
  /* [SWAP] brand */
  --primary:#0d2b45;            /* deep navy — sections, buttons, headings */
  --primaryLight:#12395c;
  --secondary:#2fb0d9;          /* bright accent — CTAs, fills, glow */
  --secondaryLight:#8fdcf2;
  --secondaryInk:#17708c;       /* the accent, dark enough to be TEXT on a light
                                   surface. #2fb0d9 is 2.5:1 on white and fails
                                   AA at any size; this is 5.6:1 on white and
                                   5.2:1 on --surfaceAlt. Fills and glows keep
                                   using --secondary; anything a person has to
                                   READ uses this. */

  /* neutrals */
  --headerColor:#12181f;
  --bodyTextColor:#55606d;
  --bodyTextColorWhite:#e6edf5;
  --surface:#ffffff;
  --surfaceAlt:#f5f7f9;         /* the reference uses #f7f7f7 for its banded sections */
  --line:#e2e8ef;

  /* type — fluid, clamp-based, same approach as the reference */
  --headerFont:"Oswald", Arial Narrow, Arial, sans-serif;
  /* the wordmark only. Oswald is condensed and dense; against the fine
     single-line hound it read compressed and generic. Archivo is the same
     width as the mark, with open counters that survive the 1.05rem header
     size and the .24em tracking on DESIGNS. Headings stay Oswald. */
  --logoFont:"Archivo", "Segoe UI", Helvetica, Arial, sans-serif;
  --bodyFont:"Source Sans 3", -apple-system, Segoe UI, Roboto, sans-serif;
  --scriptFont:"Yellowtail", cursive;      /* the neon signature face */
  --topperFontSize:clamp(0.8125rem, 1.6vw, 1rem);
  --headerFontSize:clamp(1.9375rem, 3.9vw, 3.0625rem);
  --bodyFontSize:1rem;

  /* space & shape */
  --sectionPadding:clamp(3.75rem, 7.82vw, 6.25rem) 1rem;
  --maxw:1280px;
  --radius:12px;
  --radiusLg:24px;
  --pill:60px;                   /* reference uses a 60px pill on every button */
  --shadow:0 4px 14px rgba(13,43,69,.07), 0 12px 34px rgba(13,43,69,.06);
  --shadowLg:0 18px 40px rgba(13,43,69,.14), 0 30px 70px rgba(13,43,69,.10);

  /* ─── MOTION TOKENS ───────────────────────────────────────
     The reference site uses bare `0.3s` everywhere, which means
     the browser default `ease` curve. That curve eases IN as well
     as out, so movement starts sluggish. Every duration below
     pairs with an explicit curve instead — this single change is
     the biggest perceptible quality difference between the two
     sites. */
  --durFast:150ms;
  --dur:300ms;                   /* matches the reference's 0.3s vocabulary */
  --durSlow:600ms;               /* their transform duration */
  --durReveal:800ms;
  --easeOut:cubic-bezier(.22,1,.36,1);        /* workhorse: fast start, long settle */
  --easeInOut:cubic-bezier(.65,0,.35,1);
  --spring:cubic-bezier(.34,1.56,.64,1);      /* slight overshoot for hovers */
  --revealShift:28px;
  --stagger:90ms;
}

/* ─── 2. RESET / BASE ─────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--surface);color:var(--bodyTextColor);
  font:var(--bodyFontSize)/1.65 var(--bodyFont);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
  transition:background-color var(--durSlow) var(--easeOut), color var(--durSlow) var(--easeOut);
}
img,svg,video{display:block;max-width:100%}
h1,h2,h3{font-family:var(--headerFont);color:var(--headerColor);font-weight:700;
  line-height:1.1;text-transform:uppercase;letter-spacing:.01em;margin:0 0 .5em}
h1{font-size:clamp(2.4375rem,5.2vw,4.0625rem)}
h2{font-size:var(--headerFontSize)}
h3{font-size:clamp(1.25rem,2vw,1.5625rem)}
p{margin:0 0 1.1em}
ul{margin:0;padding:0;list-style:none}
a{color:inherit}
button{font:inherit;border:0;background:none;color:inherit;cursor:pointer}
:focus-visible{outline:3px solid var(--secondary);outline-offset:3px;border-radius:6px}

.wrap{width:min(100% - 2rem, var(--maxw));margin-inline:auto}
.section{padding:var(--sectionPadding);position:relative}
.section--alt{background:var(--surfaceAlt)}
.section--navy{background:var(--primary);color:var(--bodyTextColorWhite)}
.section--navy h2,.section--navy h3{color:#fff}

/* the "topper" — the small uppercase kicker above every heading.
   The reference uses one on all 11 sections; it is the cheapest
   way to make a page look art-directed rather than assembled. */
.topper{display:block;font-family:var(--headerFont);font-size:var(--topperFontSize);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--secondaryInk);margin-bottom:.6rem}
/* on the dark sections the bright accent is the legible one, so it comes back */
.section--navy .topper,.hero .topper,.band .topper{color:var(--secondaryLight)}
.lead{font-size:clamp(1rem,.95rem + .3vw,1.1875rem);max-width:60ch}
.head{max-width:56ch;margin-bottom:clamp(2.25rem,4vw,3.5rem)}
.head.center{text-align:center;margin-inline:auto}
/* .head's 56ch is a heading measure, not a paragraph one — a multi-sentence lead
   inside it stacked up seven ragged centered lines. This opens the block up for
   the lead and pins the h2 to 34rem separately, so headline wrapping is
   unchanged at two lines. Note the lead now runs ~98 characters per line at
   1440, which is past the usual ~75 ceiling for comfortable reading; that is a
   deliberate call for a short intro paragraph, not a pattern to reuse for body
   copy. Drop --head--wide toward 44rem if it ever reads long. */
.head--wide{max-width:58rem}
.head--wide h2{max-width:34rem;margin-inline:auto}
.head--wide .lead{max-width:none}
.grid{display:grid;gap:clamp(1.25rem,2.4vw,2rem)}
@media(min-width:48rem){.grid--3{grid-template-columns:repeat(3,1fr)}}
@media(min-width:48rem){.grid--2{grid-template-columns:repeat(2,1fr)}}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-999px;top:0;z-index:999;background:#fff;padding:.75rem 1.25rem}
.skip:focus{left:.5rem;top:.5rem}

/* ─── 3. MOTION LAYER ──────────────────────────────────────
   Portable. Copy this whole block into any project; nothing in
   it is bound to a specific component.

   The reference site has NO scroll animation at all — its only
   JS-driven motion is the header shrink. Sections 3a–3b are the
   main upgrade over it.                                        */

/* 3a. SCROLL REVEAL ────────────────────────────────────────
   A transition, not a keyframe animation, so the element settles
   at its real layout position and nothing shifts. Only opacity
   and transform animate — both are compositor properties, so this
   holds 60fps on a $150 Android, which matters when half your
   clients' traffic is mobile. */
.js [data-reveal]{
  opacity:0;
  transform:translate3d(0,var(--revealShift),0);
  transition:opacity var(--durReveal) var(--easeOut),
             transform var(--durReveal) var(--easeOut);
  transition-delay:var(--d,0ms);
  will-change:transform,opacity;
}
.js [data-reveal="left"]  {transform:translate3d(calc(var(--revealShift)*-1.7),0,0)}
.js [data-reveal="right"] {transform:translate3d(calc(var(--revealShift)*1.7),0,0)}
.js [data-reveal="scale"] {transform:scale(.93)}
.js [data-reveal="clip"]  {clip-path:inset(0 0 100% 0);transform:none;
  transition:opacity var(--durReveal) var(--easeOut), clip-path var(--durReveal) var(--easeOut)}
[data-reveal].is-in{
  opacity:1;transform:none;
  will-change:auto;   /* released once done — a permanent will-change
                         pins a GPU layer per element and costs memory */
}
/* The clip reset belongs ONLY to the clip variant. Applying
   clip-path:inset(0) to every revealed element crops anything that
   deliberately sticks out of its box — the icon tiles straddling the
   card edge, the "Most popular" badge, and every outer box-shadow. */
[data-reveal="clip"].is-in{clip-path:inset(0 0 0 0)}

/* 3b. STAGGER — JS writes --d on each child, so no :nth-child
   chains and it works for any number of items. */
[data-stagger]>*{transition-delay:var(--d,0ms)}

/* 3c. HEADER — floating card at top, flat bar once scrolled.
   This is the reference site's signature move: at scroll 0 the
   header is an inset rounded card with a shadow; past ~100px it
   goes full-bleed and square. Their version transitions `top`,
   `width` and `max-width`, all of which force layout on every
   frame. This version animates only compositor-safe properties
   plus the border radius. */
.hdr{
  position:fixed;top:0;left:50%;transform:translateX(-50%);
  width:min(100% - 2rem, var(--maxw));z-index:100;
  margin-top:.75rem;border-radius:var(--radiusLg);
  background:var(--surface);box-shadow:var(--shadow);
  transition:width var(--dur) var(--easeOut),
             margin-top var(--dur) var(--easeOut),
             border-radius var(--dur) var(--easeOut),
             box-shadow var(--dur) var(--easeOut),
             background-color var(--dur) var(--easeOut);
}
.hdr.is-stuck{
  width:100%;margin-top:0;border-radius:0;
  background:rgba(255,255,255,.92);
  backdrop-filter:saturate(180%) blur(12px);
  -webkit-backdrop-filter:saturate(180%) blur(12px);
}
.hdr.is-stuck .hdr__in{padding-block:.6rem;
  width:min(100% - 1rem, var(--maxw));margin-inline:auto;padding-inline:0}
.hdr.is-stuck .logo{transform:scale(.88)}
.logo{transform-origin:left center;transition:transform var(--dur) var(--easeOut)}

/* 3d. UNDERLINE SWEEP — scaleX on a pseudo-element.
   Never animate `width` for this; width is a layout property and
   recalculates the line box every frame. */
.nav a{position:relative;text-decoration:none;font-family:var(--headerFont);
  font-weight:600;text-transform:uppercase;font-size:.9rem;letter-spacing:.04em;
  padding-block:.4rem;color:var(--headerColor);
  transition:color var(--dur) var(--easeOut)}
.nav a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--secondary);transform:scaleX(0);transform-origin:right center;
  transition:transform var(--dur) var(--easeOut)}
.nav a:hover,.nav a:focus-visible{color:var(--secondaryInk)}
.nav a:hover::after,.nav a:focus-visible::after{transform:scaleX(1);transform-origin:left center}

/* 3e. BUTTONS — the reference cross-fades background-color on
   hover. A wipe reads as more deliberate and costs the same: a
   pseudo-element translated out of frame, slid back in. */
.btn{
  --bg:var(--primary);--fg:#fff;--wipe:var(--secondary);
  position:relative;isolation:isolate;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  padding:1em 2.25em;border-radius:var(--pill);
  font-family:var(--headerFont);font-weight:700;font-size:1rem;
  text-transform:uppercase;letter-spacing:.04em;text-decoration:none;
  color:var(--fg);background:var(--bg);box-shadow:var(--shadow);
  transition:transform var(--dur) var(--spring),
             box-shadow var(--dur) var(--easeOut),
             color var(--dur) var(--easeOut);
}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--wipe);
  transform:translateY(101%);transition:transform var(--durSlow) var(--easeOut)}
.btn:hover,.btn:focus-visible{transform:translateY(-3px);box-shadow:var(--shadowLg)}
.btn:hover::before,.btn:focus-visible::before{transform:translateY(0)}
.btn:active{transform:translateY(-1px);transition-duration:var(--durFast)}
.btn--accent{--bg:var(--secondary);--fg:var(--primary);--wipe:#fff}
.btn--ghost{--bg:transparent;--fg:#fff;--wipe:#fff;--fgHover:var(--primary);
  box-shadow:inset 0 0 0 2px rgba(255,255,255,.35)}
/* The wipe covers the button on hover AND focus, so the text has to change
   on both or it gets painted onto its own background. --fgHover is a variable
   because a ghost button sitting on a light card overrides --wipe, and what it
   wipes to is what decides the readable text color. */
.btn--ghost:hover,.btn--ghost:focus-visible{color:var(--fgHover)}
.btn__arw{transition:transform var(--dur) var(--spring)}
.btn:hover .btn__arw{transform:translateX(5px)}

/* 3f. CARD LIFT + ICON KICK */
.card{position:relative;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:3.5rem 1.75rem 2rem;height:100%;
  display:flex;flex-direction:column;
  transition:transform var(--dur) var(--easeOut),
             box-shadow var(--dur) var(--easeOut),
             border-color var(--dur) var(--easeOut)}
/* The grid stretches every card in a row to the same height, so pushing the link
   down with an auto top margin lands them all on one line regardless of how long
   the paragraph above ran. align-self is load-bearing: .tlink is inline-flex, and
   a column flex item stretches to full width by default, which would drag its
   underline across the whole card. */
.card .tlink{margin-top:auto;align-self:flex-start}
.card:hover{transform:translateY(-8px);box-shadow:var(--shadowLg);border-color:transparent}
/* icon tile straddling the top edge — lifted straight from the
   reference's services section, it is what stops a 3-card row
   reading as a generic bootstrap grid */
.card__ico{position:absolute;top:-28px;left:1.75rem;width:72px;height:72px;
  display:grid;place-items:center;border-radius:14px;
  background:var(--primary);color:#fff;box-shadow:var(--shadow);
  transition:transform var(--dur) var(--spring), background-color var(--dur) var(--easeOut)}
.card:hover .card__ico{transform:translateY(-4px) rotate(-6deg) scale(1.06);background:var(--secondary)}
.card__ico svg{width:34px;height:34px}
/* The greyhound is a filled shape in this brand, not a line icon, so it is masked
   with currentColor exactly like .logo__mark rather than drawn as a stroke path.
   Wider and shorter than the 34px line icons because the silhouette is 1.83:1 —
   matching their height would leave it floating in the tile. */
.ico-dog{display:block;width:46px;height:25px;background:currentColor;
  -webkit-mask:url(greyhound-running.webp) center/contain no-repeat;
          mask:url(greyhound-running.webp) center/contain no-repeat}
.card h3{margin-bottom:.5rem}
.card p{font-size:.97rem;margin-bottom:1.25rem}
/* inline-FLEX, not inline-block: the global reset at the top of this file makes
   every svg display:block, so inside an inline-block the arrow drops onto its
   own line under the label. Flex blockifies it into a row instead, and the gap
   this rule has always transitioned finally has something to animate. */
.tlink{display:inline-flex;align-items:center;gap:.45rem;
  font-family:var(--headerFont);font-weight:600;font-size:.9rem;
  text-transform:uppercase;letter-spacing:.04em;color:var(--headerColor);text-decoration:none;
  border-bottom:2px solid var(--secondary);padding-bottom:2px;
  transition:color var(--dur) var(--easeOut), gap var(--dur) var(--easeOut)}
.tlink:hover{gap:.75rem}
.tlink .btn__arw{flex:none}
/* --headerColor, not --primary: --primary goes near-black in dark mode, which
   made these three links 1.1:1 against the card — invisible. */
.tlink:hover{color:var(--secondaryInk)}

/* 3g. WORK TILE — image zoom under a fixed frame, caption veil
   sliding up from the bottom edge. */
.work{display:block;text-decoration:none;color:inherit}
/* 3:2 matches the device-mockup shots, so nothing gets cropped. The shots are cut
   out to transparent PNG-style alpha, so the frame stays transparent in both
   themes and the devices sit straight on the section — no white plate. */
.frame{position:relative;overflow:hidden;border-radius:var(--radius);background:transparent}
.frame img{width:100%;height:auto;aspect-ratio:3/2;object-fit:contain;display:block;
  transition:transform var(--durSlow) var(--easeOut)}
.veil{position:absolute;inset:auto 0 0 0;padding:1.5rem;color:#fff;
  background:linear-gradient(to top,rgba(13,43,69,.94),rgba(13,43,69,0));
  transform:translateY(100%);opacity:0;
  transition:transform var(--durSlow) var(--easeOut), opacity var(--dur) linear}
.veil p{margin:0;font-size:.9rem;color:#d6e4f0}
.work:hover .frame img{transform:scale(1.07)}
.work:hover .veil{transform:translateY(0);opacity:1}
.work__meta{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;margin-top:1.1rem}
.work__meta h3{margin:0;font-size:1.1rem}
.work__meta span{font-family:var(--headerFont);font-size:.78rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--secondaryInk)}

/* 3h. ACCORDION — grid-template-rows 0fr→1fr animates to
   auto height with no JS measuring and no max-height guessing. */
.acc__panel{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows var(--durSlow) var(--easeOut)}
.acc__panel>div{overflow:hidden}
.acc__item.is-open .acc__panel{grid-template-rows:1fr}
.acc__btn .chev{transition:transform var(--dur) var(--easeOut)}
.acc__item.is-open .chev{transform:rotate(180deg)}

/* 3i. COUNTERS — tabular figures stop the number jittering
   wider and narrower as digits tick over. */
.stat b{display:block;font-family:var(--headerFont);font-weight:700;color:#fff;
  font-size:clamp(2.75rem,1.8rem + 3.4vw,4.5rem);line-height:1;
  font-variant-numeric:tabular-nums}

/* 3j. BURGER → X */
.burger span{display:block;width:26px;height:2px;background:var(--headerColor);border-radius:2px;
  transition:transform var(--dur) var(--easeOut), opacity var(--durFast) linear}
.burger span+span{margin-top:7px}
body.nav-open .burger span:nth-child(1){transform:translateY(9px) rotate(45deg)}
body.nav-open .burger span:nth-child(2){opacity:0}
body.nav-open .burger span:nth-child(3){transform:translateY(-9px) rotate(-45deg)}

/* 3k. SCROLL PROGRESS — one transform write per frame, driven
   by rAF rather than by a scroll handler doing layout reads. */
.prog{position:fixed;top:0;left:0;height:3px;width:100%;z-index:200;
  background:var(--secondary);transform:scaleX(0);transform-origin:left;will-change:transform}

/* 3l. REDUCED MOTION — non-negotiable, and note that reveals
   resolve to visible. Forgetting this line is the single most
   common accessibility bug in reveal-on-scroll code: the user
   gets a permanently blank page. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
  [data-reveal]{opacity:1 !important;transform:none !important;clip-path:none !important}
  .star,.shooter,.sat{display:none !important}
}

/* ─── 4. COMPONENTS ───────────────────────────────────────── */
.hdr__in{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:1rem 1.5rem;transition:padding var(--dur) var(--easeOut)}
.logo{display:flex;align-items:center;gap:.65rem;text-decoration:none;color:var(--headerColor)}
/* the mark — logo-greyhound-head.svg, a single-path hound silhouette. It is
   painted as a mask filled with currentColor rather than dropped in as an
   <img>, so it inherits .logo's colour and needs no per-theme variant: near
   -black on the light header, near-white on the dark one, white in the
   footer. The old PNG shipped an opaque white background and had to sit on a
   chip to survive a dark surface; the silhouette has real alpha, so the chip
   is gone. The path inside the file is filled #000, not currentColor — a mask
   reads only the alpha channel, and currentColor in an externally referenced
   SVG resolves against that file's own context, not this one. viewBox is
   757×712, so width tracks height at 1.063:1. */
.logo__mark{height:44px;width:47px;flex:none;background:currentColor;
  -webkit-mask:url(logo-greyhound-head.svg) center/contain no-repeat;
          mask:url(logo-greyhound-head.svg) center/contain no-repeat;
  transition:height var(--dur) var(--easeOut),width var(--dur) var(--easeOut)}
.hdr.is-stuck .logo__mark{height:40px;width:42.5px}
.logo__txt{font-family:var(--logoFont);font-weight:700;font-size:1.05rem;line-height:1.05;
  text-transform:uppercase;letter-spacing:.02em}
.logo__txt small{display:block;font-size:.62rem;letter-spacing:.24em;font-weight:500;color:var(--bodyTextColor)}
/* the neon script wordmark — only rendered in dark mode */
.logo__neon{display:none;font-family:var(--scriptFont);font-size:1.15rem;
  text-transform:none;letter-spacing:0;color:var(--secondaryLight);line-height:1}
.nav{display:none}
.nav ul{display:flex;align-items:center;gap:1.75rem}
.hdr__cta{display:none}
.tools{display:flex;align-items:center;gap:.75rem}
.themeBtn{width:42px;height:42px;border-radius:50%;display:grid;place-items:center;
  transition:background-color var(--dur) var(--easeOut), transform var(--dur) var(--spring)}
.themeBtn:hover{background:var(--surfaceAlt);transform:rotate(-18deg) scale(1.08)}
.themeBtn svg{width:22px;height:22px}
.themeBtn .sun{display:none}
.burger{padding:.6rem;border-radius:10px}
@media(min-width:62rem){
  .nav{display:block}.hdr__cta{display:inline-flex}.burger{display:none}
}

/* mobile drawer */
.drawer{position:fixed;inset:0;z-index:99;background:var(--surface);
  padding:7rem 1.5rem 2rem;transform:translateX(100%);visibility:hidden;
  transition:transform var(--durSlow) var(--easeOut), visibility 0s linear var(--durSlow)}
body.nav-open .drawer{transform:none;visibility:visible;transition-delay:0s}
.drawer ul{display:grid}
.drawer a{display:block;padding:1rem 0;border-bottom:1px solid var(--line);text-decoration:none;
  font-family:var(--headerFont);font-weight:600;font-size:1.4rem;text-transform:uppercase;
  color:var(--headerColor);opacity:0;transform:translateY(16px);
  transition:opacity var(--dur) var(--easeOut), transform var(--dur) var(--easeOut)}
body.nav-open .drawer a{opacity:1;transform:none;transition-delay:var(--d,0ms)}
.drawer .btn{margin-top:1.75rem;width:100%}

/* hero */
.hero{position:relative;overflow:hidden;background:var(--primary);color:var(--bodyTextColorWhite);
  padding:clamp(9rem,17vw,13rem) 1rem clamp(4rem,8vw,7rem);text-align:center;
  transition:background-color var(--durSlow) var(--easeOut)}
/* no max-width here: the 60rem cap existed to keep centred text to a
   readable measure. The copy is left-aligned beside the devices now,
   so the hero uses the same --maxw as every other section and the
   mockup gets the width back. The lead keeps its own measure below. */
.hero .wrap{position:relative;z-index:2}
.hero h1{color:#fff;margin-bottom:.45em}
.hero .lead{margin-inline:auto;color:#cddcea;font-size:clamp(1.05rem,1rem + .45vw,1.3rem)}
.hero__act{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center;margin-top:2.25rem}
.hero__trust{display:flex;flex-wrap:wrap;gap:1.25rem 2rem;justify-content:center;margin-top:2.75rem;
  font-size:.9rem;color:#cddcea}
.hero__trust li{display:flex;align-items:center;gap:.5rem}
.hero__trust svg{width:18px;height:18px;color:var(--secondary);flex:none}
/* the diagonal cut at the base of the hero, as on the reference */
.hero__cut{position:absolute;left:0;right:0;bottom:-1px;z-index:2;width:100%;height:clamp(40px,5vw,80px);
  fill:var(--surface);transition:fill var(--durSlow) var(--easeOut)}

/* side-by-side */
.sbs{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center}
@media(min-width:56rem){.sbs{grid-template-columns:1fr 1fr}}
.sbs__media{border-radius:var(--radiusLg);overflow:hidden;box-shadow:var(--shadowLg)}
.sbs__media img{width:100%;aspect-ratio:5/4;object-fit:cover}
.checks{display:grid;gap:.85rem;margin:1.5rem 0 2rem}
.checks li{display:flex;gap:.75rem;align-items:flex-start;font-size:1rem}
.checks svg{width:22px;height:22px;flex:none;color:var(--secondary);margin-top:2px}

/* stats */
.stats{display:grid;gap:2.5rem;text-align:center}
@media(min-width:48rem){.stats{grid-template-columns:repeat(3,1fr)}}
.stat p{margin:.5rem 0 0;color:var(--bodyTextColorWhite);font-size:.98rem}

/* pricing */
.price{display:flex;flex-direction:column;padding-top:2.25rem}
.price--best{border-color:var(--secondary);box-shadow:var(--shadowLg)}
.price--best::before{content:"Most popular";position:absolute;top:-14px;left:50%;
  transform:translateX(-50%);background:var(--secondary);color:var(--primary);
  font-family:var(--headerFont);font-size:.72rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;padding:.4rem 1rem;border-radius:var(--pill);white-space:nowrap}
.price__amt{font-family:var(--headerFont);font-weight:700;color:var(--headerColor);
  font-size:clamp(2.25rem,1.7rem + 2vw,3rem);line-height:1;margin:.35rem 0 .1rem}
.price__amt small{font-size:.9rem;font-weight:500;color:var(--bodyTextColor);letter-spacing:0}
.price ul{display:grid;gap:.7rem;margin:1.5rem 0;font-size:.95rem}
.price li{display:flex;gap:.6rem;align-items:flex-start}
.price li svg{width:20px;height:20px;flex:none;color:var(--secondary);margin-top:2px}
.price .btn{margin-top:auto;width:100%}

/* testimonials */
.quote{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:2rem;height:100%;transition:transform var(--dur) var(--easeOut),box-shadow var(--dur) var(--easeOut)}
.quote:hover{transform:translateY(-6px);box-shadow:var(--shadow)}
.quote__stars{color:var(--secondaryInk);letter-spacing:.2em;margin-bottom:.85rem}
.quote blockquote{margin:0 0 1.25rem;color:var(--headerColor);font-size:1.02rem}
.quote figcaption{font-family:var(--headerFont);text-transform:uppercase;font-size:.85rem;
  letter-spacing:.04em;color:var(--headerColor)}
.quote figcaption span{display:block;font-family:var(--bodyFont);text-transform:none;
  letter-spacing:0;font-size:.85rem;color:var(--bodyTextColor)}

/* faq */
.acc{max-width:48rem;margin-inline:auto;border-top:1px solid var(--line)}
.acc__item{border-bottom:1px solid var(--line)}
.acc__btn{width:100%;display:flex;justify-content:space-between;align-items:center;gap:1.5rem;
  padding:1.4rem 0;text-align:left;font-family:var(--headerFont);font-weight:600;
  font-size:1.05rem;text-transform:uppercase;color:var(--headerColor)}
.acc__btn .chev{width:20px;height:20px;flex:none;color:var(--secondaryInk)}
.acc__panel p{margin:0 0 1.4rem;max-width:60ch}

/* cta band */
.band{background:var(--primary);border-radius:var(--radiusLg);padding:clamp(2.5rem,5.5vw,4.5rem) 1.5rem;
  text-align:center;position:relative;overflow:hidden}
/* The hound running off the right edge. Its own asset rather than the filled
   .ico-dog silhouette: a contour drawing matches logo-greyhound-head.svg, which
   is the line the brand is actually drawn in. Masked with white rather than
   dropped in as an <img> so one file serves both themes. Line art is mostly
   empty space, so it needs roughly 3x the opacity a filled shape would — .085
   made it disappear entirely. Sits under the copy on z-index 0; every direct
   child of .band is lifted to 1. Hidden under 48rem, where it would otherwise
   run straight through the heading. */
.band > *{position:relative;z-index:1}
.band::after{content:"";position:absolute;z-index:0;pointer-events:none;
  right:-4%;top:50%;transform:translateY(-50%);width:46%;aspect-ratio:512/280;
  background:#fff;opacity:.30;
  -webkit-mask:url(greyhound-line.webp) center/contain no-repeat;
          mask:url(greyhound-line.webp) center/contain no-repeat}
@media(max-width:47.99rem){.band::after{display:none}}
/* --primary drops to near-black in the dark theme, so white lines gain contrast
   and have to come back down to sit at the same weight. */
[data-theme="dark"] .band::after{opacity:.24}
.band h2{color:#fff}
.band p{color:var(--bodyTextColorWhite);max-width:46ch;margin-inline:auto}
.band__act{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center;margin-top:2rem}

/* footer */
.ftr{background:#0a2138;color:var(--bodyTextColorWhite);padding:clamp(3rem,6vw,5rem) 1rem 2rem}
.ftr__grid{display:grid;gap:2.5rem}
@media(min-width:52rem){.ftr__grid{grid-template-columns:1.9fr 1fr 1.2fr}}
.ftr h4{font-family:var(--headerFont);color:#fff;font-size:.8rem;letter-spacing:.16em;
  text-transform:uppercase;margin:0 0 1rem}
.ftr li{margin-bottom:.6rem;font-size:.94rem}
/* Contact is a labelled list, not a link list: each row is an icon plus a value,
   so it reads as details rather than navigation. The icon is muted against the
   near-white value on purpose — it is a marker, not the content. Rows get more
   air than the link columns because there are only four of them. */
.ftr__contact li{display:flex;align-items:center;gap:.7rem;margin-bottom:1rem}
.ftr__contact svg{width:18px;height:18px;flex:none;color:#8fa6bd;
  fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.ftr a{color:var(--bodyTextColorWhite);text-decoration:none;transition:color var(--dur) var(--easeOut)}
.ftr a:hover{color:var(--secondary)}
.ftr .logo{color:#fff}
.ftr .logo__txt small{color:#8fa6bd}
.ftr__base{margin-top:3rem;padding-top:1.5rem;border-top:1px solid rgba(255,255,255,.13);
  display:flex;flex-wrap:wrap;gap:.75rem 1.5rem;justify-content:space-between;font-size:.85rem}

/* ═══ 5. AFTER DARK ════════════════════════════════════════
   The reference site's whole personality lives in its dark mode:
   a night sky behind the hero with flickering stars, shooting
   stars, a drifting satellite and a neon script wordmark. It is
   the thing people remember, and it costs almost nothing.

   Three things reimplemented rather than copied:
   1. Their shooting star animates `top` and `right`. Both are
      layout properties — every frame recalculates position for
      the whole subtree. Here it's a single translate3d.
   2. They run 26 separate flicker animations at once, which is
      what makes their page stutter on capture. Here the flicker
      is one animation on one element, varied per-star by delay
      and duration through custom properties.
   3. Stars are generated once by JS into a container, not written
      out as 26 hand-authored rules.
   ════════════════════════════════════════════════════════════ */
[data-theme="dark"]{
  --surface:#08131f;
  --surfaceAlt:#0c1a29;
  --primary:#050e18;
  --line:#1c2c3d;
  --headerColor:#f2f7fc;
  --bodyTextColor:#9fb3c8;
  --secondaryInk:var(--secondaryLight);  /* on dark, the accent can go bright
                                            again and still clear AA easily */
}
[data-theme="dark"] body{background:var(--surface);color:var(--bodyTextColor)}
[data-theme="dark"] .hdr{background:rgba(10,24,38,.9);
  box-shadow:0 0 24px rgba(47,176,217,.18), 0 0 60px rgba(47,176,217,.10)}
[data-theme="dark"] .hdr.is-stuck{background:rgba(8,19,31,.94)}
[data-theme="dark"] .card,[data-theme="dark"] .quote{background:var(--surfaceAlt)}
[data-theme="dark"] .burger span{background:#f2f7fc}
[data-theme="dark"] .themeBtn .sun{display:block}
[data-theme="dark"] .themeBtn .moon{display:none}
[data-theme="dark"] .themeBtn:hover{background:rgba(255,255,255,.07)}
[data-theme="dark"] .logo__neon{display:block;animation:neonFlicker 7s linear infinite}
/* the neon says "Designs", so the plain kicker underneath it would be a
   duplicate — hide it in the header only. The footer logo has no neon
   span, so it keeps its own. */
[data-theme="dark"] .hdr .logo__txt small{display:none}
[data-theme="dark"] .drawer{background:var(--surface)}
[data-theme="dark"] .ftr{background:#050e18}
[data-theme="dark"] .hero{background:
  radial-gradient(120% 90% at 50% -10%, #123453 0%, #0a1c2e 45%, #050e18 100%)}
[data-theme="dark"] .hero__cut{fill:var(--surface)}
[data-theme="dark"] .hero__shot img{filter:drop-shadow(0 26px 38px rgba(0,0,0,.7))}
[data-theme="dark"] .sky{opacity:1}
[data-theme="dark"] .btn--accent{animation:btnGlow 4s var(--easeInOut) infinite}

/* the sky container — inert and invisible in light mode, so the
   toggle is instant and nothing is generated twice */
.sky{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  opacity:0;transition:opacity var(--durSlow) var(--easeOut)}

/* 5a. STARS — one keyframe, varied per star by --dur/--delay/--peak.
   Opacity is the only animated property, so each star is a cheap
   composited layer. */
.star{position:absolute;width:var(--size,2px);height:var(--size,2px);border-radius:50%;
  background:#fff;opacity:.2;
  animation:starFlicker var(--dur,3s) ease-in-out var(--delay,0s) infinite}
@keyframes starFlicker{
  0%,100%{opacity:.15;transform:scale(.85)}
  50%    {opacity:var(--peak,.9);transform:scale(1)}
}

/* 5b. SHOOTING STAR — travels on a single transform.
   The long `infinite` cycle with a short visible window is the
   trick that makes it feel occasional rather than decorative:
   the element is transparent for ~92% of its own timeline. */
.shooter{position:absolute;top:var(--y,10%);left:var(--x,70%);
  width:120px;height:2px;border-radius:2px;opacity:0;
  background:linear-gradient(90deg,rgba(255,255,255,0),#fff,rgba(255,255,255,0));
  transform:rotate(35deg) translate3d(0,0,0);
  animation:shoot var(--dur,9s) linear var(--delay,2s) infinite}
@keyframes shoot{
  0%    {opacity:0;transform:rotate(35deg) translate3d(-10vw,0,0) scaleX(.2)}
  3%    {opacity:1}
  10%   {opacity:1;transform:rotate(35deg) translate3d(45vw,0,0) scaleX(1)}
  13%   {opacity:0;transform:rotate(35deg) translate3d(60vw,0,0) scaleX(.4)}
  100%  {opacity:0;transform:rotate(35deg) translate3d(60vw,0,0) scaleX(.4)}
}

/* 5c. SATELLITE — slow orbital drift plus its own rotation.
   Two transforms that would fight each other, so they live on a
   parent/child pair instead of one element. */
.sat{position:absolute;top:9%;left:-8%;font-size:1.5rem;
  animation:orbit 34s var(--easeInOut) infinite}
.sat span{display:block;animation:tumble 9s linear infinite}
@keyframes orbit{
  0%  {transform:translate3d(0,0,0)}
  50% {transform:translate3d(60vw,5vh,0)}
  100%{transform:translate3d(120vw,-2vh,0)}
}
@keyframes tumble{from{transform:rotate(0)}to{transform:rotate(360deg)}}

/* 5d. NEON — the flicker lives at the very edges of the loop, so
   the sign reads as steady with an occasional stutter. That
   asymmetry (5%/95%) is what sells it; an evenly-pulsing glow
   reads as a loading spinner. */
@keyframes neonFlicker{
  0%,100%{color:var(--secondaryLight);filter:blur(1.5px);
    text-shadow:0 0 8px var(--secondary),0 0 18px var(--secondary),0 0 38px var(--secondary)}
  4%,96% {color:#fff;filter:blur(0);
    text-shadow:0 0 6px rgba(47,176,217,.9),0 0 14px rgba(47,176,217,.55)}
}

/* 5e. BUTTON GLOW — layered box-shadows breathing.
   Keep every shadow the same colour and vary only blur radius,
   or the edges crawl. */
@keyframes btnGlow{
  0%,100%{box-shadow:0 0 22px rgba(47,176,217,.28),0 0 44px rgba(47,176,217,.18)}
  50%    {box-shadow:0 0 30px rgba(47,176,217,.42),0 0 72px rgba(47,176,217,.26)}
}

/* 5f. IMAGE PLACEHOLDERS — [SWAP] delete this block and use real
   <img> tags. Kept so the template renders standalone with no
   external requests. */
.ph{width:100%;aspect-ratio:4/3;display:grid;place-items:center;
  font-family:var(--headerFont);text-transform:uppercase;letter-spacing:.14em;
  font-size:.8rem;color:rgba(255,255,255,.85);
  background:linear-gradient(135deg,var(--primary),var(--secondary));
  transition:transform var(--durSlow) var(--easeOut)}
.work:hover .frame .ph{transform:scale(1.07)}
.sbs__media .ph{aspect-ratio:5/4}

/* ─── 5. OWNERSHIP LADDER — the signature element ──────────
   The whole offer is a price that falls to zero. The chart IS
   the product, so it gets the boldest treatment on the page and
   everything around it stays quiet. Bar height is linear in the
   buyout price: $175 x (20 - month), so the silhouette is a
   clean diagonal — which rhymes with the hero's cut edge. */
.ladder__chart{display:flex;align-items:flex-end;gap:clamp(2px,.55vw,7px);
  height:clamp(150px,25vw,250px);margin:clamp(1.5rem,3vw,2.5rem) 0 .8rem}
.js .ladder__bar{transform:scaleY(0)}
.ladder__bar{flex:1 1 0;min-width:0;height:var(--h);border-radius:4px 4px 0 0;
  background:linear-gradient(180deg,var(--secondaryLight),var(--secondary));
  transform-origin:bottom;
  transition:transform 700ms var(--easeOut) var(--dly,0ms)}
[data-reveal].is-in .ladder__bar{transform:scaleY(1)}
/* month 20: no bar left to draw, so the zero point is a lit node */
.ladder__bar--own{background:none;height:100%;position:relative;transform:none}
.js .ladder__bar--own::after{transform:translate(-50%,50%) scale(0)}
.ladder__bar--own::after{content:"";position:absolute;left:50%;bottom:0;
  width:clamp(11px,1.7vw,17px);height:clamp(11px,1.7vw,17px);
  border-radius:50%;background:#fff;
  box-shadow:0 0 0 4px var(--secondary),0 0 30px 7px rgba(47,176,217,.6);
  transition:transform 520ms var(--spring) 1520ms}
[data-reveal].is-in .ladder__bar--own::after{transform:translate(-50%,50%) scale(1)}
.ladder__axis{display:flex;justify-content:space-between;font-family:var(--headerFont);
  font-size:.78125rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:var(--secondaryLight);border-top:1px solid rgba(255,255,255,.2);padding-top:.7rem}
.ladder__key{display:grid;gap:1.1rem;margin-top:clamp(1.9rem,3.6vw,2.9rem)}
@media(min-width:44rem){.ladder__key{grid-template-columns:repeat(4,1fr)}}
.ladder__k b{display:block;font-family:var(--headerFont);font-weight:700;
  font-size:clamp(1.4rem,2.7vw,1.95rem);color:#fff;line-height:1.05;margin-bottom:.15rem}
.ladder__k span{font-size:.92rem;color:var(--bodyTextColorWhite);opacity:.82}
.ladder__k--own b{color:var(--secondaryLight)}

/* ─── 6. PROCESS — numbered because it genuinely is a sequence */
.steps{counter-reset:s;display:grid;gap:clamp(1.5rem,3vw,2rem)}
@media(min-width:52rem){.steps{grid-template-columns:repeat(4,1fr)}}
.step{position:relative;padding-top:3rem}
.step::before{counter-increment:s;content:counter(s,decimal-leading-zero);
  position:absolute;top:0;left:0;right:0;font-family:var(--headerFont);font-weight:700;
  font-size:1rem;letter-spacing:.16em;color:var(--secondaryInk);
  padding-bottom:.6rem;border-bottom:2px solid var(--secondary)}
.step h3{font-size:1.125rem;margin-bottom:.4rem}
.step p{font-size:.95rem;margin:0}

/* ─── 7. PLANS — two options, monthly or the year up front */
.plans{display:grid;gap:clamp(1.25rem,2.4vw,1.75rem);align-items:stretch}
@media(min-width:48rem){.plans{grid-template-columns:1fr 1fr}}
.plan{padding:clamp(1.7rem,3.2vw,2.5rem);border-radius:var(--radiusLg);
  border:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column}
.plan--best{border-color:var(--secondary);box-shadow:var(--shadow)}
.plan__tag{align-self:flex-start;font-family:var(--headerFont);font-weight:600;font-size:.75rem;
  letter-spacing:.13em;text-transform:uppercase;color:var(--secondaryInk);
  background:rgba(47,176,217,.13);padding:.32rem .75rem;border-radius:var(--pill);margin-bottom:1rem}
.plan__amt{font-family:var(--headerFont);font-weight:700;font-size:clamp(2.5rem,5.6vw,3.5rem);
  color:var(--headerColor);line-height:1;margin:0 0 .35rem;text-transform:uppercase}
.plan__amt small{font-size:.3em;color:var(--bodyTextColor);letter-spacing:.05em;font-weight:600}
.plan__note{font-size:.95rem;margin-bottom:1.4rem}
.plan ul{display:grid;gap:.65rem;margin:0 0 1.6rem}
.plan li{display:flex;gap:.65rem;font-size:.96rem;line-height:1.5}
.plan li svg{width:17px;height:17px;flex:none;color:var(--secondaryInk);margin-top:.3em}
.plan .btn{margin-top:auto;align-self:flex-start}

/* ─── 8. SPEED — the wedge, provable with zero clients */
.speed{display:grid;gap:clamp(.9rem,2vw,1.25rem)}
@media(min-width:40rem){.speed{grid-template-columns:1fr 1fr}}
.gauge{padding:clamp(1.4rem,3vw,2rem);border-radius:var(--radius);
  border:1px solid var(--line);background:var(--surface);text-align:center}
.gauge b{display:block;font-family:var(--headerFont);font-weight:700;
  font-size:clamp(2.6rem,7.5vw,4.25rem);line-height:1;margin-bottom:.3rem}
.gauge--them{border-style:dashed}
.gauge--them b{color:#c0453d}
.gauge--us{border-color:var(--secondary)}
.gauge--us b{color:var(--secondaryInk)}
.gauge span{font-size:.92rem;display:block}

/* ─── 9. MONTHLY LIST — numbered items in the care plan */
.mlist{display:grid;gap:clamp(1.4rem,2.8vw,2rem)}
@media(min-width:44rem){.mlist{grid-template-columns:repeat(2,1fr)}}
@media(min-width:68rem){.mlist{grid-template-columns:repeat(3,1fr)}}
.m{display:flex;gap:1rem}
.m__ico{flex:none;width:44px;height:44px;border-radius:12px;display:grid;place-items:center;
  background:rgba(47,176,217,.13);color:var(--secondaryInk)}
.m__ico svg{width:22px;height:22px}
.m h3{font-size:1.05rem;margin-bottom:.35rem}
.m p{font-size:.94rem;margin:0}

/* ═══ 11. OAK-HARBOR-SHAPED SECTIONS ═════════════════════════
   Structure follows oakharborwebdesigns.com's section order and
   its three-tier pricing pattern (the crosses are the point of
   it). Everything visual stays on our own tokens — same shape,
   different suit. */

/* 11a. HERO — copy left, device right */
.hero__copy{text-align:left}
.hero__copy .lead{margin-inline:0;max-width:38rem}
.hero__act,.hero__trust{justify-content:flex-start}
@media(min-width:60rem){
  /* the device column is the wider of the two — the mockup carries more
     detail than the paragraph does, and the copy has its own measure */
  .hero__in{display:grid;grid-template-columns:1fr 1.15fr;gap:clamp(2rem,4vw,4rem);
    align-items:center}
}
.hero__shot{margin-top:2.5rem}
@media(min-width:60rem){.hero__shot{margin-top:0}}
/* the device mockup — a transparent cut-out with no shadow baked in, so
   the shadow is a CSS drop-shadow that traces the actual silhouette of the
   laptop and phone instead of a rectangle. That also means one file covers
   both themes: only the shadow's weight changes below. */
.hero__shot img{display:block;width:100%;height:auto;
  filter:drop-shadow(0 26px 34px rgba(0,0,0,.45))}

/* 11b. OWNER */
.owner{display:grid;gap:clamp(1.75rem,4vw,3.25rem);align-items:center}
@media(min-width:52rem){.owner{grid-template-columns:.8fr 1.2fr}}
/* the portrait — owner.webp is already cropped square, so object-fit is
   only a guard against a replacement file of another shape being dropped in */
.owner__pic img{display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  border-radius:var(--radiusLg);box-shadow:var(--shadow)}

/* 11c. BENEFIT ROWS — check + text, the "What We Offer" grid */
.ben{display:flex;gap:.95rem;align-items:flex-start}
.ben__ic{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  background:var(--secondary);color:#fff;margin-top:.15rem}
.ben__ic svg{width:16px;height:16px}
.ben h3{font-size:1.06rem;margin-bottom:.35rem}
.ben p{font-size:.94rem;margin:0}

/* 11d. PERFORMANCE NOTE */
.perf__note{max-width:64ch;margin:clamp(2rem,4vw,3rem) auto 0;text-align:center;
  color:var(--bodyTextColorWhite);font-size:clamp(1rem,.95rem + .3vw,1.125rem)}

/* 11e. PRICING TIERS — three cards, ticks AND crosses.
   The crosses are the reason this pattern works: a card that only
   ever says yes reads like a brochure. Showing what each option
   drops is what makes the middle one persuasive. */
.tiers{display:grid;gap:clamp(1.25rem,2.4vw,1.75rem);align-items:stretch}
@media(min-width:46rem){.tiers{grid-template-columns:repeat(2,1fr)}}
@media(min-width:70rem){.tiers{grid-template-columns:repeat(3,1fr)}}
/* two-tier variant: keep the cards from stretching to half a wide screen */
.tiers--2{max-width:56rem;margin-inline:auto}
@media(min-width:70rem){.tiers--2{grid-template-columns:repeat(2,1fr)}}
.tier{position:relative;display:flex;flex-direction:column;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radiusLg);
  padding:clamp(1.7rem,3vw,2.3rem);transition:transform var(--dur) var(--easeOut),
  box-shadow var(--dur) var(--easeOut)}
.tier:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.tier--best{border-color:var(--secondary);box-shadow:var(--shadowLg)}
@media(min-width:70rem){.tier--best{transform:scale(1.035)}
  .tier--best:hover{transform:scale(1.035) translateY(-4px)}}
.tier__flag{position:absolute;top:0;left:50%;transform:translate(-50%,-50%);
  font-family:var(--headerFont);font-weight:600;font-size:.72rem;letter-spacing:.13em;
  text-transform:uppercase;color:#fff;background:var(--secondaryInk);
  padding:.36rem .95rem;border-radius:var(--pill);white-space:nowrap}
.tier__name{display:block;font-family:var(--headerFont);font-weight:600;font-size:.85rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--secondaryInk);margin-bottom:.5rem}
.tier__amt{font-family:var(--headerFont);font-weight:700;text-transform:uppercase;
  font-size:clamp(2.2rem,4.6vw,2.9rem);line-height:1;color:var(--headerColor);
  /* .4rem when a .tier__sub sat underneath and carried the gap itself.
     With the price now running straight into the checklist, it needs its own. */
  margin-bottom:1.25rem}
.tier__amt small{font-size:.34em;color:var(--bodyTextColor);letter-spacing:.05em;font-weight:600}
.tier__sub{font-size:.93rem;margin-bottom:1.4rem;padding-bottom:1.4rem;
  border-bottom:1px solid var(--line)}
.tier ul{display:grid;gap:.7rem;margin:0 0 1.7rem}
.tier li{display:flex;gap:.7rem;font-size:.95rem;line-height:1.5}
.tier li svg{width:17px;height:17px;flex:none;margin-top:.3em;color:var(--secondaryInk)}
.tier li.no{color:var(--bodyTextColor);opacity:.62}
.tier li.no svg{color:#c0453d;opacity:.8}
.tier .btn{margin-top:auto;align-self:stretch;text-align:center;justify-content:center}
.tiers__foot{max-width:60ch;margin:clamp(1.9rem,3.5vw,2.75rem) auto 0;text-align:center;
  font-size:.95rem}

/* dark mode: the tier cards ride on --surface so they invert with
   everything else; only the flag needs a nudge for contrast */
[data-theme="dark"] .tier__flag{background:var(--secondary);color:#08131f}

/* ═══ 12. INNER PAGES (pricing.html, faq.html) ═══════════════
   The home page opens with a hero; inner pages open with a
   quieter band that clears the fixed header without pretending
   to be one. */
.subhead{padding-top:calc(var(--hdrH,6.5rem) + clamp(2.5rem,5vw,4rem))}
.subhead h1{font-size:clamp(2rem,4.4vw,3.25rem)}
.topper.center{display:block;text-align:center;margin-bottom:clamp(1.5rem,3vw,2.25rem)}

/* rate card table — scrolls inside itself rather than pushing
   the page sideways on a phone */
.rate{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid var(--line);border-radius:var(--radiusLg);background:var(--surface)}
.rate table{width:100%;min-width:34rem;border-collapse:collapse;font-size:.95rem}
.rate th,.rate td{text-align:left;padding:.95rem 1.15rem;border-bottom:1px solid var(--line)}
.rate thead th{font-family:var(--headerFont);font-weight:600;font-size:.78rem;
  letter-spacing:.13em;text-transform:uppercase;color:var(--secondaryInk);
  background:var(--surfaceAlt);white-space:nowrap}
.rate tbody tr:last-child td{border-bottom:0}
.rate td b{font-family:var(--headerFont);font-weight:700;color:var(--headerColor);
  font-size:1.05rem;white-space:nowrap}
.rate tbody tr:hover{background:var(--surfaceAlt)}

/* the FAQ page stacks several accordions; give each its own room */
.acc + .acc{margin-top:1rem}

/* ─── the FAQ category filter ──────────────────────────────
   Three groups of questions behind one set of buttons rather
   than one long page. Two rules matter here:

   1. The buttons are the ONLY thing that hides a panel, and
      they need JS to work, so the hiding is gated behind .js
      exactly like the reveal system is. With JS off every
      panel is simply visible and the page still reads top to
      bottom — the questions are the content, the tabs are a
      convenience.
   2. The active state doubles its border with an inset shadow
      instead of thickening border-width, because a 1px→2px
      border reflows the button and nudges its neighbours by a
      pixel on every switch. */
.fset{display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center;
  margin-bottom:clamp(2.25rem,4vw,3.25rem)}
.fset__btn{font-family:var(--headerFont);font-weight:700;
  font-size:clamp(.95rem,.88rem + .4vw,1.25rem);
  text-transform:uppercase;letter-spacing:.02em;line-height:1.2;
  padding:.65rem 1.5rem;border-radius:10px;cursor:pointer;
  border:1px solid var(--line);background:var(--surface);color:var(--bodyTextColor);
  transition:color var(--dur) var(--easeOut),border-color var(--dur) var(--easeOut),
             background-color var(--dur) var(--easeOut),box-shadow var(--dur) var(--easeOut)}
.fset__btn:hover{color:var(--headerColor);border-color:var(--secondary)}
.fset__btn[aria-selected="true"]{background:var(--surfaceAlt);color:var(--headerColor);
  border-color:var(--primary);box-shadow:inset 0 0 0 1px var(--primary)}
/* on dark, --primary collapses to near-black and would vanish against the
   surface, so the selected chip switches to the accent — which is also
   where the reference puts its glow */
[data-theme="dark"] .fset__btn[aria-selected="true"]{
  background:rgba(47,176,217,.10);border-color:var(--secondary);
  box-shadow:inset 0 0 0 1px var(--secondary),0 0 26px rgba(47,176,217,.20)}
.js .fpanel[hidden]{display:none}
.fpanel__h{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  white-space:nowrap}
/* with JS off the panels stack, so each one needs its visible heading back */
html:not(.js) .fpanel__h{position:static;width:auto;height:auto;clip:auto;
  display:block;text-align:center;font-family:var(--headerFont);
  font-size:var(--topperFontSize);letter-spacing:.14em;text-transform:uppercase;
  color:var(--secondaryInk);margin:0 0 1.5rem}
html:not(.js) .fpanel + .fpanel{margin-top:clamp(2.5rem,5vw,4rem)}

/* ═══════════════════════════════════════════════════════════════
   3z. CONTACT PAGE — info column beside the form.

   Two columns on desktop, stacked on mobile, with the form second in
   the source so it is also second when they stack. Someone who wanted
   the phone number should not have to scroll a form to reach it.
   ═══════════════════════════════════════════════════════════════ */
.contact{display:grid;gap:clamp(2rem,4.5vw,3.5rem);align-items:start}
@media(min-width:60rem){.contact{grid-template-columns:1fr 1fr}}

.contact__info h1{margin:0 0 .75rem}
/* No subtitle under the form heading any more, so the heading itself carries
   the gap that used to sit before the first field. */
.contact__form h2{margin:0 0 1.75rem}
/* The contact page has no subhead banner, so its info column heading is the
   page's h1. Sized to match the form's h2 beside it -- the two columns are
   siblings, and an h1 at full size would make the pair look lopsided. */
.contact__info h1{font-size:var(--headerFontSize)}
/* First section on a page with no .subhead still has to clear the fixed
   header, which .subhead would otherwise have handled. */
.section--first{padding-top:calc(var(--hdrH,6.5rem) + clamp(2.5rem,5vw,4rem))}
.contact__info > p{max-width:46ch;margin:0 0 2.25rem}

.contact__list{list-style:none;margin:0;padding:0;display:grid;gap:1.75rem}
.contact__list li{display:flex;gap:1rem;align-items:flex-start}
.contact__list h3{margin:0 0 .25rem;font-size:1.05rem}
.contact__list p{margin:.35rem 0 0;font-size:.95rem;max-width:42ch}

.contact__ic{flex:0 0 auto;display:grid;place-items:center;
  width:2.75rem;height:2.75rem;border-radius:50%;
  background:var(--surfaceAlt);border:1px solid var(--line);color:var(--secondaryInk)}
.contact__ic svg{width:1.35rem;height:1.35rem}

/* The number and the address are the point of the column, so they are
   sized like headings rather than like body links. */
.contact__big{display:inline-block;font-family:var(--headerFont);font-weight:600;
  font-size:clamp(1.15rem,2.2vw,1.4rem);letter-spacing:.01em;
  color:var(--headerColor);text-decoration:none;word-break:break-word;
  transition:color var(--dur) var(--easeOut)}
a.contact__big:hover,a.contact__big:focus-visible{color:var(--secondaryInk)}

/* ---- the form ---- */
.contact__form{background:var(--surfaceAlt);border:1px solid var(--line);
  border-radius:var(--radiusLg);padding:clamp(1.5rem,3.5vw,2.5rem)}

.field{display:block;margin:0 0 1.15rem}
.field__lbl{display:flex;align-items:baseline;gap:.5rem;margin:0 0 .4rem;
  font-family:var(--headerFont);font-weight:600;font-size:.9rem;
  letter-spacing:.06em;text-transform:uppercase;color:var(--headerColor)}
.field__lbl em{font-style:normal;font-family:var(--bodyFont);font-weight:400;
  letter-spacing:0;text-transform:none;font-size:.82rem;color:var(--bodyTextColor)}

.field input,.field textarea{
  width:100%;padding:.85em 1em;font:inherit;color:var(--headerColor);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  transition:border-color var(--dur) var(--easeOut),box-shadow var(--dur) var(--easeOut)}
.field textarea{resize:vertical;min-height:8rem}
.field input::placeholder,.field textarea::placeholder{color:var(--bodyTextColor);opacity:.7}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--secondary);
  box-shadow:0 0 0 3px rgba(47,176,217,.22)}

/* Honeypot. Off-screen rather than display:none — some bots skip
   hidden fields, and the ones that do not are exactly the ones to catch. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.contact__submit{width:100%;margin-top:.5rem}
.contact__submit[disabled]{opacity:.6;cursor:not-allowed}

.contact__status{margin:1rem 0 0;min-height:1.4em;font-size:.95rem}
.contact__status.is-ok{color:var(--secondaryInk);font-weight:600}
.contact__status.is-err{color:#c0392b;font-weight:600}
[data-theme="dark"] .contact__status.is-err{color:#ff8b7a}
