  :root{
    /* TUCKER'S MOBILE MECHANIC THEME — derived from the logo (chrome + safety
       orange + blue ribbon). Structure, spacing and type are O.N.B's unchanged;
       only these values differ.

       Variable NAMES are kept from O.N.B on purpose (--red still means "the
       accent color") so the rest of this stylesheet needs no edits. --red is
       orange here. Do not rename without touching every rule below. */
    /* Colors are sampled from the logo PNG, not eyeballed:
       orange #FA5A00, blue #005CC2, chrome #CFCFCF.

       ---- Hierarchy (this is the rule; the tokens below only serve it) ----
         WHITE   the page ground. Nothing competes with it.
         BLACK   the automotive foundation: headings, dark bands, and the
                 frame around every photo. Structure is black, not blue.
         ORANGE  CTA and attention — buttons, the phone number, the one
                 highlighted word in a heading, and the checklist discs. The
                 discs are the only place orange is decorative rather than
                 clickable; that is a deliberate exception, not licence to
                 spread it further. Orange photo frames were tried and pulled.
         BLUE    small secondary details: icons, links, nav, pills, avatars,
                 the focus ring, the topbar strip, and the .callband dividers.
                 Never a heading. The two full-bleed exceptions (topbar,
                 callband) are both thin seams BETWEEN sections rather than
                 sections themselves — that's the line. A blue band that holds
                 real content would put the site back where it started.

       Blue used to be the primary — every h1-h4 took it, and .cta/.reviews2
       were blue bands, which made the site read blue-first and left orange
       with no room to mean "act". Those moved to black. ~56 blue references
       remain and every one is deliberately small; before adding a blue rule,
       check it against the BLUE line above. */
    --blue:#005CC2;        /* PRIMARY brand blue (logo ribbon) — 6.34:1 on white */
    --blue-deep:#00479A;   /* hover / pressed */
    --red:#FA5A00;         /* ACCENT — safety orange: bars, badges, CTA */
    --red-deep:#C24503;    /* accent hover — 5.06:1 on white, safe as text too */
    --ink:#111418;         /* body text — 17.6:1 on white */
    --muted:#4C535D;       /* secondary text — 8.6:1 on white */
    /* Body copy runs near-black by request. Three things moved together:
       --ink darkened, --muted darkened, and the #3f5464 slate that eight
       paragraph rules hardcoded was pointed at --ink instead. That slate was
       the real culprit — it was doing most of the body copy on the site, and
       no token change would have touched it. Grays that sit on the dark header,
       footer and review cards are deliberately left alone: darkening those
       reduces contrast rather than increasing it. */
    --line:#E4E8EE;        /* hairline only (not a background) */
    --tint:#F5F7FA;        /* barely-there cool wash */
    --gold:#f5b638;        /* review stars — unchanged from O.N.B */
    --white:#fff;
    /* The logo blue already clears 4.5:1 on white, so unlike O.N.B there is no
       need for a separate darkened text blue. Kept as a token so rules that
       mean "blue text" stay distinguishable from rules that mean "brand blue". */
    --blue-text:#005CC2;
    --header-blue:#005CC2;
    /* Dark chrome. Near-black rather than navy: the logo is drawn for a black
       ground. Lifted slightly off #000 so it reads as a material, not a hole.
       On #12151A — white 18.3:1, chrome 11.7:1, orange 5.7:1. All pass AA. */
    --navy:#12151A;
    --navy-2:#0A0B0D;
    --chrome:#CFCFCF;      /* logo's silver */
    --on-dark:#EDF0F4;     /* primary text on dark chrome */
    --on-dark-muted:#B9C1CC; /* secondary text on dark chrome */
    /* Text color for filled-accent surfaces (buttons, call bands). White on
       #FA5A00 is only 3.22:1 and FAILS AA; black on the same orange is 6.12:1
       and passes. Any rule that fills with --red must take its text here. */
    --on-accent:#0A0B0D;

    /* ---- Type ----
       Brief: modern, professional, trustworthy, premium without looking
       expensive. Explicitly NOT a dealership, a parts store, or a racing site.

       Display is Barlow Condensed, body is Barlow — one superfamily, two
       widths. The automotive note comes from WIDTH, not from a novelty face:
       condensed grotesques are the lettering of shop signage, door decals and
       service manuals, so the character reads as industrial without any of
       the checkered-flag/piston-font costume. Because both faces share a
       skeleton, the pairing reads as one deliberate voice rather than two
       fonts that happen to sit together.

       Barlow Condensed DOES have a real 900, but only 600/700/800 are
       fetched. Rules below still ask for 900 in ~27 places and resolve to the
       800 face, which is the weight they were tuned against under Manrope.
       Adding a 900 file would silently re-weight all of them — do it only as
       a deliberate pass, not as a "fix".

       Caveat replaces Kaushan Script on the owner signature. Kaushan is a
       decorative brush face and read casual, which undercut the brief; Caveat
       reads as an actual pen signature and supports the local, personal note
       that block is there to strike.

       Every font-family in this file resolves through these three tokens;
       swapping a typeface means editing one line here. */
    --font-display:'Barlow Condensed',system-ui,sans-serif;
    --font-body:'Barlow',system-ui,sans-serif;
    /* One script face, and it earns its place: Caveat is a pen, and it stays
       on Tucker's signature, where a person is literally signing.
       Four display scripts were auditioned for the section eyebrows and all
       four were pulled — Permanent Marker, Yellowtail, Racing Sans One and
       Lobster Two. The failure was the same every time and it was not the
       choice of face: every one of them is a WIDE letterform, and this site is
       set in a condensed grotesque throughout. A wide script above a condensed
       headline reads as two designs stacked, no matter how good the script is.
       The eyebrow now uses the display family's own italic cut instead, and
       gets its sign-painter character from slant and a hard cast shadow. */
    --font-script:'Caveat',cursive;
    --shadow:0 20px 45px -28px rgba(10,11,13,.30);
    --shadow-sm:0 10px 24px -18px rgba(10,11,13,.30);
    --sp:clamp(72px,9vw,124px);

    /* ---- Header bar height, in ONE place ----
       The bar is exactly the logo plus .mainbar .wrap's vertical padding: the
       nav links come out ~52px tall and the CTA ~65px, both shorter than the
       logo, so the logo is what sets the height. Measured: 128 + 24*2 = 176px
       desktop, 78 + 12*2 = 102px on the mobile bar (see the html.js-nav
       override in the <=900px block).

       --head-h's one remaining consumer is the mobile nav panel's max-height,
       which is sized as "the viewport minus the bar I open underneath". It no
       longer feeds html's scroll-padding-top — that mattered when the header
       was sticky and covered anchor targets, and the bar now scrolls away.
       Change the logo height or the bar padding through these tokens, not
       through the rules, or the panel and the bar drift apart. */
    --logo-h:128px;
    --head-pad:24px;
    --head-h:calc(var(--logo-h) + var(--head-pad) * 2);
  }
  *{box-sizing:border-box;margin:0;padding:0}
  /* 14px flat, not calc(var(--head-h) + 14px). The offset used to clear the
     header because the header was position:sticky and sat over the top of the
     scrollport; now that it scrolls away with the document there is nothing at
     the top of the viewport to clear, and keeping the old value would park
     every anchor target 176px BELOW the fold with dead space above it. The
     remaining 14px is breathing room so a heading is not flush to the edge.
     Still scroll-padding-top on the scrollport rather than per-section
     scroll-margin-top: every anchor on the site wants the same treatment. */
  html{scroll-behavior:smooth;scroll-padding-top:14px}
  /* 17.5, not 17: Barlow's x-height is shorter than Inter's, so it reads a
     size smaller at the same px. This is the value Barlow was calibrated at
     before the Manrope/Inter detour. */
  body{font-family:var(--font-body);color:var(--ink);background:var(--white);line-height:1.65;font-size:17.5px;-webkit-font-smoothing:antialiased}
  /* Tracking is neutral, not negative. The -.02em here was tuned for Manrope,
     a wide geometric that needs pulling in at display sizes; Barlow Condensed
     is already narrow, and the same tightening closes its counters and makes
     large headlines read as a wall. */
  h1,h2,h3,h4{font-family:var(--font-display);line-height:1.08;letter-spacing:0;color:var(--ink)}
  a{color:inherit;text-decoration:none}
  img{max-width:100%;display:block}
  /* Build wraps responsive images in <picture>; display:contents makes the
     wrapper layout-neutral so the inner <img> keeps every existing rule
     (object-fit, absolute .svc-bg, aspect-ratio boxes) exactly as before. */
  picture{display:contents}
  .wrap{max-width:1160px;margin:0 auto;padding:0 26px}
  :focus-visible{outline:3px solid var(--blue);outline-offset:2px;border-radius:6px}
  /* The ring is drawn OUTSIDE the element (offset:2px), so what it has to
     contrast with is the surface AROUND the control, not the control. On the
     blue topbar --blue on --blue is 1:1 — the ring is literally invisible —
     and on the near-black chrome it is 2.89:1, under the 3:1 that WCAG 1.4.11
     asks of a focus indicator. White clears everything these bands contain:
     18.3:1 on --navy, 6.34:1 on --blue, 3.22:1 on an orange fill. Only the
     colour changes; width, offset and radius stay inherited from above.

     Both .reviews2 modifiers are excluded rather than the base class being
     listed loosely: --empty grounds on --tint and --page on --white, both
     light, and a white ring on either is invisible. Only the plain navy band
     qualifies. Same trap for anyone extending this list — check the modifier,
     not just the block. */
  .topbar :focus-visible,.stickyhead :focus-visible,.callband :focus-visible,
  .hero :focus-visible,.page-hero :focus-visible,.cta :focus-visible,
  .area :focus-visible,.estimate-card :focus-visible,
  .reviews2:not(.reviews2--empty):not(.reviews2--page) :focus-visible,
  .svc-back :focus-visible,footer :focus-visible{outline-color:#fff}

  /* Skip link (markup owns the <a class="skip-link" href="#main">; this only
     styles it). Moved off-screen with a transform rather than display:none or
     visibility:hidden, both of which take it out of the tab order entirely and
     defeat the point. position:fixed, not absolute: it must be able to appear
     wherever the reader currently is, and Tab can reach it again after the
     page has been scrolled (Shift+Tab back to the top of the document, or a
     screen reader moving focus). z-index is above
     .stickyhead's 60 and the mobile nav panel's 70. The fill is --white with
     --ink on it (17.6:1) so the label never depends on whatever it lands over,
     and both tokens flip with the dark theme. min-height:44px for the touch
     floor even though this is a keyboard affordance — a switch user tapping it
     needs the same target. */
  .skip-link{position:fixed;top:0;left:0;z-index:100;transform:translateY(-120%);
    display:inline-flex;align-items:center;min-height:44px;
    background:var(--white);color:var(--ink);border:2px solid var(--red);
    border-bottom-right-radius:12px;padding:10px 22px;
    font-family:var(--font-display);font-weight:800;font-size:1.05rem;letter-spacing:.02em;
    box-shadow:var(--shadow);transition:transform .16s}
  .skip-link:focus{transform:translateY(0)}

  /* Bumped from .78rem. At that size the wide .15em tracking read as a caption
     rather than a label, and the hero's location line was the first thing on
     the page a visitor should be able to take in at a glance. The dash and gap
     grow with it — a 24px rule against 1rem type looks like a leftover. */
  .eyebrow{font-family:var(--font-display);font-weight:700;font-size:.98rem;letter-spacing:.15em;text-transform:uppercase;color:var(--blue);display:inline-flex;align-items:center;gap:13px}
  .eyebrow::before{content:"";width:30px;height:3px;border-radius:3px;background:var(--red)}
  .eyebrow.center{justify-content:center}
  .eyebrow.on-dark{color:var(--red)}

  .btn{display:inline-flex;align-items:center;gap:.55rem;font-family:var(--font-display);font-weight:700;font-size:1rem;padding:1rem 1.7rem;border-radius:8px;border:0;cursor:pointer;transition:background .16s,transform .16s,color .16s;white-space:nowrap}
  .btn-blue{background:var(--blue);color:#fff;box-shadow:0 12px 26px -16px rgba(0,92,194,.9)}
  .btn-blue:hover{background:var(--blue-deep);transform:translateY(-2px)}
  .btn-outline{background:#fff;color:var(--navy);border:2px solid var(--line)}
  .btn-outline:hover{border-color:var(--blue);color:var(--blue)}
  .btn-white{background:#fff;color:var(--blue-deep)}
  .btn-white:hover{transform:translateY(-2px)}
  .btn-lg{padding:1.1rem 2rem;font-size:1.06rem}
  .btn-red{background:var(--red);color:var(--on-accent);box-shadow:0 14px 30px -16px rgba(250,90,0,.95)}
  .btn-red:hover{background:var(--red-deep);transform:translateY(-2px)}
  .btn-xl{padding:1.45rem 3rem;font-size:1.4rem;font-weight:800;letter-spacing:.02em}
  .btn-arrow{width:1.35em;height:1.35em;flex:none;transition:transform .18s}
  .btn:hover .btn-arrow{transform:translateX(4px)}
  .stars{color:var(--gold);letter-spacing:2px}
  .gicon{width:24px;height:24px;flex:none}
  .label-note{position:fixed;left:14px;bottom:14px;z-index:99;background:var(--navy);color:var(--on-dark-muted);font:600 12px/1.45 var(--font-body);padding:9px 13px;border-radius:9px;box-shadow:var(--shadow);max-width:272px}

  /* subtle scroll reveal */
  .rise{opacity:0;transform:translateY(16px);transition:opacity .6s ease,transform .6s ease}
  .rise.in{opacity:1;transform:none}
  @media(prefers-reduced-motion:reduce){.rise{opacity:1!important;transform:none!important;transition:none}}

  /* ============ HEADER ============ */
  .ribbon{height:4px;background:var(--red)}
  /* Deliberate exception to the black-foundation rule: the topbar stays blue.
     It's a thin utility strip, and against the black header below it reads as
     a brand edge rather than a blue surface. Ends on --blue-deep, not --navy,
     so it doesn't fade into the header and lose the color. */
  .topbar{background:linear-gradient(90deg,var(--blue) 0%,var(--blue-deep) 100%)}
  .topbar .wrap{display:flex;justify-content:flex-end;align-items:center;gap:24px;padding:10px 26px}
  .topphone{display:inline-flex;align-items:center;gap:11px;color:#fff;font-family:var(--font-display);font-weight:700;font-size:1.34rem;transition:opacity .16s}
  .topphone:hover{opacity:.82}
  .topphone svg{width:26px;height:26px}
  .socials{display:flex;gap:10px}
  .socials a{width:50px;height:50px;border-radius:11px;background:transparent;display:grid;place-items:center;color:#fff;transition:.16s}
  .socials a:hover{background:rgba(255,255,255,.18)}
  .socials svg{width:32px;height:32px}

  /* display:contents: the wrapper carries no box, so .ribbon/.topbar/.stickyhead
     are laid out as direct children of body. It no longer has to (it was here to
     stop the wrapper being .stickyhead's containing block back when the bar was
     position:sticky) but it costs nothing and keeps one fewer stacking context
     between .svc-dd/.nav panel and the page.

     position:relative, NOT sticky. The bar scrolls away with the document — the
     header is 176px of a 900px-tall laptop viewport and holding that much of the
     fold hostage on every scroll is not worth the always-visible CTA. relative
     rather than static because two things measure themselves against this box:
     .svc-dd hangs off .nav-item (its own relative parent, unaffected) but the
     mobile nav panel is position:absolute;top:100% and needs THIS element as its
     containing block. Make it static and the panel resolves against the initial
     containing block and opens at the bottom of the viewport.
     z-index:60 is kept so the bar still paints over the hero it now scrolls
     past, and so .svc-dd (80) and the mobile panel (70) keep their order. */
  .siteheader{display:contents}
  .stickyhead{position:relative;z-index:60;background:#fff;box-shadow:0 3px 16px -12px rgba(10,11,13,.5)}
  .mainbar .wrap{display:flex;align-items:center;gap:36px;padding:var(--head-pad) 26px}
  .logo-left{flex:0 0 auto;transform:translateX(clamp(-72px,-4.5vw,-28px))}
  /* Height comes from --logo-h because it is what --head-h is computed from,
     and --head-h is what the mobile nav panel sizes itself against. */
  .logo-left img{height:var(--logo-h);width:auto;display:block}
  .mainnav{display:flex;align-items:center;gap:28px}
  .mainnav a{color:var(--blue-text);font-family:var(--font-display);font-weight:700;font-size:clamp(1.16rem,1.75vw,1.36rem);letter-spacing:.01em;transition:.16s;position:relative;padding:8px 0;white-space:nowrap}
  /* Why a clamp and not a flat size: the labels are white-space:nowrap in a
     single flex row, and at 901px — the narrowest viewport that still gets the
     desktop nav — there are only 36px between the last link and the CTA. A flat
     1.36rem eats that and collides. The floor is the size this was before, so
     narrow desktops are no worse than they were and wide ones get the bump. */
  .mainnav a:hover{color:var(--blue-deep)}
  .mainnav a.active::after,.mainnav a:hover::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;border-radius:3px;background:var(--red)}
  .mainbar-cta{display:flex;align-items:center;gap:12px;margin-left:auto}
  /* Matches .estimate-submit: white label, neutral shadow. At 1.18rem/800
     (18.88px) it already clears the 18.66px bold large-text threshold, so
     white on --red holds AA here without a size change. */
  .book-btn{display:inline-flex;align-items:center;gap:.5rem;background:var(--red);color:#fff;font-family:var(--font-display);font-weight:800;font-size:1.18rem;letter-spacing:.03em;padding:1.05rem 2.1rem;border-radius:10px;box-shadow:0 6px 14px -8px rgba(10,11,13,.8);transition:background .16s,transform .16s;white-space:nowrap}
  .book-btn:hover{background:var(--red-deep);transform:translateY(-2px)}
  .book-btn:hover .btn-arrow{transform:translateX(4px)}

  /* ============ HERO ============ */
  /* Two background-image declarations, deliberately. The hero photo is the LCP
     element on every page, and hero.webp is 49% smaller than hero.jpg (49KB vs
     97KB) — worth having, but image-set() has no <picture> equivalent here
     because this is a CSS background, not markup. A browser that does not
     understand image-set() discards the second declaration as invalid and
     keeps the first; one that does, overrides with it. The shorthand above
     still supplies center/cover/no-repeat, which the longhand override does
     not reset. */
  .hero{position:relative;background:linear-gradient(100deg,rgba(10,11,13,.86) 0%,rgba(10,11,13,.6) 45%,rgba(10,11,13,.32) 100%),url("../img/hero.jpg") center/cover no-repeat}
  .hero{background-image:linear-gradient(100deg,rgba(10,11,13,.86) 0%,rgba(10,11,13,.6) 45%,rgba(10,11,13,.32) 100%),image-set(url("../img/hero.webp") type("image/webp"),url("../img/hero.jpg") type("image/jpeg"))}
  .hero .wrap{max-width:1220px;padding:clamp(120px,16vw,210px) 26px}
  .hero-copy{max-width:660px}
  .hero .eyebrow{color:#dcecfb}
  /* Top end raised from 4.2rem now that the display face is condensed: the
     manual <br> breaks mean the longest line is "Mobile Mechanic", which sets
     to roughly 540px of the 600px .hero--form column at this size. Push the
     cap further and it wraps against the quote form. */
  /* Down from clamp(3rem,6.2vw,5.4rem) to fit "Expert". The three rows are
     pinned with <br>, and the longest is now "Mechanic Services in" at 20
     characters — roughly 8.8em in Barlow Condensed 900, against a 600px
     .hero--form column. That caps the size at ~4.3rem. Keeping 5.4rem would
     need a fourth row, which pushes the paragraph below the fold. */
  .hero h1{font-size:clamp(2.5rem,5.4vw,4.3rem);font-weight:900;line-height:1.04;letter-spacing:0;margin:18px 0 22px;color:#fff;text-shadow:0 2px 5px rgba(10,11,13,.7),0 6px 22px rgba(10,11,13,.85),0 14px 44px rgba(10,11,13,.65)}
  .hero h1 u{text-decoration:none;color:#fff;position:relative;white-space:nowrap}
  .hero h1 u::after{content:"";position:absolute;left:0;right:0;bottom:.02em;height:.13em;background:var(--red);opacity:1;border-radius:2px}
  /* The city sits on its own <br> line, so the accent lands as a block rather
     than a coloured word mid-sentence. Orange clears AA on the hero's dark
     overlay at this size, and the h1's text-shadow carries it over the
     lighter right-hand side of the photo. */
  .hero h1 .hero-loc{color:var(--red)}
  .hero .sub{font-size:1.18rem;color:#d3e6f7;max-width:42ch;margin-bottom:30px}
  .hero-cta{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:30px;align-items:center}
  .hero-cta .callnum{display:inline-flex;flex-direction:column;color:#fff;padding-left:6px}
  .hero-cta .callnum small{font-size:.76rem;color:var(--on-dark-muted);font-weight:600}
  .hero-cta .callnum b{font-family:var(--font-display);font-size:1.24rem}
  /* ===== Hero with embedded lead form (homepage): copy left, quote form right ===== */
  .hero--form .wrap{max-width:1340px;display:grid;grid-template-columns:minmax(0,1fr) minmax(470px,600px);gap:clamp(28px,4vw,48px);align-items:center;padding:clamp(104px,13vw,150px) 26px clamp(64px,8vw,104px)}
  .hero--form .hero-copy{max-width:600px}
  .hero-form{width:100%;min-width:0;transform:translateX(20px)}
  .estimate-lede{color:var(--muted);font-size:1rem;line-height:1.55;margin:0 0 20px;text-align:center}
  /* Dark and near-opaque over the photo. The old .85 white let the truck
     through the card; at .95 dark the form stays a solid object and the blur
     only softens the edges of what shows at the corners. */
  .hero-form .estimate-card--hero{margin:0;padding:clamp(22px,2.4vw,32px);text-align:left;background:rgba(18,21,26,.95);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 30px 64px -24px rgba(10,11,13,.7)}
  .hero-form .estimate-card--hero>h2{font-size:clamp(2rem,3.2vw,2.7rem);text-align:left;margin-bottom:18px}
  .hero-form .estimate-card--hero .estimate-lede{font-size:.95rem;margin-bottom:16px}
  .hero-form .estimate-card--hero .estimate-form{gap:11px 14px}
  .hero-form .estimate-card--hero .field label{font-size:.82rem}
  .hero-form .estimate-card--hero .field input,.hero-form .estimate-card--hero .field select,.hero-form .estimate-card--hero .field textarea{padding:.68rem .8rem}
  .hero-form .estimate-card--hero .field textarea{min-height:74px}
  /* 1.2rem, not the old 1.14rem: the hero button carries the same white-on-
     orange label and needs the same large-text floor to stay AA. */
  .hero-form .estimate-card--hero .estimate-submit{padding:.98rem 2.8rem;font-size:1.2rem;margin-top:4px}
  @media(max-width:900px){
    .hero--form .wrap{grid-template-columns:1fr;padding-top:clamp(90px,20vw,120px)}
    .hero--form .hero-copy{max-width:660px}
    .hero-form{transform:none}
    .hero-form .estimate-card--hero{max-width:600px;margin:0 auto}
  }
  @media(max-width:620px){
    /* Center the homepage hero copy (eyebrow + headline + subtext) on phones */
    .hero--form .hero-copy{text-align:center}
    .hero--form .hero-copy .eyebrow{justify-content:center}
    .hero--form .hero-copy .sub{margin-left:auto;margin-right:auto}
  }
  .trust-row{display:flex;gap:26px;flex-wrap:wrap;padding-top:26px;border-top:1px solid rgba(255,255,255,.2)}
  .trust-row .t{display:flex;align-items:center;gap:8px;color:#fff;font-size:.92rem;font-weight:600}
  .trust-row svg{width:20px;height:20px;color:var(--red);flex:none}

  .owner-frame{position:relative}
  .owner-frame .photo{aspect-ratio:4/5;border-radius:16px;overflow:hidden;box-shadow:var(--shadow);background:#dbe7ef}
  .owner-frame .photo img{width:100%;height:100%;object-fit:cover;object-position:66% center}
  .owner-frame .photo::after{content:"";position:absolute;inset:0;border-radius:16px;box-shadow:inset 0 0 0 6px #fff}
  .owner-tag{position:absolute;left:-16px;top:28px;background:#fff;padding:11px 16px;border-radius:12px;box-shadow:var(--shadow);display:flex;align-items:center;gap:10px;border-left:4px solid var(--red)}
  .owner-tag .dot{width:9px;height:9px;border-radius:50%;background:#3fbb5b;box-shadow:0 0 0 4px rgba(63,187,91,.2)}
  .owner-tag small{display:block;font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:var(--blue-text);font-family:var(--font-display);font-weight:700}
  .owner-tag b{font-family:var(--font-display);font-size:.98rem;color:var(--ink)}
  .rev-float{position:absolute;right:26px;bottom:26px;background:#fff;border-radius:13px;padding:12px 15px;box-shadow:var(--shadow);display:flex;align-items:center;gap:11px;border:1px solid var(--line)}
  .rev-float b{font-family:var(--font-display);font-size:1.4rem;color:var(--ink);line-height:1}
  .rev-float small{color:var(--muted);font-size:.76rem}

  /* ============ ABOUT / INTRO ============ */
  .about{background:#fff}
  .about .wrap{display:grid;grid-template-columns:1.12fr .88fr;gap:60px;align-items:start;padding:clamp(64px,8vw,100px) 26px}
  /* Three rows, fixed: "Count On Reliable Mobile" / "Mechanic Services in" /
     city. The first break is a <br> in the markup and the city is
     display:block below, so the split holds at every size instead of
     migrating with the column. The break sits after "Mobile" to keep the two
     rows close in length; breaking after "Reliable" instead would leave a
     27-character second row that outruns the column.

     Max is 3.4rem, down from 3.6 when the line was two words shorter: this
     column is ~587px at max wrap width and the longest row needs ~10em, so
     3.6 left only a few px of slack.

     A gear + slanted-caps + wrench lockup was built here and reverted. If it
     comes back it cannot live in this column — at 587px it had to shrink below
     the size of the heading it replaced, so it needs grid-column:1/-1. */
  .about h2{font-size:clamp(1.65rem,4.3vw,3.4rem);font-weight:900;line-height:1.06;letter-spacing:-.01em;margin-bottom:8px;text-transform:uppercase}
  .about h2 .a{color:var(--ink)}
  /* The city breaks to its own line rather than wrapping wherever the column
     happens to run out. It's the orange beat in an otherwise black heading,
     and a highlight split across two lines stops reading as one. */
  .about h2 .b{color:var(--red);display:block}
  .about-copy p{color:var(--ink);font-size:1.07rem;line-height:1.72;margin-top:20px;max-width:56ch}
  .about-copy a{color:var(--blue);font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:color .16s}
  .about-copy a:hover{color:var(--red)}
  .about-photo{border-radius:16px;overflow:hidden;box-shadow:var(--shadow);background:#dbe7ef;border:5px solid var(--navy)}
  /* height:auto is load-bearing, same as on .meet-photo .frame img below. The
     img carries width="1280" height="960" to reserve space against layout
     shift, and those attributes map to a presentational HEIGHT. This rule
     overrode the width and not the height, so the hint survived — and an
     element with both a used width and a used height ignores aspect-ratio
     entirely. The frame rendered a flat 960px tall column at every viewport,
     showing the photo uncropped instead of the 4:3 band. */
  .about-photo img{width:100%;height:auto;display:block;aspect-ratio:4/3;object-fit:cover}
  .about-cap{font-family:var(--font-display);font-weight:800;color:var(--ink);font-size:1.05rem;margin:18px 0 20px}
  .acc{border:1px solid var(--line);background:var(--tint);border-radius:11px;margin-bottom:12px;overflow:hidden}
  .acc summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:12px;padding:18px 20px;font-family:var(--font-display);font-weight:800;font-size:1.12rem;color:var(--ink)}
  .acc summary::-webkit-details-marker{display:none}
  .acc-chevron{width:20px;height:20px;flex:none;color:var(--red);transition:transform .2s}
  .acc[open] .acc-chevron{transform:rotate(90deg)}
  .acc-body{padding:0 20px 20px;color:var(--muted);font-size:1rem;line-height:1.65}
  .acc-body a{color:var(--blue);font-weight:600;text-decoration:underline;text-underline-offset:2px}
  .acc-body a:hover{color:var(--blue-deep)}
  .faq-list{max-width:960px;margin:0 auto}
  .faq-title{text-align:center;text-transform:uppercase;font-family:var(--font-display);font-weight:900;font-size:clamp(1.9rem,4.2vw,3rem);line-height:1.12;letter-spacing:-.005em;color:var(--red);max-width:960px;margin:0 auto clamp(34px,4vw,52px)}
  .faq-title .hl{color:var(--red)}
  .faq .acc{background:transparent;border:0;border-radius:0;overflow:visible;margin-bottom:16px}
  .faq .acc summary{background:#ededf0;border-radius:8px;padding:21px 26px;font-size:1.14rem;gap:14px}
  .faq .acc-chevron{color:var(--blue)}
  .faq .acc[open] .acc-chevron{transform:rotate(-90deg)}
  .faq .acc-body{padding:22px 26px 8px;color:var(--muted)}
  .checklist{list-style:none;display:flex;flex-direction:column;gap:24px;margin:24px 0 0}
  .check-item{display:flex;align-items:flex-start;gap:16px}
  /* Solid orange disc, white mark. The shadow is neutral rather than the old
     orange-tinted one — tinted glow on a filled orange shape reads as a
     smudge, not a lift. */
  .check-ic{width:46px;height:46px;flex:none;border-radius:50%;background:var(--red);display:flex;align-items:center;justify-content:center;box-shadow:0 6px 14px -8px rgba(10,11,13,.55)}
  .check-ic svg{width:23px;height:23px;color:#fff}
  .check-item b{display:block;font-family:var(--font-display);font-weight:800;font-size:1.38rem;color:var(--ink);margin-bottom:4px}
  .check-item span{color:var(--muted);font-size:1.02rem;line-height:1.4}

  /* ============ TRUST STRIP ============ */
  .strip{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
  .strip .wrap{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:24px 26px;flex-wrap:wrap}
  .strip .item{display:flex;align-items:center;gap:11px;font-family:var(--font-display);font-weight:600;color:var(--ink);font-size:.96rem}
  .strip .item svg{width:24px;height:24px;color:var(--blue);flex:none}
  .strip .sep{width:1px;height:26px;background:var(--line)}

  .sec{padding:var(--sp) 0}
  .sec-head{max-width:660px;margin:0 auto 58px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:16px}
  .sec-head h2{font-size:clamp(2.1rem,3.5vw,2.8rem);font-weight:800}
  .sec-head p{color:var(--muted);font-size:1.12rem}

  /* ============ MEET O.N.B ============ */
  /* `center`, not the `start` this rule shipped with. The 4/5 portrait runs
     ~400px taller than the copy column, and top-aligning left that entire gap
     hanging under the signature, which read as a missing section rather than
     whitespace. Centred, it splits either side of the copy and reads as margin. */
  .meet .wrap{display:grid;grid-template-columns:1fr 1.02fr;gap:60px;align-items:center}
  .meet-photo{position:relative;order:2}
  .meet-photo .frame{border-radius:16px;overflow:hidden;box-shadow:var(--shadow);border:5px solid var(--navy)}
  /* owner.jpg is landscape with the subject hard right; a 4/5 portrait crop at
     the default `center top` cuts him out of frame entirely. 76% keeps him and
     the open hood he is working over, which is the half of the photo that says
     what the business does. */
  /* height:auto is load-bearing. The img carries width/height attributes to
     reserve space against layout shift, and those map to a presentational
     height that outranks aspect-ratio — the frame rendered a flat 960px tall
     at every viewport until this was added. */
  .meet-photo .frame img{width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;object-position:76% center}
  .meet-photo .cap{position:absolute;left:18px;bottom:14px;background:rgba(0,92,194,.92);color:#fff;font-size:.82rem;font-weight:600;padding:7px 13px;border-radius:8px}
  .est-chip{position:absolute;right:-16px;top:-16px;background:var(--red);color:var(--on-accent);width:96px;height:96px;border-radius:50%;display:grid;place-content:center;text-align:center;box-shadow:var(--shadow);transform:rotate(5deg)}
  .est-chip small{font:700 .58rem/1.1 var(--font-display);letter-spacing:.05em;text-transform:uppercase}
  .est-chip b{font-family:var(--font-display);font-size:1.55rem;line-height:1}
  .meet h2{font-size:clamp(2rem,3.7vw,3rem);font-weight:900;line-height:1.1;letter-spacing:-.01em;margin:0 0 8px}
  /* Ink opening clause, orange payoff — the same split .finalcta h2 and
     .contact-title use, rather than the reference's all-accent headline. The
     reference runs red then blue; blue is never a heading in this theme. */
  .meet h2 .a{color:var(--ink)}
  .meet h2 .b{color:var(--red)}
  .meet p{color:var(--ink);margin-bottom:18px;font-size:1.07rem}
  .meet .sign{margin:24px 0 4px}
  .meet .sign .nm{font-family:var(--font-script);font-weight:700;font-size:clamp(2.7rem,4vw,3.3rem);color:var(--blue);line-height:1}
  .meet .sign .role{color:var(--muted);font-size:.9rem;font-weight:600}
  .meet-stats{display:flex;gap:34px;margin-top:26px;flex-wrap:wrap}
  .meet-stats .st b{font-family:var(--font-display);font-weight:800;font-size:1.6rem;color:var(--ink);display:block}
  .meet-stats .st span{color:var(--muted);font-size:.86rem;font-weight:600}

  /* ── Section divider ────────────────────────────────────────────────────
     A hairline broken by the same short orange bar the h2::after rules use, so
     it reads as part of the existing system rather than a new motif. Sits
     between sections and carries no padding of its own — the sections either
     side already supply the space, and adding more pushed them apart again. */
  .divider{padding:0}
  .divider .wrap{display:flex;align-items:center;gap:20px}
  .divider .wrap::before,.divider .wrap::after{content:"";flex:1;height:1px;background:var(--line)}
  .divider i{display:block;width:46px;height:4px;border-radius:2px;background:var(--red)}

  /* ── Statement rows (mission, values) ───────────────────────────────────
     Media one side, copy the other, alternating down the page. Deliberately
     lighter than .meet: no signature, no frame border, no caption pill, so
     the owner block above stays the emphatic one and these read as supporting
     material rather than three equal-weight rows in a stack. */
  .stmt .wrap{display:grid;grid-template-columns:1fr 1.05fr;gap:clamp(30px,4.5vw,64px);align-items:center}
  .stmt--flip .stmt-media{order:2}
  /* Consecutive rows collapse the doubled .sec padding between them; the pair
     is one band of content, not two sections that happen to be adjacent. */
  .stmt+.stmt{padding-top:0}
  .stmt-media img{width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;border-radius:16px;box-shadow:var(--shadow)}
  /* Composed artwork, not a photo: it is square and every edge carries something
     (logo at the top, the verse reference at the bottom), so the 4:3 crop above
     would eat both. `contain` rather than `cover` as a second guard — if the file
     is ever swapped for one that is not square, it letterboxes instead of
     silently cropping the words out. */
  .stmt-media img.stmt-art{aspect-ratio:1/1;object-fit:contain;background:#0A0908}
  /* Empty slot, not stand-in photography. hero.jpg and owner.jpg both look
     real enough to ship by accident — this cannot. Swap the whole .photo-slot
     div for an <img> when the photo exists; the aspect-ratio matches. */
  .photo-slot{aspect-ratio:4/3;border:2px dashed var(--line);border-radius:16px;background:var(--tint);
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;text-align:center;padding:24px}
  .photo-slot b{font-family:var(--font-display);font-weight:800;letter-spacing:.12em;text-transform:uppercase;font-size:.76rem;color:var(--blue-text)}
  .photo-slot span{color:var(--muted);font-size:.86rem;line-height:1.5;max-width:28ch}
  .stmt h2{font-size:clamp(1.9rem,3.4vw,2.7rem);font-weight:900;line-height:1.1;letter-spacing:-.01em;color:var(--ink);margin:0 0 14px}
  .stmt h2 .hl{color:var(--red)}
  .stmt p{color:var(--ink);font-size:1.07rem;margin:0}

  /* ============ CALL BAND ============ */
  /* Dark chrome, not brand blue: the band is the same material as the header
     and footer, so it reads as structure rather than as an inserted promo.
     It also keeps the orange phone pill the brightest thing on the strip —
     on blue the pill and the band competed. Contrast on --navy is measured
     in :root (white 18.3:1, chrome 11.7:1, orange 5.7:1). */
  /* Blue, not black. These bands are dividers between content sections, not
     content themselves — in brand blue they read as the seam the page is
     stitched with, and they stop competing with the genuinely black surfaces
     (header, final CTA, reviews) that ARE structure. White on #005CC2 is
     6.34:1, so the copy clears AA at any size, and the orange phone pill is
     the logo's own blue/orange pairing rather than a clash. */
  .callband{background:var(--blue);padding:22px 0}
  .callband .wrap{text-align:center}
  /* Barlow, not Barlow Condensed. This is the one place the condensed display
     face worked against the design: a single centred line meant to span the
     band read narrow and cramped in the middle of it. The normal-width face at
     the same size covers noticeably more of the 1108px inner width.
     Size is up from clamp(.84rem,1.38vw,1.02rem); the min end stays modest
     because this copy is long and would go to three rows on a phone. */
  .callband p{margin:0;color:#fff;font-family:var(--font-body);font-weight:800;font-size:clamp(.9rem,1.6vw,1.2rem);letter-spacing:.03em;text-transform:uppercase;line-height:1.45}
  .callband a{color:var(--chrome);text-decoration:none;white-space:nowrap}
  .callband a:hover{text-decoration:underline}
  /* White on #FA5A00 is 3.22:1 — that clears WCAG AA only under the large-text
     rule, which needs 18.66px AND bold. Hence the explicit 1.2rem (19.2px) at
     900 instead of inheriting the clamp: at the clamp's .9rem floor the pill
     would drop to 14.4px on phones and the white would stop being accessible.
     Pinning it also keeps the number the loudest thing in the band. */
  .callband .callband-phone{display:inline-block;color:#fff;background:var(--red);font-size:1.2rem;font-weight:900;letter-spacing:.02em;padding:.3em .85em;border-radius:999px;box-shadow:0 6px 16px -6px rgba(0,0,0,.55)}
  .callband .callband-phone:hover{text-decoration:none;filter:brightness(1.06)}
  .callband--book{padding:22px 0}
  .callband--book .wrap{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center;gap:14px 24px}
  .callband--book p{margin:0}
  .callband--book p b{color:#fff}
  .callband--book .book-btn{color:#fff}

  /* ============ THE O.N.B DIFFERENCE ============ */
  .diff{background:var(--tint)}
  .diff-wrap{display:grid;grid-template-columns:1.05fr .95fr;gap:60px;align-items:start}
  .diff h2{font-size:clamp(2rem,3.4vw,2.7rem);font-weight:900;line-height:1.12;letter-spacing:-.01em;margin:0 0 18px}
  .diff h2 .a{color:var(--red)}
  .diff h2 .b{color:var(--red)}
  .diff-copy p{color:var(--ink);font-size:1.08rem;line-height:1.75;margin-bottom:16px}
  .diff-copy p:last-child{margin-bottom:0}
  .diff-copy a{color:var(--blue);font-weight:600;text-decoration:none;border-bottom:1px solid rgba(0,92,194,.35)}
  .diff-copy a:hover{border-bottom-color:var(--header-blue)}
  .diff-photo .frame{border-radius:16px;overflow:hidden;box-shadow:var(--shadow);border:5px solid var(--navy)}
  .diff-photo .frame img{width:100%;display:block;aspect-ratio:4/3;object-fit:cover}
  .diff-checks{gap:15px;margin-top:22px}
  .diff-checks .check-ic{width:38px;height:38px}
  .diff-checks .check-ic svg{width:19px;height:19px}
  .diff-checks .check-item b{font-size:1.02rem;margin-bottom:1px}
  .diff-checks .check-item span{font-size:.92rem;color:var(--muted)}

  /* ============ SERVICES ============ */
  .svc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
  .svc{background:#fff;border:1px solid var(--line);border-radius:12px;padding:32px 26px;transition:transform .18s,box-shadow .18s,border-color .18s;display:flex;flex-direction:column}
  .svc:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:#cfe2ef}
  .svc .ic{width:54px;height:54px;border-radius:12px;background:var(--tint);display:grid;place-items:center;margin-bottom:18px}
  .svc .ic svg{width:28px;height:28px;color:var(--blue)}
  .svc h3{font-size:1.2rem;margin-bottom:8px}
  .svc p{color:var(--muted);font-size:.95rem;margin-bottom:16px;flex:1}
  .svc .more{font-family:var(--font-display);font-weight:700;color:var(--blue-text);font-size:.9rem}
  .svc:hover .more{color:var(--red)}

  /* ============ CATEGORY CARDS (homepage "What We Clean") ============ */
  .cats{background:var(--white)}
  .cats-head{text-align:center;max-width:940px;margin:0 auto 56px}
  /* THREE across, because there are three categories — one full row, no
     orphan. This number tracks CATEGORIES in build.cjs and has to be revisited
     whenever that list changes: it was repeat(3,1fr) at five categories, went
     to repeat(2,1fr) at four (3+1 leaves a card alone beside two empty cells),
     and is back to three now that four became three. The rule of thumb is that
     the column count should divide the category count, or the grid ends in a
     short row. The 920px breakpoint below drops to 2-up before the cards get
     too narrow to hold three lines of copy.

     Two-value gap: 40px between the rows, 60px down the middle. They are not
     the same channel. A row gap separates a card's LEARN MORE from the next
     card's art, which is already a hard edge; the column gap has to separate
     live columns of body copy, and at 40px the right edge of one card's
     paragraph sat close enough to the next card's border to read as one block.
     60px is the gutter .about .wrap already uses for its two columns, so this
     is the section matching the page rather than inventing a number. The row
     value is now moot at desktop — one row has no gap to set — but it still
     applies at 560px and below, where the grid stacks to a single column. */
  .cat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:40px 60px}
  .cat-card{background:#fff;border:1px solid var(--line);border-radius:14px;overflow:hidden;display:flex;flex-direction:column;transition:transform .18s,box-shadow .18s,border-color .18s}
  .cat-card:hover{transform:translateY(-5px);box-shadow:var(--shadow);border-color:#cfe2ef}
  /* Navy, matching the artwork's own backdrop, so the frame does not flash a
     pale panel before the SVG paints. It was --line back when the art was
     line work floating on a light field. */
  /* max-height caps what aspect-ratio would otherwise let run away. The ratio
     sizes the panel from the card's WIDTH, and going 2-up roughly doubled that
     width — 4/3 of a 534px card is a 400px tall band of artwork above three
     lines of text, which inverts the card. 260px is what the panel measured at
     three-up, so the art keeps the size it was designed at and only the card
     around it got wider.
     object-fit is contain, not cover, now that the panel is wider than the
     4:3 the art was cut to: cover would crop the icon's sides to fill. The
     letterboxing contain leaves is invisible because each cat-*.svg paints its
     own #12151A backdrop, which is exactly this element's background. */
  .cat-media{display:block;aspect-ratio:4/3;max-height:260px;overflow:hidden;background:var(--navy)}
  .cat-media img{width:100%;height:100%;object-fit:contain;transition:transform .5s ease}
  .cat-card:hover .cat-media img{transform:scale(1.05)}
  .cat-body{padding:26px 26px 30px;display:flex;flex-direction:column;flex:1}
  /* Blue rather than ink. This is the one place blue is doing more than the
     "small secondary details" role the palette gives it, and it earns the
     exception: the card title, its inline link and its Learn More are the
     three interactive-feeling elements in the card, so tying them to one hue
     makes the card read as a single destination instead of a heading with two
     unrelated links under it. Ink is still the default for headings
     everywhere else — do not sweep this outward. 6.34:1 on white. */
  .cat-body h2,.cat-body h3{font-family:var(--font-display);font-weight:800;font-size:1.75rem;line-height:1.12;letter-spacing:.01em;text-transform:uppercase;color:var(--blue);margin-bottom:12px}
  .cat-body p{color:var(--muted);font-size:.97rem;line-height:1.6;margin-bottom:20px;flex:1}
  .cat-body p .cat-link{color:var(--blue-text);font-weight:700;text-decoration:underline;text-underline-offset:2px;text-decoration-thickness:1.5px}
  .cat-body p .cat-link:hover{color:var(--red)}
  .cat-more{display:inline-flex;align-items:center;gap:.5rem;font-family:var(--font-display);font-weight:800;font-size:.86rem;letter-spacing:.06em;text-transform:uppercase;color:var(--blue-text)}
  .cat-more svg{width:1.15em;height:1.15em;transition:transform .18s}
  .cat-card:hover .cat-more{color:var(--red)}
  .cat-card:hover .cat-more svg{transform:translateX(4px)}
  @media(max-width:920px){.cat-grid{grid-template-columns:repeat(2,1fr);gap:20px}}
  @media(max-width:560px){.cat-grid{grid-template-columns:1fr}}

  /* ============ SEGUE BAND (intro -> services) ============ */
  .segue{text-align:center;padding:clamp(50px,6vw,90px) 0 clamp(30px,4vw,52px)}
  /* Ribbon banner with wrenches, replacing the painted-script treatment. The
     eyebrow is the flex row; .segue-ribbon is the banner itself.
     No novelty font: this is the same Barlow Condensed as every heading, and
     all the character comes from the container. That is also why it finally
     sits with the h2 instead of on top of it. */
  /* gap:0 — the wrenches are pulled INTO the banner by their own negative
     margin below, so any gap here would fight it. */
  .segue-eyebrow{display:flex;align-items:center;justify-content:center;gap:0;margin-bottom:14px}
  /* --red, the site orange, so the banner matches the buttons and rules rather
     than introducing a second warm tone.
     THE FONT-SIZE FLOOR IS LOAD-BEARING. White on #FA5A00 is only 3.22:1,
     which fails AA for normal text and clears it solely under the large-text
     rule: 18.66px AND bold. Hence the clamp bottoming out at 1.2rem (19.2px)
     against font-weight:800 — not 1.05rem as before, which at narrow widths
     put the copy at 16.8px and straight into the failing band. Do not lower
     the minimum or drop the weight below 700 while the background is --red.
     The old value was --red-deep (#C24503, 5.06:1), which passes as normal
     text at any size; go back to it if this ever needs to be set smaller. */
  /* position + z-index so the banner paints OVER the wrench handles that the
     negative margin has pushed underneath it. Without the stacking context the
     handles would sit on top and read as lines drawn across the ribbon. */
  .segue-ribbon{position:relative;z-index:1;background:var(--red);color:#fff;font-family:var(--font-display);font-weight:800;font-size:clamp(1.2rem,1.9vw,1.55rem);letter-spacing:.09em;text-transform:uppercase;line-height:1;padding:.62em 1.5em;
    /* Fishtail ends. The notch is a percentage of the height (via the polygon's
       50% midpoint) rather than a fixed px inset, so it stays proportional as
       the clamp resizes the banner. */
    clip-path:polygon(0 0,100% 0,calc(100% - 15px) 50%,100% 100%,0 100%,15px 50%)}
  /* Wrenches are ink, not red: two red shapes either side of a red banner read
     as one blob. Dark against white separates them and echoes the black
     foundation the rest of the page is built on.

     The negative inline margin is what makes the tool look like it is holding
     the banner rather than sitting beside it. It is small on purpose: the
     handle's spike already ends flush with the viewBox edge, so the margin
     only has to slide that point into the ribbon's fishtail notch — it is not
     what creates the silhouette. Do not deepen it past the 15px notch depth
     set in .segue-ribbon's clip-path, or the tip goes behind solid red and the
     spike is gone. It is a length, not a percentage: percentage margins
     resolve against the CONTAINING BLOCK's inline size, so -13% here would
     have been 13% of the whole section width, not of the wrench. */
  /* Width, not height, because the SVG is 53x27 — a 1.96 aspect traced from
     the reference PNG. The rendered height lands near 30px at the top of the
     clamp, which is what keeps the tool reading against a ~55px ribbon. */
  .segue-wrench{width:clamp(42px,4.8vw,60px);height:auto;flex:none;color:var(--navy);margin-inline:clamp(-10px,-.8vw,-6px)}
  /* The right-hand wrench is the left one mirrored, so its jaw also faces
     outward. Doing this in CSS keeps a single SVG in build.cjs rather than two
     near-identical shapes that drift apart on the next tweak. */
  .segue-eyebrow>.segue-wrench:last-child{transform:scaleX(-1)}
  @media (max-width:560px){
    /* The wrenches are decoration and the banner needs every pixel of the
       viewport once the copy is this long. */
    .segue-wrench{display:none}
    .segue-ribbon{letter-spacing:.05em;padding:.6em 1.15em;clip-path:polygon(0 0,100% 0,calc(100% - 10px) 50%,100% 100%,0 100%,10px 50%)}
  }
  /* max-width is doing as much work here as font-size. The headline is ~74
     characters, so the two-line break is a function of the ratio between the
     two, not of either alone — widening the box to 940px at this size would
     pull it back to one long line on a big monitor, and narrowing it much
     past 880px tips it to three. If the copy length changes, re-check the
     pair rather than nudging the font. line-height tightened to 1.04 because
     two lines of 900-weight condensed at 54px leave a visible gutter at 1.08. */
  /* text-wrap:balance evens the two rows instead of filling row one and
     leaving a short remainder. Needed once the nbsp below forbids the
     "Habersham, / GA" break, because the next legal break point sits much
     earlier in the line and without balancing the result is badly top-heavy.
     Browsers without it fall back to normal wrapping, which is only ever a
     ragged second line — nothing breaks.

     max-width 1060px is the two-row budget, not a taste call. The headline is
     ~74 characters and this face at 3.65rem runs about 26px per character, so
     two rows need roughly 960px of measure; 900px was 40px short and spilled
     to three. The ceiling is .wrap's 1160px less its 26px gutters = 1108px,
     so there is ~48px of headroom left. Grow the copy or the font past that
     and it goes to three rows again — drop the font, do not widen the box. */
  .segue-title{font-size:clamp(2.15rem,4.7vw,3.65rem);font-weight:900;line-height:1.04;letter-spacing:-.015em;color:var(--ink);max-width:1060px;margin:0 auto;text-wrap:balance}
  .segue-title .hl{color:var(--red)}
  /* Blue, not --muted grey. This is one of the small secondary details the
     palette reserves blue for, and it separates the line from the h2 above by
     hue instead of by yet another size step — the two are close enough in
     weight that grey read as a dimmed continuation of the headline rather
     than a distinct instruction. #005CC2 on white is 6.34:1, so it clears AA
     as normal text and the size below is not load-bearing for contrast the
     way the orange ribbon's is. Dark theme already flips this to near-white
     via the BLUE TYPE → WHITE block in site-dark.css. */
  .segue-sub{font-family:var(--font-display);font-weight:800;font-size:1.12rem;letter-spacing:.11em;text-transform:uppercase;color:var(--blue);margin:18px 0 0}

  /* ============ SERVICE FLIP CARDS (photo+title default, hover reveals copy) ============ */
  .svc-index>.wrap{max-width:min(1700px,94vw)}
  /* min(100%,300px) floor keeps the track from forcing the grid wider than the
     viewport on phones (a bare floor zoomed the whole page out). Collapses to
     a single full-width column below ~300px, multi-column above.

     Three fixed tracks, not auto-fit. The service groups are uneven (three
     tiles, then two) and auto-fit collapses the unused track, which stretched
     every two-tile row to full width — those tiles came out half again as wide
     as the ones directly above them and the grid stopped reading as a grid.
     A held-open empty third slot is the cheaper cost by far: tile size stays
     constant down the whole page.

     Breakpoints match .cat-grid rather than inventing new ones, so the two
     card grids on the site step down together.

     list-style because .svc-cards is a <ul> now. The global reset zeroes
     margin and padding but not markers. */
  .svc-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;list-style:none}
  @media(max-width:920px){.svc-cards{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:560px){.svc-cards{grid-template-columns:1fr}}
  /* scroll-margin-top:120px removed — html now carries scroll-padding-top for
     every anchor on the site, and the two would have ADDED (target offset is
     scroll-margin plus scroll-padding), leaving ~310px of dead space above a
     linked card. */
  /* 352px was right when this was a standalone index page of a dozen cards at
     420px wide. These are 300px wide and there are eleven of them on the car
     repair page, so the tile is shorter — but it still has to hold the back's
     paragraph, its inline link and the button without scrolling, which is what
     sets the floor. Measured against the longest copy in CAT_SERVICES.

     background is the fallback ground for the scrim: .svc-front is a
     translucent gradient, so with nothing behind it the tiles would render as
     a pale wash of the page. --navy because the palette note in :root puts
     structure on black rather than blue. The filler truck photo covers it
     today and a real photo will cover it later; this is what shows if an
     image ever fails to load. */
  .svc-card{position:relative;display:block;height:clamp(280px,21vw,360px);border-radius:18px;overflow:hidden;text-decoration:none;background:var(--navy);box-shadow:0 20px 44px -30px rgba(10,11,13,.6)}
  .svc-card .svc-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
  /* pic() wraps every photo in <picture> for the WebP source, and <picture> is
     an inline box. Absolute positioning ignores it, so the desktop tile never
     noticed — but the touch rules below make the card a flex column, and there
     the flex item would be the wrapper rather than the image. display:contents
     takes the wrapper out of layout and leaves the <img> as the direct child.
     Source selection is resolved by the img, not by layout, so WebP still
     wins. */
  .svc-card picture{display:contents}
  /* The scrim got darker and gained a middle stop. Two stops from 50% black to
     66% blue was tuned against photography that was dark where the label sits;
     the truck shot standing in as filler is a WHITE vehicle lit by a sunrise,
     and it parks its brightest area directly under the centred label. White on
     white is not a contrast problem you tune, it is one you cover: the middle
     stop holds ~72% over the band the text occupies, which puts white type at
     roughly 7:1 over the brightest pixel in the photo. The blue at the bottom
     is unchanged and still does the brand work. Worth re-checking whenever the
     real photography lands, but darker is the safe default for a scrim that
     has to work under twenty five images nobody has shot yet. */
  .svc-front{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:22px;background:linear-gradient(180deg,rgba(10,11,13,.62),rgba(4,26,58,.72) 55%,rgba(0,71,154,.82));transition:opacity .32s ease}
  /* h4 is the menu tile: the segue band above it holds the h2 and the group
     title is the h3, so the tile sits one level down from its group. Sized
     smaller than the h3 rule beside it because the longest label here runs to
     "Spark Plugs & Ignition Coils" and it has to hold one or two lines inside
     a tile a third shorter than the flip card this was drawn for. */
  .svc-front h3{color:#fff;font-size:clamp(1.5rem,2.1vw,1.9rem);font-weight:900;letter-spacing:-.015em;line-height:1.18;text-shadow:0 2px 14px rgba(0,0,0,.45);margin:0}
  .svc-front h4{color:#fff;font-size:clamp(1.25rem,1.9vw,1.75rem);font-weight:900;letter-spacing:-.01em;line-height:1.16;text-shadow:0 2px 14px rgba(0,0,0,.45);margin:0;text-wrap:balance}
  /* Tightened from 26px/18px/.94rem. The back now carries roughly fifty words
     rather than the one short line it was drawn for, and at the old settings
     the button was pushed off the bottom edge of the tile. */
  .svc-back{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;text-align:center;padding:26px clamp(22px,2.4vw,40px);background:var(--navy);opacity:0;transition:opacity .32s ease}
  .svc-back p{color:#cfe4f4;font-size:.92rem;line-height:1.55;margin:0}
  .svc-btn{display:inline-flex;align-items:center;gap:9px;background:var(--red);color:var(--on-accent);font-family:var(--font-display);font-weight:800;font-size:.8rem;letter-spacing:.07em;text-transform:uppercase;padding:12px 24px;border-radius:9px;box-shadow:0 12px 24px -12px rgba(250,90,0,.75);transition:transform .16s,background .16s}
  .svc-btn::after{content:"";width:17px;height:17px;flex:none;background:currentColor;-webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12h14M13 6l6 6-6 6'/></svg>") center/contain no-repeat;mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12h14M13 6l6 6-6 6'/></svg>") center/contain no-repeat}
  .svc-card:hover .svc-front,.svc-card:focus-visible .svc-front{opacity:0}
  .svc-card:hover .svc-back,.svc-card:focus-visible .svc-back{opacity:1}
  /* The hover no longer repaints the fill. It was #c81f1b — an off-palette red
     left over from before the orange theme — and --on-accent on it is 3.43:1,
     so the button's own label dropped below AA the moment it was hovered
     (6.12:1 on --red at rest). --red-deep is no help either: black on #C24503
     is 3.90:1, still short at .8rem. The 2px lift is the affordance. */
  .svc-card:hover .svc-btn{transform:translateY(-2px)}
  .svc-card .svc-btn.stretched::before{content:"";position:absolute;inset:0;z-index:1}
  .svc-back .svc-inlink{position:relative;z-index:2;color:#fff;font-weight:700;text-decoration:underline;text-underline-offset:2px}
  .svc-back .svc-inlink:hover{text-decoration:none}
  .svc-card:focus-within .svc-front{opacity:0}
  .svc-card:focus-within .svc-back{opacity:1}

  /* TOUCH. Everything above hangs the copy, the inline link and the button off
     :hover, which a phone does not have. :focus-within covers a keyboard, but
     on a touch screen the reveal is at best a stray tap and on iOS it sticks
     until you tap elsewhere. Rather than fake a hover, drop the flip entirely:
     the card unstacks into photo, name, copy, button, which is the same
     information in the same order with nothing hidden.

     Queried on hover:none rather than a width. A narrow desktop window still
     has a pointer and the flip still works there; a wide tablet does not and
     needs this. Width was never what the rule was actually about. */
  @media(hover:none){
    .svc-card{height:auto;display:flex;flex-direction:column}
    .svc-card .svc-bg{position:relative;height:170px;flex:none}
    /* Both halves go static and share the navy, so the name and the copy read
       as one panel under the photo instead of two stacked cards. The front
       loses its gradient with the same change: it is a scrim for text sitting
       ON the photo, and here the text is below it. */
    /* justify-content as well as align-items. .svc-front is a row flex, so
       align-items governs the vertical and the name stayed centred under a
       left-aligned paragraph. .svc-back is a column, where the two axes are
       the other way round, and setting both is what makes one rule cover
       both boxes. */
    .svc-front,.svc-back{position:static;opacity:1;background:var(--navy);align-items:flex-start;justify-content:flex-start;text-align:left}
    .svc-front{padding:18px 20px 0}
    .svc-back{padding:10px 20px 22px;gap:14px;flex:1}
    .svc-front h4{font-size:1.2rem;text-shadow:none}
  }

  /* ============ RECENT WORK ============ */
  .work-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
  .work{border-radius:14px;overflow:hidden;box-shadow:var(--shadow-sm);position:relative;aspect-ratio:4/3}
  .work img{width:100%;height:100%;object-fit:cover}
  .work .ph{position:absolute;inset:0;background:var(--tint);border:1.5px dashed #b8d5e8;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;text-align:center;padding:20px;color:var(--blue)}
  .work .ph svg{width:34px;height:34px;opacity:.7}
  .work .ph b{font-family:var(--font-display);font-size:.98rem}
  .work .ph span{font-size:.82rem;color:var(--muted)}
  .work .tag{position:absolute;top:12px;left:12px;background:var(--navy);color:#fff;font:700 .68rem var(--font-display);letter-spacing:.08em;text-transform:uppercase;padding:5px 11px;border-radius:6px;z-index:2}
  .work-note{text-align:center;margin-top:26px;color:var(--muted);font-size:.95rem}

  /* ============ PROCESS ============ */
  .proc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:30px}
  .step{text-align:center;padding:0 12px}
  .step .num{width:60px;height:60px;margin:0 auto 20px;border-radius:14px;background:var(--navy);color:#fff;display:grid;place-items:center;font-family:var(--font-display);font-weight:800;font-size:1.45rem}
  .step h3{font-size:1.22rem;margin-bottom:8px}
  .step p{color:var(--muted)}

  /* ============ REVIEWS ============ */
  .rev-badge{display:inline-flex;align-items:center;gap:11px;background:#fff;border:1px solid var(--line);border-radius:999px;padding:10px 22px;box-shadow:var(--shadow-sm);margin:0 auto}
  .rev-badge b{font-family:var(--font-display);font-size:1.4rem;color:var(--ink)}
  .rev-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
  .revcard{background:#fff;border:1px solid var(--line);border-radius:12px;padding:28px 26px;position:relative}
  .revcard::before{content:"";position:absolute;top:0;left:28px;width:44px;height:4px;background:var(--red);border-radius:0 0 3px 3px}
  .revcard .stars{margin:6px 0 14px;display:block}
  .revcard p{color:var(--ink);font-size:1.01rem;margin-bottom:20px}
  .revcard .who{display:flex;align-items:center;gap:12px}
  .revcard .av{width:44px;height:44px;border-radius:50%;background:var(--blue);display:grid;place-items:center;color:#fff;font-family:var(--font-display);font-weight:800}
  .revcard .who b{display:block;color:var(--ink);font-family:var(--font-display);font-size:.97rem}
  .revcard .who small{color:var(--muted);font-size:.8rem}

  /* ============ SERVICE AREA (the one dark section) ============ */
  .area{background:var(--navy);color:#fff}
  .area .wrap{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center}
  .area h2{color:#fff;font-size:clamp(2rem,3.1vw,2.5rem);margin:16px 0}
  .area p{color:#bcd4e5;font-size:1.08rem;margin-bottom:26px}
  .towns{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .towns a{display:flex;align-items:center;gap:9px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);border-radius:10px;padding:13px 16px;font-weight:600;transition:.16s}
  .towns a:hover{background:var(--blue);border-color:var(--blue)}
  .towns a svg{width:17px;height:17px;color:var(--red)}
  .towns a:hover svg{color:#fff}
  .map-card{aspect-ratio:1/1;border-radius:16px;background:var(--navy-2);border:1px solid rgba(255,255,255,.13);position:relative;overflow:hidden;display:grid;place-items:center}
  .map-card .ring{position:absolute;border:2px dashed rgba(120,165,225,.4);border-radius:50%}
  .map-card .ring.one{width:56%;height:56%}.map-card .ring.two{width:80%;height:80%;opacity:.5}
  .map-card .pin{position:relative;z-index:2;text-align:center}
  .map-card .pin .d{width:52px;height:52px;border-radius:50%;background:var(--red);display:grid;place-items:center;margin:0 auto 10px;box-shadow:0 0 0 8px rgba(250,90,0,.2)}
  .map-card .pin b{font-family:var(--font-display);font-size:1.12rem}
  .map-card .pin small{color:#9fbcd0;display:block}

  /* ============ PAGE HERO (interior) ============ */
  .page-hero{position:relative;overflow:hidden;color:#fff;background:linear-gradient(100deg,rgba(10,11,13,.82) 0%,rgba(10,11,13,.62) 50%,rgba(10,11,13,.42) 100%),url("../img/hero.svg") center/cover no-repeat}
  /* ===== HERO DIVIDER (swap this block per concept) =====
     Brush Stroke — bristle-textured edge, dry-brush drag marks, streaks lifting off. */
  /* Height tracks the SVG's native 1440:100 ratio (100/1440 ≈ 6.94vw) so the
     brush edge never distorts: at desktop widths it lands near 82px, and on
     narrow phones it scales down proportionally instead of compressing the
     horizontal brush drags into jagged vertical spikes. Capped at 82px. */
  /* O.N.B's brush-stroke divider was a pressure-washing motif; dropped here
     rather than ported. The element is kept so the rule stays a no-op if a
     mechanic-appropriate divider is added later. */
  .page-hero .hero-divider{display:none}
  .page-hero .wrap{padding:clamp(152px,18vw,256px) 26px}
  .page-hero .crumbs{font-family:var(--font-display);font-weight:600;font-size:.9rem;color:var(--on-dark-muted);margin-bottom:22px}
  .page-hero .crumbs a{color:#fff}
  .page-hero .crumbs a:hover{text-decoration:underline}
  .page-hero .crumbs span{margin:0 8px;color:#7c9fc6}
  .page-hero .eyebrow{color:#dcecfb}
  .page-hero h1{font-size:clamp(3rem,6.6vw,5.2rem);line-height:1.02;font-weight:900;color:#fff;letter-spacing:0;margin:18px 0 20px;text-shadow:0 2px 5px rgba(10,11,13,.7),0 6px 22px rgba(10,11,13,.85),0 14px 44px rgba(10,11,13,.65)}
  .page-hero p{color:#eaf3fb;font-size:clamp(1.18rem,1.7vw,1.4rem);font-weight:600;max-width:58ch;text-shadow:0 2px 10px rgba(10,11,13,.55)}
  .page-hero--center .wrap{text-align:center}
  .page-hero--center h1{font-size:clamp(2.8rem,6vw,5rem);margin:0 auto 16px}
  .page-hero--center p{margin-left:auto;margin-right:auto;color:#fff;font-weight:700;font-size:clamp(1.35rem,2.2vw,1.7rem);text-shadow:0 2px 14px rgba(10,11,13,.75),0 1px 4px rgba(10,11,13,.6)}

  /* ============ FINAL CTA ============ */
  .cta{background:var(--navy)}
  .cta .wrap{text-align:center;padding:clamp(56px,7vw,88px) 26px}
  .cta h2{color:#fff;font-size:clamp(2.1rem,3.5vw,2.8rem);margin-bottom:14px}
  .cta p{color:rgba(255,255,255,.95);font-size:1.18rem;margin-bottom:30px}
  .cta-row{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;align-items:center}
  .cta-row .callwhite{color:#fff;font-family:var(--font-display);font-weight:700;font-size:1.15rem;display:inline-flex;align-items:center;gap:8px}
  .finalcta{background:var(--tint)}
  .finalcta .wrap{text-align:center;padding:clamp(48px,6vw,80px) 26px}
  .finalcta h2{color:var(--ink);font-size:clamp(2.6rem,5vw,3.9rem);font-weight:900;line-height:1.1;letter-spacing:-.015em;margin-bottom:18px}
  .finalcta h2 .hl{color:var(--red)}
  .finalcta p{color:#12202b;font-size:1.24rem;font-weight:600;margin-bottom:30px}
  .finalcta-row{display:flex;gap:16px 22px;justify-content:center;flex-wrap:wrap;align-items:center}
  .finalcta-btn{padding:1.4rem 2.8rem;font-size:1.3rem}
  .areamap{padding:clamp(46px,6vw,80px) 0;background:linear-gradient(180deg,#f6fafd,#fff);border-top:1px solid var(--line)}
  .areamap-h{color:var(--red);font-size:clamp(2.8rem,5.4vw,4.3rem);font-weight:900;line-height:1.1;letter-spacing:-.015em;margin:0 0 28px}
  /* Second line is ink, not orange. --ink and not a literal black, because
     this heading also renders in the dark theme where ink flips to #F3F2F1 —
     which is why .areamap-h .hl could come out of site-dark.css's whitening
     list. One token now does what two rules used to.
     At 4.3rem the longer line is ~29 characters against the .wrap's 1108px
     ceiling, so it sits at roughly 990px. Lengthen the radius copy much past
     this and it takes a third line. */
  .areamap-h .hl{color:var(--ink)}
  .areamap-lede{max-width:620px;color:var(--ink);font-size:1.06rem;margin:0 0 30px}
  .areamap-card{border-radius:20px;overflow:hidden;box-shadow:0 30px 60px -34px rgba(10,11,13,.55);border:1px solid var(--line);background:#fff}
  .areamap-card iframe{width:100%;height:clamp(340px,46vw,460px);border:0;display:block}
  .areamap-fallback{margin:14px 0 0;font-family:var(--font-display);font-weight:700;font-size:.95rem}
  .areamap-fallback a{color:var(--blue-text);text-decoration:none;border-bottom:2px solid var(--line);padding-bottom:2px}
  .areamap-fallback a:hover{color:var(--blue);border-color:var(--blue)}
  /* --blue-text, not --blue: the token already flips to #F3F2F1 in the dark
     theme, so this needs no entry in site-dark.css. On white it is 6.34:1. */
  .areamap-link{display:inline-flex;align-items:center;gap:9px;margin-top:16px;font-family:var(--font-display);font-weight:800;font-size:1.06rem;color:var(--blue-text);text-decoration:none}
  .areamap-link:hover{text-decoration:underline;text-underline-offset:3px}
  .areamap-pin{width:17px;height:17px;flex:none;color:var(--red)}
  /* The arrow shifts, the pin does not — the pin marks a place, so sliding it
     would read as the place moving. */
  .areamap-link .btn-arrow{width:19px;height:19px;transition:transform .16s}
  .areamap-link:hover .btn-arrow{transform:translateX(4px)}
  .areamap-towns{display:flex;flex-wrap:wrap;gap:12px 14px;margin-top:26px}
  .areamap-towns span{background:var(--blue);color:#fff;font-family:var(--font-display);font-weight:800;font-size:.98rem;padding:9px 18px;border-radius:999px;white-space:nowrap}

  /* ============ FOOTER ============ */
  footer{background:var(--navy-2);color:var(--on-dark-muted);padding:64px 0 28px}
  .foot-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr 1.2fr;gap:40px;padding-bottom:42px;border-bottom:1px solid rgba(255,255,255,.12)}
  .foot-grid h4{color:#fff;font-family:var(--font-display);font-size:.8rem;letter-spacing:.11em;text-transform:uppercase;margin-bottom:16px}
  .foot-grid a{display:block;margin-bottom:10px;font-size:.94rem}
  .foot-grid a:hover{color:#fff}
  .foot-about{display:flex;flex-direction:column;gap:14px}
  .foot-about img{width:58px;height:58px;border-radius:50%}
  .foot-bottom{display:flex;justify-content:space-between;padding-top:22px;font-size:.84rem;flex-wrap:wrap;gap:10px}

  /* Rich footer (Next Steps layout) */
  footer.foot2{background:#fff;color:var(--ink);padding:clamp(48px,6vw,74px) 0 26px;border-top:1px solid var(--line)}
  .foot2-grid{display:grid;grid-template-columns:1.2fr .8fr .9fr minmax(370px,2fr);gap:clamp(26px,3vw,46px);padding-bottom:38px;border-bottom:1px solid var(--line)}
  .foot2-brand{display:flex;flex-direction:column;gap:20px}
  .foot2-logo{width:360px;max-width:100%;height:auto;display:block}
  /* flex-wrap because there are five icons: at 44px with a 10px gap the row is
     260px, and the two-column footer at 560px gives this cell 241px. Wrapping
     is what stops the last icon pushing the grid past the viewport. */
  .foot2-socials{display:flex;flex-wrap:wrap;gap:10px}
  /* 44x44, up from 40. Under the touch-target floor and no padding around them
     to make up the difference, so the box itself has to carry it. */
  .foot2-socials a{width:44px;height:44px;border-radius:9px;background:var(--blue);color:#fff;display:grid;place-items:center;transition:background .16s,transform .16s}
  .foot2-socials a:hover{background:var(--blue-deep);transform:translateY(-2px)}
  .foot2-socials svg{width:20px;height:20px}
  .foot2-col h4{color:var(--blue);font-family:var(--font-display);font-weight:800;font-size:.82rem;letter-spacing:.14em;text-transform:uppercase;margin-bottom:18px}
  .foot2-links{display:flex;flex-direction:column;gap:12px}
  .foot2-links a{position:relative;padding-left:22px;color:var(--ink);font-size:.98rem;font-weight:500;line-height:1.3}
  .foot2-links a::before{content:"";position:absolute;left:3px;top:.35em;width:6px;height:6px;border-top:2.4px solid var(--blue);border-right:2.4px solid var(--blue);transform:rotate(45deg)}
  .foot2-links a:hover{color:var(--blue)}
  .foot2-next p{color:var(--ink);font-size:1rem;line-height:1.6;margin-bottom:22px;max-width:340px}
  .foot2-btns{display:flex;gap:14px;flex-wrap:nowrap;align-items:center}
  /* 1.2rem is not a styling preference, it is what makes .foot2-quote legal.
     White on --red is 3.22:1, which fails AA as normal text and clears it only
     under the large-text exemption: 18.66px+ AND weight 700+. 1.2rem is
     19.2px at 800. Shrink this and the quote button's text has to go back to
     --on-accent (6.12:1) or its background down to --red-deep (5.06:1).
     Sized on the shared selector so .foot2-phone keeps pace — the two read as
     a pair, and only one of them growing would look like a mistake. Blue at
     6.34:1 has no size constraint of its own. */
  .foot2-quote,.foot2-phone{flex:none;white-space:nowrap;font-family:var(--font-display);font-weight:800;font-size:1.2rem;padding:.95rem 1.6rem;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;gap:8px;transition:transform .16s,background .16s}
  .foot2-quote{border:2px solid var(--red);color:#fff;background:var(--red)}
  .foot2-quote:hover{background:var(--red-deep);border-color:var(--red-deep);color:#fff;transform:translateY(-2px)}
  .foot2-quote:hover .btn-arrow{transform:translateX(4px)}
  .foot2-phone{border:2px solid var(--blue);background:var(--blue);color:#fff}
  .foot2-phone:hover{background:var(--blue-deep);border-color:var(--blue-deep);transform:translateY(-2px)}
  .foot2-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:22px;font-size:.84rem;color:var(--muted);flex-wrap:wrap;gap:10px 24px}
  .foot2-legal{display:flex;flex-wrap:wrap;gap:10px 22px}
  .foot2-legal a{color:var(--muted);font-size:.84rem;font-weight:500}
  .foot2-legal a:hover{color:var(--blue)}
  @media(max-width:900px){.foot2-grid{grid-template-columns:1fr 1fr}.foot2-btns{flex-wrap:wrap}
    /* Footer link hit areas to >=44px tall (audit @390px: footer + legal links
       were ~20-22px). Center the chevron ::before to match.
       Moved up from the 560px block these were written in: everything from a
       small tablet down is a touch device, and 561-900px was getting 22px
       targets. The measurement the original comment cites is unchanged. */
    .foot2-links a{min-height:44px;display:flex;align-items:center}
    .foot2-links a::before{top:50%;margin-top:-4px}
    .foot2-legal a{display:inline-flex;align-items:center;min-height:44px;padding:2px 4px}}
  @media(max-width:560px){.foot2-grid{grid-template-columns:1fr}
    /* Mobile: center the social icon row under the logo */
    .foot2-socials{justify-content:center}}

  @media(max-width:900px){
    .mainbar .wrap{flex-wrap:wrap;justify-content:center;gap:16px}
    .mainnav{flex-wrap:wrap;justify-content:center;gap:14px 22px}
    .mainbar-cta{margin-left:0}
    .hero .wrap,.about .wrap,.meet .wrap,.stmt .wrap,.area .wrap,.diff-wrap{grid-template-columns:1fr}
    /* Single column: the alternating order is meaningless, and leaving it in
       would put one row's photo above its heading and the next row's below. */
    .stmt--flip .stmt-media{order:-1}
    .diff-photo{order:-1}
    .hero .rev-float{position:static;margin:26px 26px 0;display:inline-flex}
    .meet-photo{order:-1}
    .svc-grid{grid-template-columns:1fr 1fr}
    .work-grid,.rev-grid,.proc-grid,.foot-grid{grid-template-columns:1fr 1fr}
  }
  @media(max-width:560px){.svc-grid,.work-grid,.rev-grid,.proc-grid,.foot-grid{grid-template-columns:1fr}}
  /* Mobile: keep the utility bar on one clean line — phone left, socials right,
     tighter icons so the number never wraps.

     Two changes, both forced by measurement rather than taste:

     1. The icons are 44x44, not 36x36. Five of them at 36px was under the touch
        floor with nothing around them to make up the difference.
     2. flex-wrap:wrap on the row. At 44px the five icons are 220px and the
        phone with its glyph is ~124px; against the 362px of usable width a
        390px viewport leaves after padding, that fits with about 8px to spare
        and the bar still reads as one line on the phones most of this traffic
        arrives on. It does NOT fit at 360 or 320, and the previous rule had no
        wrap, so those widths pushed the whole PAGE into horizontal scroll —
        which is worse than a two-row utility bar. Wrapping is the escape
        hatch, not the intent: it only engages once one line is impossible.
     Side padding came 16 -> 14 and the gap 10 -> 10/6 to buy back the width
     the larger icons cost. */
  @media(max-width:600px){
    .topbar .wrap{flex-wrap:wrap;justify-content:space-between;gap:6px 10px;padding:6px 14px}
    .topphone{font-size:1.06rem;white-space:nowrap;gap:8px;min-height:44px}
    .topphone svg{width:19px;height:19px}
    .socials{gap:0;margin-left:auto}
    .socials a{width:44px;height:44px;border-radius:9px}
    .socials svg{width:22px;height:22px}
  }
  /* Mobile: lift gallery overlay labels to a legible >=12px floor (audit @390px: BEFORE/AFTER + category badges rendered ~10.6-11.2px). Descendant selectors out-specify the page-scoped .ba-tag/.ba-lbl rules. */
  @media(max-width:820px){.ba-card .ba-tag,.ba-split .ba-lbl,.work .tag{font-size:12.5px}}

  /* ============ CATEGORY / SERVICE PAGES ============ */
  .lede{max-width:860px}
  .lede .eyebrow{margin-bottom:14px}
  .lede h2{font-size:clamp(1.9rem,3.3vw,2.6rem);font-weight:900;margin:0 0 22px;color:var(--ink)}
  .lede p{color:var(--ink);font-size:1.1rem;line-height:1.78;margin-bottom:18px}
  .lede p:last-child{margin-bottom:0}
  .lede a{color:var(--blue);font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:color .16s}
  .lede a:hover{color:var(--red)}
  .cat-intro{padding:clamp(52px,6vw,84px) 0}
  .cat-intro>.wrap{max-width:1150px}
  .cat-intro .wrap{display:grid;grid-template-columns:minmax(0,650px) 400px;justify-content:space-between;gap:36px;align-items:stretch}
  .trust{background:var(--white)}
  .trust .wrap{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(36px,5vw,68px);align-items:center;padding:0 26px}
  .trust-photo{border-radius:16px;overflow:hidden;box-shadow:var(--shadow);background:#dbe7ef;border:5px solid var(--navy);align-self:stretch}
  .trust-photo img{width:100%;height:100%;display:block;aspect-ratio:1/1;object-fit:cover}
  /* --red, so the eyebrow matches the bar beside it and the orange used
     everywhere else, instead of being the one slightly-browner warm tone.
     THE SIZE IS WHAT MAKES THAT LEGAL. #FA5A00 on --white is 3.22:1, which
     fails AA for normal text and clears the 3:1 large-text threshold only at
     18.66px AND 700+. Hence 1.2rem (19.2px) against font-weight:800 — the old
     .82rem was 13.1px, fine while this was --red-deep (5.06:1) and a
     violation the moment the color changed. Same trade already made on the
     segue ribbon and the callband phone pill. Do not shrink this or drop the
     weight; go back to --red-deep if it ever needs to be smaller. */
  .trust-eyebrow{display:inline-flex;align-items:center;gap:11px;font-family:var(--font-display);font-weight:800;font-size:1.2rem;letter-spacing:.18em;text-transform:uppercase;color:var(--red)}
  .trust-eyebrow::before{content:"";width:4px;height:1.05em;background:var(--red);border-radius:2px}
  .trust-copy h2{font-family:var(--font-display);font-weight:900;font-size:clamp(1.7rem,3vw,2.4rem);line-height:1.1;letter-spacing:-.01em;text-transform:uppercase;color:var(--ink);margin:14px 0 18px}
  .trust-copy>p{color:var(--muted);font-size:1.04rem;line-height:1.6;margin:0}
  .trust-copy>p b{color:var(--ink);font-weight:800}
  .trust-checks{margin-top:30px;gap:26px}
  .trust-checks .check-item span{color:var(--muted)}
  @media(max-width:900px){.trust .wrap{grid-template-columns:1fr;gap:32px}.trust-photo img{aspect-ratio:16/10}}
  /* HOW WE GET THE JOB DONE (3-step process) */
  .process{background:var(--white)}
  /* 1040px against the font size below is the two-row budget. The longest of
     the two rows is "Our Mobile Mechanic Process" — 27 characters, ~780px at
     4.15rem — so there is room to spare before it would wrap to three, and the
     full 51-character line is ~1480px, far past the box, so it can never
     collapse to one. The hard ceiling is .wrap's 1160px less its 26px gutters
     = 1108px. Re-check both numbers if this copy changes length. */
  .process-head{max-width:1040px;margin:0 auto clamp(38px,5vw,58px);text-align:center;display:flex;flex-direction:column;align-items:center;gap:24px}
  /* Ink base with an orange second clause, so the line splits into what we do
     and whose process it is. It was orange end to end, which meant the two
     halves had nothing to distinguish them and the emphasis span was decorative
     rather than structural. Matches how .segue-title is built. */
  .process-head h2{font-family:var(--font-display);font-weight:900;font-size:clamp(2.6rem,5.3vw,4.15rem);line-height:1.05;letter-spacing:0;margin:0;color:var(--ink);text-wrap:balance}
  .process-head h2 .hl{color:var(--red)}
  .process-rule{width:min(560px,80%);height:4px;border-radius:3px;background:var(--navy)}
  .process-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(28px,4vw,56px)}
  .process-step{text-align:center;display:flex;flex-direction:column;align-items:center;gap:15px}
  .process-ic{width:66px;height:66px;border-radius:50%;background:var(--blue);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 14px 28px -12px rgba(0,92,194,.75)}
  .process-ic svg{width:32px;height:32px}
  /* The service pages number their steps instead of illustrating them. Same
     circle, same blue, same shadow: the badge is the homepage's, and only what
     sits inside it changes. Twenty five pages would have needed seventy five
     icons drawn to say things an icon cannot say anyway ("Measure, Do Not
     Guess"), and a number is the honest way to show three things in order.
     Sized to fill the circle the way the 32px icon does. */
  .process-ic b{font-family:var(--font-display);font-weight:900;font-size:1.85rem;line-height:1;letter-spacing:-.02em}
  /* .process-steps is an <ol> on those pages, because the steps genuinely run
     in order and that is what tells a screen reader, and an AI summariser
     pulling "how does this work", that step two follows step one. The grid is
     unchanged; only the marker the list would otherwise draw is removed, since
     the numbered badge already is the marker. */
  ol.process-steps{list-style:none}
  .process-step h3{font-family:var(--font-display);font-weight:900;font-size:clamp(1.35rem,2vw,1.7rem);letter-spacing:.01em;color:var(--ink);margin:0}
  .process-step p{color:var(--muted);font-size:1.02rem;line-height:1.55;margin:0;max-width:330px}
  @media(max-width:760px){.process-steps{grid-template-columns:1fr;gap:36px}}
  .cat-intro-copy{background:#fff;border-radius:24px;box-shadow:0 44px 110px rgba(10,11,13,.32),0 14px 36px rgba(10,11,13,.18);padding:clamp(24px,2.3vw,36px) clamp(18px,2vw,26px)}
  .cat-intro-copy h2{font-size:clamp(1.9rem,3.5vw,2.75rem);font-weight:900;line-height:1.1;letter-spacing:0;margin:0 0 10px;text-wrap:balance}
  .cat-intro-copy h2 .nv{color:var(--red)}
  .cat-intro-copy h2 .hl{color:var(--red)}
  .cat-intro-copy p{color:var(--ink);font-size:.98rem;line-height:1.48;margin-bottom:7px}
  .cat-intro-copy p a{color:var(--blue);font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:color .16s}
  .cat-intro-copy p a:hover{color:var(--red)}
  .cat-intro-copy .btn{margin-top:8px}
  .cat-intro-photo{display:flex}
  .cat-intro-photo .photo{border-radius:18px;overflow:hidden;border:4px solid var(--navy);box-shadow:var(--shadow);background:#dbe7ef;width:100%}
  .cat-intro-photo .photo img{width:100%;height:100%;object-fit:cover;display:block}
  /* Mirrored variant: photo left, copy right. The columns swap rather than the
     elements being reordered, because the photo already comes first in the
     source on this one — see the comment on the markup. */
  .cat-intro--flip .wrap{grid-template-columns:400px minmax(0,650px)}
  /* Two of these stack on every category page with only the segue band between
     them, so the second drops the top padding the first already spent. */
  .cat-intro--flip{padding-top:clamp(20px,2.4vw,34px)}
  /* The band is no longer standalone: .cat-svcs follows it and is the grid its
     sub line ("Explore our ... services") has always been pointing at. The
     56px bottom margin .cats-head carries for exactly that case is correct
     again, so the override that zeroed it is gone. Bottom padding drops to
     nothing because the margin is now doing that job. */
  .cat-segue{padding:clamp(34px,4vw,56px) 0 0}
  /* Top padding is zero on purpose. The band above already spends its margin
     separating itself from the tiles; a section pad here as well would put a
     hundred-odd pixels between an instruction and the thing it instructs. */
  .cat-svcs{padding:0 0 clamp(30px,3.6vw,54px)}
  /* Wider than the 1160px the rest of the page runs at, and deliberately. The
     body sections either side are prose and cap at a comfortable measure; this
     is a picture grid, and a picture grid held to a reading measure looks like
     a thumbnail strip. 94vw with a 1700px ceiling is the same rule .svc-index
     already used for this component, so it is the width the tiles were drawn
     to rather than a number picked here. The segue band above stays at 1160
     and stays centred, which is what a heading over a wide grid should do. */
  .cat-svcs>.wrap{max-width:min(1700px,94vw)}
  @media(max-width:900px){.cat-intro .wrap,.cat-intro--flip .wrap{grid-template-columns:1fr;gap:32px}.cat-intro-photo{order:-1}.cat-intro-photo .photo img{aspect-ratio:16/10}}
  .svc-index .svc{padding:26px 24px}
  .svc-index .svc h3{font-size:1.1rem}
  .svc-index .svc p{font-size:.9rem}
  /* scroll-margin-top dropped for the same reason as .svc-card's — html's
     scroll-padding-top now offsets every anchor and the two would stack. */
  .svc-group{margin-top:46px}
  .svc-group:first-child{margin-top:0}
  .svc-group-title{font-family:var(--font-display);font-weight:900;font-size:clamp(1.7rem,2.6vw,2.25rem);letter-spacing:-.01em;color:var(--ink);margin-bottom:24px;display:flex;align-items:center;gap:15px}
  .svc-group-title::before{content:"";width:34px;height:5px;border-radius:3px;background:var(--red);flex:none}
  .contact-cta{padding:clamp(10px,2vw,28px) 0 clamp(44px,5vw,76px)}
  .contact-cta>.wrap{max-width:1200px;display:grid;grid-template-columns:440px minmax(0,1fr);gap:clamp(30px,4vw,60px);align-items:center}
  .contact-photo{display:flex}
  .contact-photo .photo{border-radius:18px;overflow:hidden;border:4px solid var(--navy);box-shadow:var(--shadow);background:#dbe7ef;width:100%;aspect-ratio:5/4}
  .contact-photo .photo img{width:100%;height:100%;object-fit:cover;display:block}
  .contact-card{background:#fff;border-radius:24px;box-shadow:0 44px 110px rgba(10,11,13,.32),0 14px 36px rgba(10,11,13,.18);padding:clamp(28px,3vw,50px)}
  .contact-card h2{font-size:clamp(1.85rem,3.3vw,2.65rem);font-weight:900;line-height:1.06;letter-spacing:-.01em;margin:0 0 18px;color:var(--red)}
  .contact-card h2 .hl{color:var(--red)}
  .contact-card p{color:var(--ink);font-size:1rem;line-height:1.6;margin-bottom:14px}
  .contact-card .btn{margin-top:12px}
  @media(max-width:900px){.contact-cta>.wrap{grid-template-columns:1fr;gap:30px}.contact-photo .photo img{aspect-ratio:16/10}}
  /* REVIEWS 2 — dark band + card carousel (styled like the ONB site) */
  .reviews2{background:var(--navy);color:#fff;padding:clamp(26px,3.4vw,46px) 0;overflow:hidden}/* black foundation — see the hierarchy note in :root */

  /* Empty state. The loud blue treatment above is correct once real reviews
     exist — but while the carousel is empty it makes "we have no reviews yet"
     the single most prominent block on the page, which is backwards. This
     modifier quiets the section down. Drop `reviews2--empty` from the markup
     in build.cjs the day real reviews land; nothing else needs to change. */
  .reviews2--empty{background:var(--tint);color:var(--ink)}
  .reviews2--empty .rev2-h2{color:var(--ink)}
  .reviews2--empty .rev2-sub{color:var(--muted);font-weight:500}
  .reviews2--empty .rev2-body{justify-content:center}
  .reviews2--empty .rev2-based,.reviews2--empty .rev2-based b{color:var(--ink)}
  .reviews2--empty .rev2-google{background:var(--white);box-shadow:var(--shadow-sm)}
  .rev2-head{max-width:900px;margin:0 auto clamp(16px,2vw,26px);padding:0 26px;text-align:center}
  .rev2-h2{color:#fff;font-size:clamp(2rem,4.3vw,3.15rem);font-weight:900;line-height:1.08;letter-spacing:-.01em;margin:0 0 14px;text-wrap:balance}
  /* Orange on the city name. Not in site-dark.css's whitening list, for the
     same reason .process-head h2 .hl is not: this headline is already #fff in
     the light theme, so whitening the .hl would erase the emphasis entirely.
     #FA5A00 on --navy is about 5.7:1, and on the empty state's --tint ground
     about 3.1:1 — which clears AA only because this is 2rem+ at weight 900.
     Shrink this headline below 18.66px and the orange has to go to
     --red-deep. */
  .rev2-h2 .hl{color:var(--red)}
  .rev2-sub{color:#fff;font-size:clamp(1.05rem,1.7vw,1.35rem);font-weight:600;line-height:1.42;margin:0 auto;max-width:760px}
  .rev2-body{max-width:1440px;margin:0 auto;padding:0 clamp(18px,3vw,40px);display:flex;align-items:center;gap:clamp(22px,3vw,46px)}
  /* The column width is what sizes the Google pill and the review button —
     both stretch to fill it rather than shrinking to their own text, so this
     one number controls all three. Widening it narrows the carousel beside it
     (flex:1), which costs the three-up cards about 11px each. */
  .rev2-badge{flex:none;width:184px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:5px}
  .rev2-excellent{font-family:var(--font-display);font-weight:900;letter-spacing:.02em;font-size:1.5rem;color:#fff}
  .rev2-badge-stars{color:var(--gold);font-size:1.75rem;letter-spacing:3px;line-height:1}
  .rev2-based{color:#fff;font-size:.95rem}
  .rev2-based b{color:#fff}
  /* align-self:stretch, not a width — the column's align-items:center would
     otherwise shrink these to their own text. Stretching means the pill and
     the button always agree on width without repeating the number. */
  .rev2-google{align-self:stretch;font-family:var(--font-display);font-weight:800;font-size:1.5rem;letter-spacing:-.01em;margin-top:8px;background:#fff;padding:7px 16px;border-radius:999px;box-shadow:0 8px 20px -10px rgba(0,0,0,.5)}
  /* WHITE ON ORANGE IS LOAD-BEARING ON THE FONT SIZE. #fff on --red is 3.22:1,
     which fails AA for normal text and clears it only under the large-text
     exemption: 18.66px or more AND weight 700+. 1.2rem is 19.2px at weight
     800, so it qualifies with almost nothing to spare. Do not shrink this
     below 1.2rem while the text is white — drop to --red-deep first (#C24503
     takes white to 5.06:1 and passes at any size), or go back to
     --on-accent, which is 6.12:1 on orange.
     Side padding came down from 1.4rem to hold the button near the badge
     column's width now that the type is larger.
     The shadow is neutral, not orange. An orange shadow on the near-black
     band is not a shadow at all — it is a halo, since the colour sits well
     above the ground it falls on. Black at .55 reads as a shadow on the
     empty state's light ground and as almost nothing on the dark band, which
     is the correct behaviour for both. It matches .rev2-google's shadow. */
  .rev2-write{align-self:stretch;text-align:center;margin-top:14px;background:var(--red);color:#fff;font-family:var(--font-display);font-weight:800;font-size:1.2rem;letter-spacing:.04em;padding:.78rem 1.05rem;border-radius:9px;white-space:nowrap;box-shadow:0 8px 16px -10px rgba(0,0,0,.55);transition:background .16s,transform .16s}
  .rev2-write:hover{background:var(--red-deep);transform:translateY(-2px)}
  .rev2-carousel{flex:1;min-width:0;position:relative;display:flex;align-items:center;gap:12px}
  /* --gap is a variable because the card's flex-basis has to subtract it. Two
     places, one number: change it here and the three-up fit follows. */
  .rev2-track{--gap:22px;display:flex;gap:var(--gap);overflow-x:auto;scroll-behavior:smooth;scroll-snap-type:x mandatory;padding:8px 4px 16px;scrollbar-width:none}
  .rev2-track::-webkit-scrollbar{display:none}
  /* Review cards mirror the live O.N.B website (real gun.png + waves.png art) */
  /* Padding moved off the card and onto .rev2-main / .rev2-foot. The dark
     attribution band has to run the full width of the card, so the card
     itself can no longer be the thing holding the inset. */
  /* LITERAL COLOURS, NOT TOKENS, for this card's interior. The card is a
     fixed light object by design — pale panel, dark band, orange frame — and
     it looks the same in both themes. Tokens would break that: --ink is
     #1A1D22 in the light theme and #F3F2F1 in the dark one, so token-coloured
     quote text turns near-white on a near-white panel the moment the theme
     flips. --red is the exception and stays a token; orange is identical in
     both themes, so the frame follows the accent if it is ever retuned. */
  /* Proportions started from the supplied mockup (1046x1352, aspect .774, band
     29.3% of card height, emblem 27.2% sitting 9.0% up — a quarter of it above
     the seam). The emblem's position there was solved by matching its blue
     swoosh between logo.png and the mockup, since the artwork's soft outer
     edge cannot be measured directly.
     Two things now depart from it deliberately. The card is shorter and wider
     (430 tall, not 492), and its WIDTH is no longer a chosen number at all —
     it is whatever makes exactly three cards fill the track, because a card
     sliced in half at the right edge reads as a layout bug rather than as an
     invitation to scroll. calc subtracts the two gaps between three cards.
     Band height still tracks the mockup at .288 (mockup .293). */
  .rev2-card{--band:124px;scroll-snap-align:start;flex:0 0 calc((100% - var(--gap) * 2) / 3);position:relative;overflow:hidden;background:#F5F3F0;border:3px solid var(--red);border-radius:20px;min-height:430px;display:flex;flex-direction:column;box-shadow:0 18px 40px rgba(0,0,0,.3)}
  /* Band as a ::before rather than a background on .rev2-foot. An opaque
     background paints as part of its own element and would cover the emblem
     whatever its z-index — which is exactly what hid it the first time. This
     gives three layers: band (1), emblem (2), attribution text (3). */
  .rev2-card::before{content:"";position:absolute;left:0;right:0;bottom:0;height:var(--band);background:#12151A;border-top:3px solid var(--red);z-index:1}
  /* flex:1 so short and long reviews both push the band to the bottom edge —
     otherwise the band floats mid-card on the short ones and the row of cards
     loses its baseline. */
  .rev2-main{position:relative;flex:1;padding:22px 26px 20px;display:flex;flex-direction:column}
  /* Tyre tread, lifted out of the mockup itself (assets/img/tread.png —
     extracted by tonal band, since the tread and the review text overlap in
     space but never in tone). It is black at low alpha, not baked grey, so
     the panel colour can change without re-cutting the asset.
     right top / cover keeps the tread anchored to the corner it belongs in as
     the card reflows; the asset's own aspect is within 2% of the panel's, so
     cover crops almost nothing. */
  .rev2-main::before{content:"";position:absolute;inset:0;background:url(../img/tread.png) right top/cover no-repeat;opacity:.85;pointer-events:none;z-index:0}
  /* webp override, same two-declaration pattern as .hero. tread.webp is
     lossless (the art has hard edges and alpha) and still 41% smaller. */
  .rev2-main::before{background-image:image-set(url(../img/tread.webp) type("image/webp"),url(../img/tread.png) type("image/png"))}
  .rev2-top{display:flex;justify-content:space-between;align-items:flex-start;position:relative;z-index:2}
  /* These five rules used to carry the reference site's own palette —
     #e10600 stars, #0d2a66 names, #2f6fe0 rule, #1a2b4a body — which is a
     different red and a different blue from ours sitting inside a card that
     is otherwise on-brand. They are tokens now. Stars are --gold, matching
     the .stars rule the rest of the site already uses; the site does not have
     two star colors. */
  /* Orange stars, not --gold. Everywhere else on the site stars sit on white
     as a small rating flourish and gold is right; here they are the first
     thing in a card that is already framed in orange, and gold beside that
     frame reads as a third warm colour rather than a deliberate one. */
  .rev2-stars{position:relative;z-index:2;color:var(--red);font-size:1.5rem;letter-spacing:3px;line-height:1}
  .rev2-quote{position:relative;z-index:2;font:800 3.9rem/.4 Georgia,serif;color:#12151A;height:1.2rem}
  .rev2-text{font:italic 500 1.05rem/1.45 var(--font-body);color:#1A1D22;margin:1.15rem 0 0;flex-grow:1;position:relative;z-index:2}
  /* The dark attribution band. The orange top edge is a border rather than the
     card's own rule element, so it can never drift out of alignment with the
     band it is capping — they are the same box. */
  /* Transparent: the fill and the orange edge belong to .rev2-card::before, so
     that the emblem can sit between them and this text. min-height mirrors
     --band — the two have to stay equal. */
  /* padding-right RESERVES the emblem's footprint rather than hoping the name
     is short enough to miss it. The emblem is 127px wide (100px tall at the
     file's 1.271 aspect) sitting 14px off the right edge, so it owns the last
     141px of the card; 158 leaves 17px of clearance. A real customer name is
     not "Sample review 1" and an earlier layout only cleared the emblem
     because the placeholder happened to be short.
     This matters more now that the emblem sits entirely inside the band —
     it and the attribution text are the same strip. */
  .rev2-foot{position:relative;z-index:3;display:flex;align-items:center;gap:.8rem;background:transparent;padding:0 158px 0 26px;min-height:var(--band)}
  .rev2-g{width:36px;height:36px;flex:none}
  /* min-width:0 lets a long name wrap inside the reserved zone. Without it the
     flex item refuses to shrink below its longest word and overflows back
     under the emblem, which is the exact thing the reservation prevents. */
  .rev2-who{display:flex;flex-direction:column;line-height:1.3;min-width:0}
  .rev2-who small{color:#A7ADB6;font-size:.86rem}
  .rev2-who b{color:#fff;font-size:1.02rem;font-weight:700;line-height:1.35}
  /* Emblem sits WHOLLY on the black band, not straddling the seam as the
     mockup shows. The mockup is wrong about this and the reason is in the
     file: 35% of the art in the emblem's upper quarter is near-white (lum
     >200). On the pale panel that third of the drawing has almost no contrast
     left, so the part above the seam reads as faded while the part below it
     stays crisp — which is exactly what it looked like. The logo is drawn for
     a dark ground and there is no CSS fix for that; only the band is dark.
     (Not the same issue as the earlier one. That time I wrongly claimed the
     PNG was not cut out — it is: RGBA, 62.6% fully transparent, clean corners.
     Cut-out is about alpha, this is about the colour of the drawn pixels.)
     100px in a 124px band leaves 12px above and below, hence bottom:12px.
     z-index:2 lands it above the band fill (1) and below the name and Google
     mark (3), so the text always wins where they meet. Decorative — the card
     names the business in words, so alt="" and aria-hidden. */
  .rev2-logo{position:absolute;right:14px;bottom:12px;width:auto;height:100px;z-index:2;pointer-events:none}
  .rev2-arrow{flex:none;width:46px;height:46px;border-radius:50%;border:0;background:#fff;color:var(--blue-text);box-shadow:0 12px 26px -12px rgba(0,0,0,.6);cursor:pointer;display:grid;place-items:center;transition:transform .16s,background .16s,opacity .16s}
  .rev2-arrow svg{width:22px;height:22px}
  .rev2-arrow:hover:not(:disabled){transform:scale(1.08);background:#eef6fc}
  /* Reviews are a finite list, so the arrows run out of travel. Dimmed and
     non-interactive beats a live-looking button that does nothing. */
  .rev2-arrow:disabled{opacity:.35;cursor:default}
  /* Three-up needs roughly 300px a card to hold five lines of review plus the
     attribution row. Below that, step to two rather than letting the cards
     compress — the emblem's reserved strip is a fixed 158px, so a narrow card
     spends most of its band on reservation and the name wraps to three lines. */
  @media(max-width:1180px){.rev2-card{flex-basis:calc((100% - var(--gap)) / 2)}}
  @media(max-width:820px){
    .rev2-body{flex-direction:column}
    .rev2-badge{width:auto;flex-direction:row;flex-wrap:wrap;justify-content:center;gap:10px 16px}
    /* The column turns into a row here, so align-self:stretch would stop
       meaning "match the column width" and start meaning "match the row
       height" — the pill would grow to whatever the tallest sibling is. */
    .rev2-google,.rev2-write{align-self:auto}
    /* Put the review button on its own centered line under the badge row */
    .rev2-write{flex-basis:100%;margin-top:2px;justify-self:center}
    /* Show one full card per view. The arrows were flex siblings eating ~116px
       of the row, leaving the 300px-min card wider than the track so its right
       edge was clipped. Overlay the arrows in the side gutters instead. */
    .rev2-carousel{width:100%;gap:0;padding:0 44px}
    .rev2-track{flex:1 1 0;min-width:0;width:100%}
    .rev2-card{flex:0 0 100%}
    /* The emblem is a fixed pixel size, so its reserved strip does not shrink
       with the card — on a 360px phone the full-width reservation would leave
       the name about 65px. Scale emblem and reservation down together: 84px
       tall is 107 wide, owns the last 121px, reserve 133 for clearance.
       bottom re-centres it in the unchanged 124px band. */
    .rev2-logo{height:84px;bottom:20px}
    .rev2-foot{padding-right:133px}
    .rev2-arrow{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;z-index:5}
    .rev2-arrow.prev{left:2px}
    .rev2-arrow.next{right:2px}
    .rev2-arrow:hover,.rev2-arrow:focus-visible{transform:translateY(-50%) scale(1.08)}
  }

  /* ── Reviews PAGE (.reviews2--page) ────────────────────────────────────────
     Same section and the same .rev2-card as the carousel — the only difference
     is that every review is on the page at once instead of three at a time.

     Placed below the media queries above on purpose: .rev2-body--page and
     .rev2-body are both (0,1,0), so at ≤820px the carousel's
     `flex-direction:column` would otherwise win on source order and this would
     silently do nothing. */
  /* White ground, unlike the carousel's navy band. The carousel is one section
     inside a long page and the dark band is what separates it from its
     neighbours; here the reviews ARE the page, so a full-height dark slab was
     the page's whole body. var(--white)/var(--ink) rather than #fff/#111 so the
     dark theme remaps both. The blue call band below the section is what
     divides it from the final CTA now that both are light. */
  /* --rev-w is the measure for the strip AND the grid, so the bar always lines
     up with the cards under it. It is what sets card width: at 1140 the three
     columns come out ~365px each, against ~437px when this block ran the full
     1440 the carousel uses. Narrower cards give a review 5-6 words a line
     instead of 9-10, which is what the reference layout reads like. Change this
     one number to resize the cards; do not touch the column count. */
  .reviews2--page{--rev-w:1140px;background:var(--white);color:var(--ink);padding:clamp(40px,5vw,72px) 0}
  .reviews2--page .rev2-h2{color:var(--ink)}
  .rev2-body--page{display:block}

  /* Bigger than the carousel's h2 (3.15rem cap) because this one is the page's
     own headline rather than a section label inside a longer page — it is the
     first thing under the hero. Two lines, so the leading tightens to 1.02;
     the carousel's 1.08 opened a visible gap between them. */
  .reviews2--page .rev2-h2{font-size:clamp(2.3rem,5.4vw,4.15rem);line-height:1.02;margin:0}
  .reviews2--page .rev2-head{max-width:1100px}
  /* Below this the two-line split stops helping: the business name alone runs
     wider than the viewport, so let it wrap on its own. */
  @media(max-width:700px){.rev2-br{display:none}}

  /* Summary strip. The carousel's badge is a stacked column beside the
     scroller; with no scroller to sit beside, it becomes one white bar the
     full width of the grid — Google mark, verdict, stars, score, count, then
     the button pushed to the far end.
     A hairline border does the separating now that the section behind it is
     also white — the shadow alone was enough on navy and is not here. */
  .rev2-strip{display:flex;align-items:center;flex-wrap:wrap;gap:10px 13px;
    background:var(--white);border:1px solid var(--line);border-radius:14px;padding:13px 16px;max-width:var(--rev-w,1440px);
    margin:0 auto clamp(20px,2.6vw,32px);box-shadow:var(--shadow-sm)}
  .rev2-gword{font-family:var(--font-display);font-weight:800;font-size:1.65rem;letter-spacing:-.01em;line-height:1}
  .rev2-verdict{color:var(--ink);font-weight:700;font-size:1.06rem}
  .rev2-strip-stars{color:var(--gold);font-size:1.3rem;letter-spacing:2px;line-height:1}
  .rev2-score{color:var(--ink);font-weight:800;font-size:1.06rem}
  /* The rule between score and count is the reference's, and it is doing real
     work: it separates the rating from the sample size, which are two facts
     people read as one number if they run together. */
  .rev2-count{color:var(--muted);font-size:.95rem;padding-left:13px;border-left:1px solid var(--line)}
  /* align-self:center undoes the stretch the carousel's column needs — without
     it the button grows to the full height of the bar. margin-left:auto is what
     pins it to the right end. Orange, not the reference's blue: this is a CTA,
     and every CTA on this site is orange. */
  /* color:var(--on-accent) is the price of the smaller size. .rev2-write's own
     comment above spells this out: white on --red is 3.22:1 and legal only at
     18.66px+ AND bold. 1.05rem is 16.8px, which drops it straight into the
     failing band — this rule was quietly breaking the rule it inherits from.
     Black on the same orange is 6.12:1 and passes at any size, which is the
     remedy that comment names. */
  .rev2-strip .rev2-write{align-self:center;margin:0 0 0 auto;font-size:1.05rem;padding:.6rem 1.05rem;color:var(--on-accent)}
  /* ...and the hover has to hold --red for the same reason. The inherited
     hover goes to --red-deep, and --on-accent on #C24503 is 3.90:1 — the
     black label that makes the resting state legal fails the moment the fill
     darkens. The lift is the hover; the colour stays put. */
  .rev2-strip .rev2-write:hover{background:var(--red)}
  /* Phone: the button drops to its own full-width line under the summary
     instead of being squeezed beside it. */
  @media(max-width:680px){
    .rev2-strip{justify-content:center;text-align:center}
    .rev2-strip .rev2-write{margin:4px 0 0;flex:1 0 100%;text-align:center}
    .rev2-count{padding-left:0;border-left:0}
  }

  /* Masonry. CSS columns rather than grid because the cards are deliberately
     unequal heights and columns is the only layout that closes the gaps that
     leaves. Reading order runs down each column instead of across rows, which
     is the right trade for a set of independent reviews.
     The height floor is the load-bearing line. .rev2-card ships 430px so the
     carousel's three cards match each other; dropping it to 0 let a two-line
     review render a quote panel barely taller than the attribution band under
     it, which read as a cropped card rather than a short one. 330px is a floor,
     not a fixed height — long reviews still push past it, so height still
     tracks the review. The roomier .rev2-main padding lifts every card by
     another ~14px and stops the last line hugging the dark band. */
  .rev2-grid{columns:3;column-gap:22px;max-width:var(--rev-w,1440px);margin:0 auto}
  .rev2-grid .rev2-card{break-inside:avoid;min-height:330px;width:100%;margin:0 0 22px}
  .rev2-grid .rev2-main{padding:26px 26px 30px}
  @media(max-width:1180px){.rev2-grid{columns:2}}
  @media(max-width:820px){.rev2-grid{columns:1;max-width:520px}}

  /* GOOGLE REVIEWS WIDGET (.grev) — Trustindex-style masonry, real GBP data */
  .grev{background:var(--tint);padding:var(--sp) 0}
  /* When the widget sits directly under the hero (reviews page), match the
     white brush divider so there's no white-on-tint seam at the section edge. */
  .page-hero + .grev{background:#fff}
  .grev-head{text-align:center;max-width:820px;margin:0 auto clamp(24px,3vw,42px)}
  .grev-head h2{font-size:clamp(2rem,4vw,3rem);font-weight:900;margin:.5rem 0 0;text-wrap:balance}
  .grev-widget{max-width:1160px;margin:0 auto}
  .grev-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;background:#fff;border:1px solid var(--line);border-radius:12px;padding:15px 22px;margin-bottom:18px;box-shadow:var(--shadow-sm)}
  .grev-brand{display:flex;align-items:center;gap:11px;flex-wrap:wrap}
  .grev-logo{font-family:var(--font-display);font-weight:800;font-size:1.55rem;letter-spacing:-.02em}
  .grev-verdict{font-weight:700;color:var(--ink);font-size:1.05rem}
  .grev-bar-stars{color:var(--gold);font-size:1.32rem;letter-spacing:2px;line-height:1}
  .grev-score{font-weight:800;color:var(--ink);font-size:1.12rem}
  .grev-pipe{color:var(--line);font-weight:400;font-size:1.1rem}
  .grev-count{color:var(--muted);font-weight:600}
  .grev-write{flex:none;background:var(--blue);color:#fff;font-family:var(--font-display);font-weight:700;font-size:.98rem;padding:.7rem 1.35rem;border-radius:8px;white-space:nowrap;transition:background .16s,transform .16s}
  .grev-write:hover{background:#0d6ba8;transform:translateY(-1px)}
  .grev-grid{columns:3;column-gap:18px} /* no-JS fallback (columnar fill) */
  .grev-grid.is-masonry{columns:auto;display:flex;gap:18px;align-items:flex-start}
  .grev-col{flex:1;min-width:0;display:flex;flex-direction:column;gap:18px}
  /* Wall cards mirror the rev2 carousel card (red stars, quote, gun divider,
     waves art) but size to content in the masonry — no fixed height, tighter
     vertical rhythm so short reviews don't pad out with white space. */
  .grev-card{position:relative;overflow:hidden;background:#fff;border:1px solid var(--line);border-radius:22px;padding:20px 26px 16px;margin:0 0 18px;box-shadow:0 14px 34px -6px rgba(0,71,154,.18);display:flex;flex-direction:column;break-inside:avoid;-webkit-column-break-inside:avoid}
  .grev-grid.is-masonry .grev-card{margin:0} /* flex gap handles spacing in masonry mode */
  .grev-top{display:flex;justify-content:space-between;align-items:flex-start;position:relative;z-index:2}
  .grev-stars{display:block;color:#e10600;font-size:1.3rem;letter-spacing:4px;line-height:1}
  .grev-quote{font:800 3.6rem/.4 Georgia,serif;color:#0d2a66;height:1.2rem}
  .grev-text{font:italic 500 1rem/1.55 var(--font-body);color:#1a2b4a;margin:.8rem 0 .75rem;position:relative;z-index:2}
  .grev-div{display:flex;align-items:center;position:relative;z-index:2;margin:.05rem 0 .8rem}
  .grev-line{flex:1;height:2.5px;background:#2f6fe0;border-radius:2px}
  .grev-gun{height:50px;margin-left:-6px;flex-shrink:0;transform:translateY(-3px)}
  .grev-foot{display:flex;align-items:center;gap:.75rem;position:relative;z-index:3}
  .grev-g{width:32px;height:32px;flex:none}
  .grev-who{display:flex;flex-direction:column;line-height:1.2}
  .grev-who small{color:var(--muted);font-size:.82rem}
  .grev-who small:last-child{color:var(--muted)}
  .grev-who b{color:#0d2a66;font-size:1.02rem;font-weight:700;line-height:1.3}
  .grev-waves{position:absolute;right:0;bottom:0;width:55%;max-height:66%;object-fit:contain;object-position:right bottom;pointer-events:none;z-index:1}
  @media(max-width:900px){.grev-grid{columns:2}}
  @media(max-width:600px){.grev-grid{columns:1}.grev-bar{justify-content:center;text-align:center}}
  .area .mapframe{position:absolute;inset:0;width:100%;height:100%;border:0;filter:saturate(.9)}
  .napbar{display:flex;gap:14px 30px;flex-wrap:wrap;margin-top:24px}
  .napbar .np{display:flex;align-items:center;gap:10px;color:#dbe9f5;font-size:.98rem;font-weight:600}
  .napbar .np svg{width:19px;height:19px;color:var(--red);flex:none}
  .napbar .np a{color:#fff}
  .napbar .np a:hover{text-decoration:underline}
  .related{background:var(--tint);border-top:1px solid var(--line)}
  .related .wrap{text-align:center;max-width:760px}
  .related h2{font-size:clamp(1.7rem,2.8vw,2.2rem);font-weight:900;margin-bottom:14px}
  .related p{color:var(--ink);font-size:1.1rem;line-height:1.75}
  .related a{color:var(--blue);font-weight:700;text-decoration:underline;text-underline-offset:2px}
  .related a:hover{color:var(--red)}

  /* ============ SERVICES NAV DROPDOWN ============ */
  .mainnav .nav-item{position:relative;display:flex;align-items:center}
  .mainnav .nav-trigger{display:inline-flex;align-items:center;gap:5px}
  .mainnav .caret{width:14px;height:14px;transition:transform .16s}
  .nav-item:hover .caret,.nav-item.open .caret{transform:rotate(180deg)}
  .svc-dd{
    position:absolute;top:calc(100% + 14px);left:0;width:290px;
    background:var(--navy);
    box-shadow:0 26px 44px -22px rgba(10,11,13,.6);
    padding:8px 0;border-radius:0 0 10px 10px;overflow:hidden;z-index:80;
    opacity:0;visibility:hidden;transform:translateY(-8px);
    transition:opacity .16s,transform .16s,visibility .16s;
  }
  .nav-item:hover .svc-dd,.nav-item:focus-within .svc-dd,.nav-item.open .svc-dd{opacity:1;visibility:visible;transform:translateY(0)}
  .svc-dd a{
    display:block;padding:14px 24px;color:#dbeaf5;
    font:700 1.06rem/1.2 var(--font-display);letter-spacing:.01em;
    transition:background .13s,color .13s,padding .13s;
  }
  .svc-dd a::after,.svc-dd a:hover::after{content:none;display:none}
  .svc-dd a:hover{background:var(--blue);color:#fff;padding-left:28px}
  .svc-dd a.active{background:var(--blue-text);color:#fff;padding-left:28px}/* current page — deep blue marker */
  /* ============ MOBILE HAMBURGER NAV (<=900px, JS-enhanced) ============ */
  /* No-JS fallback keeps the wrapped inline nav defined above. When nav.js runs
     it adds html.js-nav, and we switch to a hamburger button + slide-down panel
     with the Services menu opening inline — this replaces the old centered
     absolute dropdown that rendered off-center on mobile. */
  .nav-toggle{display:none}
  .nav-cta-mobile{display:none}

  @media(max-width:900px){
    /* The mobile bar is shorter, so the header tokens are re-pointed HERE
       rather than the heights being hardcoded on the rules below. Set on
       html.js-nav — the same element :root sets them on, at higher
       specificity — so --head-h resolves to the mobile number for anything
       reading it: 78 + 12*2 = 102px against the desktop 176px. The nav panel's
       max-height below is what depends on that being right; with the desktop
       176px it would cut 74px off a panel that starts 74px higher.
       Only html.js-nav gets it: with JS off the bar wraps to an unpredictable
       height and there is no number to give. */
    html.js-nav{--logo-h:78px;--head-pad:12px}
    html.js-nav .mainbar .wrap{flex-wrap:nowrap;justify-content:space-between;gap:12px;padding:var(--head-pad) 18px}
    html.js-nav .logo-left{transform:none}
    html.js-nav .mainbar-cta{display:none}

    /* Hamburger button (>=48px touch target) */
    html.js-nav .nav-toggle{
      display:flex;flex-direction:column;justify-content:center;gap:5px;
      width:48px;height:48px;flex:none;margin-left:auto;padding:12px;
      background:transparent;border:0;border-radius:10px;cursor:pointer;
    }
    html.js-nav .nav-toggle span{
      display:block;width:100%;height:3px;border-radius:3px;background:var(--blue);
      transition:transform .22s ease,opacity .16s ease;
    }
    body.nav-open .nav-toggle span:nth-child(1){transform:translateY(8px) rotate(45deg)}
    body.nav-open .nav-toggle span:nth-child(2){opacity:0}
    body.nav-open .nav-toggle span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}

    /* Slide-down panel — top:100% of .stickyhead, i.e. flush under the bar.
       That element is position:relative for exactly this reason. */
    html.js-nav .mainnav{
      position:absolute;top:100%;left:0;right:0;
      display:flex;flex-direction:column;align-items:stretch;
      flex-wrap:nowrap;justify-content:flex-start;gap:0;
      background:var(--navy);padding:6px 0 18px;
      box-shadow:0 26px 40px -20px rgba(10,11,13,.55);
      /* 78vh was a guess at "most of the screen" and it is wrong twice over.
         vh on mobile is the LARGE viewport — it ignores the browser's own
         toolbars, so 78vh on a phone whose chrome is showing is more screen
         than exists. And 78% is not the right fraction anyway: the panel opens
         BELOW the header, so what it can use is the viewport minus the header.
         dvh tracks the live viewport as the toolbars collapse, --head-h is the
         same token the bar itself is built from, and the 16px is the shadow's
         breathing room. The vh line stays first as the fallback for engines
         without dvh, where the old number is at least survivable.
         Landscape phones are the case that forced this: at 375px tall, 78vh
         is 292px starting 102px down — 19px of the panel off-screen. */
      max-height:78vh;
      max-height:calc(100dvh - var(--head-h) - 16px);
      overflow-y:auto;
      /* Contain the scroll chain: reaching the end of the panel must not start
         scrolling the page behind it. The page itself is deliberately NOT
         locked — this panel is position:absolute, not fixed, so it belongs to
         the document; freezing the document with the page near the top would
         put the tail of the panel out of reach with no way to get to it. */
      overscroll-behavior:contain;
      transform:translateY(-14px);opacity:0;visibility:hidden;pointer-events:none;
      transition:opacity .2s ease,transform .2s ease,visibility .2s;
      z-index:70;
    }
    html.js-nav body.nav-open .mainnav{
      transform:translateY(0);opacity:1;visibility:visible;pointer-events:auto;
    }

    /* Panel rows */
    html.js-nav .mainnav > a:not(.nav-cta-mobile),
    html.js-nav .mainnav .nav-trigger{
      display:flex;align-items:center;justify-content:space-between;
      width:100%;min-height:54px;padding:14px 24px;
      color:#e6f1fa;font-size:1.12rem;font-weight:700;
      border-bottom:1px solid rgba(255,255,255,.09);
    }
    html.js-nav .mainnav > a:not(.nav-cta-mobile)::after,
    html.js-nav .mainnav .nav-trigger::after{display:none;content:none}
    html.js-nav .mainnav > a:not(.nav-cta-mobile):hover,
    html.js-nav .mainnav .nav-trigger:hover{color:#fff;background:rgba(255,255,255,.06)}
    html.js-nav .mainnav a.active{color:#fff;box-shadow:inset 4px 0 0 var(--red)}

    /* Services accordion */
    html.js-nav .mainnav .nav-item{position:static;display:block;width:100%}
    html.js-nav .mainnav .nav-item .caret{width:18px;height:18px}
    html.js-nav .svc-dd{
      position:static;transform:none;width:auto;
      background:rgba(0,0,0,.22);box-shadow:none;border-radius:0;
      opacity:1;visibility:visible;pointer-events:auto;
      max-height:0;overflow:hidden;padding:0;
      transition:max-height .28s ease;
    }
    html.js-nav .nav-item.open .svc-dd{max-height:640px}
    html.js-nav .svc-dd a{padding:13px 24px 13px 40px;font-size:1.02rem;border-bottom:1px solid rgba(255,255,255,.06)}
    html.js-nav .svc-dd a:hover{padding-left:44px}

    /* Full-width BOOK NOW at the bottom of the panel.
       Selector is specific enough to beat .mainnav a / .mainnav a:hover, which
       would otherwise recolor the button text blue. */
    html.js-nav .mainnav a.nav-cta-mobile,
    html.js-nav .mainnav a.nav-cta-mobile:hover{
      display:inline-flex;justify-content:center;color:var(--on-accent);background:var(--red);
      margin:16px 24px 0;padding:1rem 1.5rem;font-size:1.14rem;
    }
  }

  /* ============ CONTACT / FREE ESTIMATE FORM ============ */
  .estimate{background:var(--white)}
  .estimate>.wrap{max-width:820px}
  .form-intro{text-align:center;max-width:820px;margin:0 auto clamp(26px,3.4vw,40px)}
  .form-intro-eyebrow{display:block;font-family:var(--font-display);font-weight:700;font-size:clamp(1.15rem,2.1vw,1.6rem);line-height:1.2;color:var(--blue);margin-bottom:6px}
  .form-intro-title{font-family:var(--font-display);font-weight:900;font-size:clamp(2rem,4.4vw,3.4rem);line-height:1.06;letter-spacing:0;color:var(--red);margin:0 0 12px}
  .form-intro-note{font-family:var(--font-display);font-weight:800;font-size:clamp(.82rem,1.4vw,1rem);letter-spacing:.06em;text-transform:uppercase;color:var(--ink);margin:0}
  /* The quote card is the one dark object on a light page. It reads as a
     distinct thing to be filled in rather than another white panel, and it
     ties back to the dark header and footer, which use the same --navy.
     All three placements (hero, final CTA, contact) sit on light grounds. */
  .estimate-card{background:var(--navy);border:1px solid rgba(255,255,255,.09);border-radius:16px;box-shadow:var(--shadow);padding:clamp(26px,4vw,48px)}
  .estimate-card>h2{font-family:var(--font-display);font-weight:900;font-size:clamp(1.9rem,3.4vw,2.6rem);line-height:1.12;letter-spacing:0;color:#fff;text-transform:uppercase;margin:0 0 20px;text-align:left}
  /* Short accent rule under the title, in place of a centred lede. */
  .estimate-card>h2::after{content:"";display:block;width:62px;height:4px;border-radius:2px;background:var(--red);margin-top:13px}
  .estimate-lede{color:var(--on-dark-muted);text-align:left;margin:-8px 0 clamp(20px,2.6vw,28px);font-size:1.02rem;line-height:1.55}
  .estimate-lede a{color:var(--blue);font-weight:700}
  /* minmax(0,1fr), not 1fr. A bare 1fr track takes an automatic minimum of
     min-content, and an <input>'s min-content width is its default `size`
     (~20 characters, ~190px here) regardless of width:100% — percentages are
     treated as auto when a browser computes intrinsic contributions. Two such
     tracks plus the gap need ~390px against the 216px this card actually has
     at a 320px viewport, so the form pushed the page into horizontal scroll on
     the narrowest phones. min-width:0 on .field is the other half: it is the
     grid item, and its own auto minimum would reintroduce the same floor. */
  .estimate-form{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px 18px}
  .field{display:flex;flex-direction:column;gap:7px;min-width:0}
  .field--full{grid-column:1 / -1}
  .field label{font-family:var(--font-display);font-weight:700;font-size:.86rem;letter-spacing:.02em;color:var(--on-dark)}
  .field label .req{color:var(--red)}
  /* Inputs are a light well punched into the dark card — one flat state for
     empty and filled alike. */
  /* font-size:1rem is 16px and that is a hard floor, not a taste call: iOS
     Safari zooms the whole page in on focus for any field under 16px and does
     not zoom back out. Nothing below may override it — the hero card's
     .estimate-card--hero overrides only padding for that reason.
     min-width:0 stops a <select> whose widest <option> is long from setting a
     floor its column cannot honour at 320px. */
  .field input,.field select,.field textarea{font-family:var(--font-body);font-size:1rem;color:var(--ink);background:#E9ECEF;border:1px solid transparent;border-radius:9px;padding:.8rem .95rem;width:100%;min-width:0;box-sizing:border-box;transition:box-shadow .15s,border-color .15s}
  .field textarea{min-height:120px;resize:vertical}
  /* --muted, not a lighter grey: 4.6:1 on the input fill, so the format hints
     are legible rather than decorative. */
  .field input::placeholder,.field textarea::placeholder{color:var(--muted)}
  .field select option{color:var(--ink);background:#fff}
  /* Orange ring: the focused field has to be findable against the dark card,
     and blue at 3px disappears into it. */
  .field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--red);box-shadow:0 0 0 3px rgba(250,90,0,.45)}
  /* Fields have ONE flat state. An orange-until-typed swap was tried here and
     reverted: eight orange blocks put the accent everywhere the eye should be
     resting, and left the submit button with nothing to be the loudest thing.

     Autofill needs pinning, or the browser paints its own yellow-white over
     the field. */
  .field input:-webkit-autofill,.field input:-webkit-autofill:hover,.field input:-webkit-autofill:focus,.field input:-webkit-autofill:active,.field textarea:-webkit-autofill,.field select:-webkit-autofill{-webkit-text-fill-color:var(--ink);caret-color:var(--ink);border:1px solid var(--line);-webkit-box-shadow:0 0 0 40px #E9ECEF inset;box-shadow:0 0 0 40px #E9ECEF inset;transition:background-color 600000s 0s,color 600000s 0s}
  .field input:autofill,.field textarea:autofill,.field select:autofill{-webkit-text-fill-color:var(--ink);border:1px solid var(--line);box-shadow:0 0 0 40px #E9ECEF inset}
  .estimate-hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;overflow:hidden}
  /* Centred and sized to its label, not stretched across both columns.
     White label on --red is 3.22:1, which is AA only as LARGE text — so the
     size floor here is load-bearing. 1.2rem = 19.2px at weight 800 clears the
     18.66px bold threshold; drop it back to 1.16rem and the button silently
     fails AA. Anything smaller filled with --red must use --on-accent. */
  .estimate-submit{grid-column:1 / -1;justify-self:center;display:inline-flex;align-items:center;justify-content:center;gap:.6rem;background:var(--red);color:#fff;font-family:var(--font-display);font-weight:800;font-size:1.2rem;letter-spacing:.04em;text-transform:uppercase;padding:1.05rem 3.2rem;border:0;border-radius:10px;cursor:pointer;box-shadow:0 6px 14px -8px rgba(10,11,13,.8);transition:background .16s,transform .16s}
  .estimate-submit:hover{background:var(--red-deep);transform:translateY(-2px)}
  .estimate-submit:disabled{opacity:.7;cursor:default;transform:none}
  .form-status{grid-column:1 / -1;margin:0;font-size:.95rem;line-height:1.5;padding:.7rem .9rem;border-radius:8px}
  .form-status--error{background:#fdecec;color:#a11;border:1px solid #f3c2c2}
  .estimate-thanks{text-align:center;padding:clamp(20px,4vw,40px) 0}
  .estimate-thanks-ic{width:64px;height:64px;margin:0 auto 18px;border-radius:50%;background:var(--blue);color:#fff;display:flex;align-items:center;justify-content:center}
  .estimate-thanks-ic svg{width:32px;height:32px}
  .estimate-thanks h2{font-family:var(--font-display);font-weight:900;font-size:clamp(1.6rem,3vw,2.2rem);color:var(--ink);margin:0 0 10px}
  .estimate-thanks p{color:var(--muted);font-size:1.05rem;line-height:1.6;margin:0 auto;max-width:440px}
  .estimate-thanks a{color:var(--blue);font-weight:700}
  @media(max-width:620px){
    /* Keep the paired fields side by side. The label-inside-the-box overlay
       that used to live here is gone: it was a workaround for having no real
       placeholders, and now it would sit on top of one. Labels stay above
       their fields at every width, which also keeps the required markers
       visible — the overlay had to hide them. */
    .estimate-form{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px 10px}
    .field textarea{min-height:96px}
  }
  /* Embedded lead form inside the shared final-CTA (bottom of every page) */
  .finalcta--form .estimate-card{max-width:640px;margin:30px auto 0;text-align:left}
  .finalcta--form .estimate-card .form-status{margin-top:0}

  /* ==========================================================
     TUCKER'S ADDITIONS
     Components O.N.B has no equivalent for: interior page heroes,
     breadcrumbs, the service-shell placeholders, and the contact layout.
     Everything above this line is O.N.B's stylesheet, recolored only.
     ========================================================== */

  /* Interior hero — same furniture as the homepage hero, no form column.

     Carries the same hero.jpg as the homepage rather than a flat --navy fill,
     so every hero on the site is one photograph. The overlay is HEAVIER than
     the homepage's (.92/.78/.58 against .86/.6/.32) for a specific reason:
     there the copy sits in the left third, over the dark treeline, and the
     bright sunset on the right is covered by the form card. Here the copy runs
     the full width with nothing over the sky, so the right end of the gradient
     has to do the work the card used to. Lighten it and the tail of a long h1
     lands on the sun.

     Height is set on .wrap, not here. `.hero .wrap` carries the homepage's
     clamp(120px,16vw,210px) — around 410px of vertical padding at desktop —
     which stacked on top of a section padding of its own and gave every
     interior page an ~800px band holding one short heading. That was survivable
     while the fill was flat navy and merely looked empty; with a photograph in
     it, it reads as a landing page and pushes the actual content of the page
     under the fold. One padding declaration now, on the element that already
     had the competing one.

     The clamp was then scaled twice, both by request: 40% taller, then the
     about page alone 15% taller again — and finally that about value was
     adopted for every interior hero, which is why there is one rule here and
     no per-page modifier. Resulting heights, measured at 1440/1280/768/390:

       about, contact    681  645  527  560
       thank-you, svc-*  717  676  558  590
       mechanic          788  753  630  740

     Note those columns are NOT equal. A single padding value sets the space
     ABOVE and BELOW the copy, not the height of the band, so pages whose copy
     wraps to more lines still come out taller — mechanic's h1 is the longest
     on the site and runs three lines at 390px. Every hero now has identical
     breathing room, which is what reads as consistent when clicking between
     pages; identical pixel heights would need a min-height sized to the
     tallest page, making every other band mostly empty. Reopen that only if
     the unequal heights are actually visible in use. */
  .hero--inner{background:linear-gradient(100deg,rgba(10,11,13,.92) 0%,rgba(10,11,13,.78) 48%,rgba(10,11,13,.58) 100%),url("../img/hero.jpg") center/cover no-repeat;display:block}
  /* Same webp override as .hero above, and for the same reason — this is the
     LCP element on the 24 interior pages. Overlay stops differ (heavier here),
     so the gradient has to be restated rather than shared. */
  .hero--inner{background-image:linear-gradient(100deg,rgba(10,11,13,.92) 0%,rgba(10,11,13,.78) 48%,rgba(10,11,13,.58) 100%),image-set(url("../img/hero.webp") type("image/webp"),url("../img/hero.jpg") type("image/jpeg"))}
  .hero--inner .wrap{display:block;max-width:900px;padding:clamp(161px,16.5vw,229px) 26px}

  .hero--inner .hero-copy{max-width:760px}
  .hero--inner h1{color:#fff;font-size:clamp(2.2rem,5vw,3.5rem)}
  .hero--inner .sub{color:rgba(255,255,255,.88)}
  .hero--inner .sub a{color:#fff;text-decoration:underline;text-underline-offset:3px}

  /* Banner variant (the five category pages): same dark photo band, but the
     heading carries the whole hero instead of sharing it with an eyebrow and a
     paragraph. Left-aligned, not centred like .hero--title — the gradient above
     is built to be darkest on the left, so centred text drifts onto the lighter
     half of the photo and loses contrast.

     MUST stay below the .hero--inner rules above: `.hero--cat h1` and
     `.hero--inner h1` are both (0,1,1), and `.hero--cat .sub` and
     `.hero--inner .sub` are both (0,2,0). Above them this block silently loses
     every declaration it shares with them. */
  .hero--cat .hero-copy{max-width:900px}
  /* Roughly 1.4x the 3.5rem the other interior heroes take — big enough to read
     as a banner, short of the 7rem title cards, which have one or two words to
     spend it on and this has six. Leading and tracking tighten as it grows;
     margin:0 because the sub below now owns the gap. */
  .hero--cat h1{font-size:clamp(2.5rem,6.2vw,4.9rem);line-height:1.03;letter-spacing:-.015em;margin:0}
  /* Long-heading step-down, applied by build.cjs to any category heading over
     47 characters. A third line with one word on it is what this exists to
     prevent, so it gives up the least size that achieves that: 4.6rem against
     the 4.9rem above. The longest heading on the site wraps to a third line at
     77px in this measure, and 4.6rem lands at 73.6px — close enough to read as
     the same banner, with room left for the font's own rounding. */
  .hero--cat-long h1{font-size:clamp(2.2rem,5.75vw,4.6rem)}
  /* Bold rather than regular: a light weight over a photograph reads as grey
     mush. 60ch keeps it from running the full 900 and turning into a second
     headline — the size below is as large as it goes before it starts
     competing with the h1 rather than supporting it. */
  .hero--cat .sub{max-width:60ch;margin:clamp(14px,1.6vw,20px) 0 0;font-weight:700;font-size:clamp(1.15rem,1.75vw,1.5rem);line-height:1.45;color:rgba(255,255,255,.92)}

  /* Title-card variant (contact, about): an oversized centred heading, with an
     optional sub beneath it.

     MUST stay below the .hero--inner rules above. `.hero--title h1` and
     `.hero--inner h1` are both (0,1,1), so this only wins on source order —
     placed above them it silently lost, and the heading kept rendering at the
     shared 56px while every other declaration here appeared to work.

     Height is pinned with min-height rather than left to the shared padding.
     Dropping the eyebrow and sub removes ~160px of content, which through a
     padding-driven rule would have collapsed this band well short of every
     other interior hero — undoing the height pass those were just given.
     calc(22.5vw + 357px) is the line through the heights that rule produces at
     1280 (645px) and 1440 (681px), so this hero tracks the others as the
     viewport moves instead of holding one fixed number. */
  .hero--title{display:flex;align-items:center;min-height:clamp(500px,calc(22.5vw + 357px),681px)}
  .hero--title .wrap{width:100%;padding-top:clamp(48px,6vw,80px);padding-bottom:clamp(48px,6vw,80px);text-align:center}
  /* .hero-copy is capped at 760px for the left-column layout the other
     interior heroes use; a centred word needs the full measure, or it centres
     inside a box that is itself sitting off-centre. */
  .hero--title .hero-copy{max-width:none;margin:0 auto}
  /* Roughly double the 5vw/3.5rem the other interior heroes take. Tighter
     leading and a slight negative track: display type wants less of both as it
     grows, and the defaults here were tuned at half this size. margin:0 is
     load-bearing — the inherited bottom margin pushed the word ~30px above
     true centre, which is visible once it is the only thing in the band. */
  .hero--title h1{font-size:clamp(3.4rem,9vw,7rem);line-height:1;letter-spacing:-.015em;margin:0}
  /* About carries a sub under the heading; contact has none. `.hero .sub` and
     `.hero--title .sub` are both (0,2,0), so — same trap as the h1 — this only
     overrides the left-column defaults (42ch, left-aligned, 30px bottom margin)
     by sitting below them. The measure is wider than 42ch because centred text
     with a short measure ends up a narrow column under a very wide heading. */
  .hero--title .sub{max-width:56ch;margin:clamp(14px,1.8vw,22px) auto 0;font-weight:600;font-size:clamp(1rem,1.6vw,1.28rem);line-height:1.55}
  /* Long-heading variant (reviews). "Contact" and "About Us" are one short word
     each and can take the 7rem above; a 39-character heading at that size runs
     to three lines taller than the hero itself. Two deliberate lines at ~5rem
     reads as the same title card at the same weight — it is the character
     count that changed, not the design. 1.06 leading because two lines of
     display type at 1 collide on the descenders. */
  .hero--title-long h1{font-size:clamp(2.3rem,5.2vw,5rem);line-height:1.06}
  /* Below this the break costs more than it buys — "Mobile Mechanic Reviews"
     alone no longer fits a phone, so let the whole heading wrap on its own. */
  @media(max-width:640px){.h1-br{display:none}}

  .breadcrumb{background:var(--tint);border-bottom:1px solid var(--line);font-size:.9rem;padding:14px 0}
  .breadcrumb .wrap{display:flex;gap:9px;align-items:center;flex-wrap:wrap;color:var(--muted)}
  .breadcrumb a{color:var(--blue-text);font-weight:600}
  .breadcrumb a:hover{color:var(--red)}
  .breadcrumb b{color:var(--ink)}

  /* Service list on a category page. */
  .svc-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;margin:26px 0 30px}
  .svc-item{display:flex;flex-direction:column;gap:3px;padding:18px 20px;border:1px solid var(--line);border-left:4px solid var(--red);border-radius:10px;background:#fff;box-shadow:var(--shadow-sm);transition:transform .16s,box-shadow .16s}
  .svc-item:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
  .svc-item b{font-family:var(--font-display);font-weight:800;color:var(--ink);letter-spacing:.02em}
  .svc-item span{color:var(--muted);font-size:.9rem}

  /* Anything deliberately unfinished is marked, so a placeholder can never be
     mistaken for finished copy. */
  .placeholder-flag{display:inline-block;vertical-align:middle;margin-left:.5em;padding:.25em .7em;border-radius:999px;background:var(--red);color:var(--on-accent);font-family:var(--font-body);font-size:.42em;font-weight:800;letter-spacing:.1em;text-transform:uppercase}
  .placeholder-note,.empty-shell,.map-placeholder{border:2px dashed #C7CEDA;border-radius:12px;background:repeating-linear-gradient(45deg,#fafbfd,#fafbfd 12px,#f3f5f9 12px,#f3f5f9 24px)}
  .empty-shell,.map-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;text-align:center;padding:52px 26px;margin:26px 0}
  .map-placeholder{min-height:320px;margin:0}
  .empty-shell b,.map-placeholder b{font-family:var(--font-display);font-weight:800;color:var(--ink);font-size:1.05rem}
  .empty-shell span,.map-placeholder span{color:var(--muted);font-size:.92rem;max-width:46ch}
  .empty-shell code,.map-placeholder code{background:#fff;border:1px solid var(--line);border-radius:4px;padding:1px 5px;font-size:.86em}
  .placeholder-note{padding:18px 22px;color:var(--muted);font-style:italic}

  /* Contact — centred lead block over one centred quote card, under the
     standard photo hero. */
  .contact-lead{max-width:840px;margin:0 auto clamp(28px,3.6vw,44px);text-align:center}
  /* Blue, and the only blue heading-adjacent text on the site — permitted
     because this is an eyebrow, which the theme files under "small secondary
     details", not under headings. It stays visibly subordinate to the h1 below
     it: smaller, and it is the h1 that carries the accent color. The max is
     held at 1.95rem — half the h2's 3.9rem — so "visibly subordinate" survives
     the size bump instead of becoming a judgement call at the widest viewport. */
  .contact-eyebrow{display:block;font-family:var(--font-display);font-weight:800;font-size:clamp(1.3rem,2.6vw,1.95rem);line-height:1.15;color:var(--blue);margin-bottom:10px}
  /* Sentence case, not the uppercase the rest of the display type takes. At
     this size uppercase turns a nine-word instruction into a wall — the
     reference sets it in sentence case for the same reason. */
  .contact-title{font-size:clamp(2.2rem,5.4vw,3.9rem);font-weight:900;line-height:1.03;letter-spacing:-.015em;color:var(--ink);margin:0}
  .contact-title .hl{color:var(--red)}
  .contact-kicker{font-family:var(--font-display);font-weight:800;font-size:clamp(.84rem,1.5vw,1.02rem);letter-spacing:.09em;text-transform:uppercase;color:var(--ink);margin:15px 0 0}
  /* Body face, not the display face the kicker above uses, and not uppercased.
     The kicker is a promise being made ("within 24 hours!") and is styled to
     be read as one; this is an operating fact and should recede next to it.
     Same centred column, so it reads as a footnote to the kicker rather than a
     competing second headline. --muted keeps it 4.9:1 on white, past AA. */
  .contact-hours{font-size:.98rem;line-height:1.55;color:var(--muted);margin:10px auto 0;max-width:46ch}
  .contact-hours b{color:var(--ink);font-weight:700}

  /* Centred variant of the shared dark quote card. Only alignment changes —
     fill, padding and field styling stay common with the hero and final-CTA
     placements so all three read as the same object. */
  .estimate-card--lead{max-width:780px;margin:0 auto}
  .estimate-card--lead>h2{text-align:center}
  .estimate-card--lead>h2::after{margin-left:auto;margin-right:auto}
  .estimate-card--lead .estimate-lede{text-align:center;max-width:54ch;margin:0 auto clamp(20px,2.6vw,28px)}

  .contact-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:clamp(20px,2.6vw,34px);max-width:780px;margin:clamp(26px,3.4vw,42px) auto 0;background:var(--tint);border:1px solid var(--line);border-radius:14px;padding:28px clamp(22px,3vw,34px);text-align:center}
  .contact-fact h3{font-size:.8rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:var(--red-deep);margin:0 0 7px}
  .contact-fact p{color:var(--muted);margin:0;line-height:1.6;font-size:.95rem}
  .contact-phone{font-family:var(--font-display);font-weight:900;font-size:1.5rem;color:var(--red)}

  /* Form states */
  .form-status.is-error{color:#B3261E;background:#FDECEA;border:1px solid #F5C6C0;border-radius:8px;padding:11px 14px;font-size:.92rem;font-weight:600}
  .form-thanks{grid-column:1/-1;display:flex;flex-direction:column;gap:5px;align-items:center;text-align:center;padding:34px 20px}
  /* This replaces the form's contents in place, so it renders on the dark
     card: brand blue would drop to ~1.6:1 on --navy and the muted grey to
     3.9:1. Both are re-pointed to the on-dark pair. */
  .form-thanks b{font-family:var(--font-display);font-weight:900;font-size:1.35rem;color:#fff}
  .form-thanks span{color:var(--on-dark-muted)}

  .foot2-nap{color:rgba(255,255,255,.62);font-size:.88rem}

  /* ============================================================
     LOGO-DRIVEN CHROME
     ------------------------------------------------------------
     The logo's wordmark is drawn in chrome and white with a white
     outline. Composited on white it washes out and is barely legible;
     on near-black it reads cleanly. That is a property of the artwork,
     not a style preference, so the surfaces the logo sits on — the
     sticky header and the footer — are dark. Body stays white.

     To revert to a white header, delete this block and supply a logo
     variant with dark lettering.
     ============================================================ */

  /* ---- Type calibration ----
     A Manrope/Inter compensation layer lived here: negative heading tracking,
     body knocked 17.5 -> 17px, and five headline clamps with their top ends
     pulled in ~20% because Manrope set wider than the condensed face those
     sizes were originally drawn for.

     All of it is gone with the return to Barlow Condensed / Barlow, because
     every condition it corrected for has reversed. The base rules above are
     already tuned for a condensed display face and a Barlow body, so they now
     govern directly instead of being overridden back to themselves. */

  /* Caveat is fetched at 600. The signature reads thin and incidental at 400;
     600 gives it enough weight to sit as a real mark rather than a caption. */
  /* .segue-eyebrow used to ride along here. It declares its own 800 now, and
     this rule sits later in the file — so leaving it listed would silently
     override that weight from 640 lines away. */
  .meet .sign .nm{font-weight:600}

  /* ---- Header ---- */
  .stickyhead{background:var(--navy);box-shadow:0 6px 24px -14px rgba(0,0,0,.85)}
  .mainnav a{color:var(--on-dark)}
  .mainnav a:hover{color:#fff}
  /* The slide-down panel was already dark, so it needs nothing. The hamburger
     bars were brand blue, which is 3.1:1 on the new near-black bar — right at
     the edge for a UI control. Chrome instead. */
  @media(max-width:900px){
    html.js-nav .nav-toggle span{background:var(--chrome)}
  }

  /* ---- Footer ---- */
  footer.foot2{background:var(--navy);color:var(--on-dark-muted);border-top:0}
  .foot2-grid{border-bottom-color:rgba(255,255,255,.14)}
  .foot2-col h4{color:var(--on-dark)}
  .foot2-links a{color:var(--on-dark-muted)}
  .foot2-links a:hover{color:#fff}
  .foot2-links a::before{border-top-color:var(--red);border-right-color:var(--red)}
  .foot2-next p{color:var(--on-dark-muted)}
  /* #8A93A0 on #12151A is 5.89:1 — muted to the eye, still AA for small text. */
  .foot2-bottom{color:#8A93A0}
  .foot2-legal a{color:#8A93A0}
  .foot2-legal a:hover{color:var(--on-dark)}

  /* ============================================================
     TOUCH TARGETS
     ------------------------------------------------------------
     44x44 CSS px floor, applied at the breakpoint the site already
     treats as "phone or tablet". Only the controls that measured
     under it are here; anything already carrying enough padding
     (.acc summary 66px, .svc-dd a 48px, the nav panel's 54px rows,
     .rev2-write 57px, the buttons) is deliberately absent.

     Links set INSIDE a sentence are also absent — .about-copy a,
     .lede a, .acc-body a, .diff-copy a, .cat-body p .cat-link,
     .related a, .cat-intro-copy p a, .areamap-fallback a. There is
     no way to give an inline link a 44px box without opening up
     the line-height of the paragraph it lives in, and WCAG's own
     target-size criteria exempt targets in a block of text for
     exactly that reason. Left as-is on purpose.
     ============================================================ */
  @media(max-width:900px){
    /* Stand-alone "read more" affordances: inline-flex with no padding, so
       they were the height of their own 13.8px/17px type. */
    .cat-more,.areamap-link{min-height:44px}
    /* The top-bar phone is the single most-used control on a mobile page on a
       mechanic's site and it was a 28px line box. Handled at <=600px too, but
       601-900px had nothing. */
    .topphone{min-height:44px}
  }

  /* ============================================================
     REDUCED MOTION
     ------------------------------------------------------------
     The .rise reveal carries its own rule up at the top of the
     file. This is everything else, and it sits at the END on
     purpose: several of the declarations it overrides have equal
     specificity, so source order is what makes it win.

     scroll-behavior is the important one. Smooth scrolling is by
     far the largest motion on the site — every in-page CTA glides
     the whole document past the reader — and it is exactly the
     kind of movement the media query exists to stop.

     Transitions are collapsed to a duration the engine treats as
     instant rather than removed, so state changes still HAPPEN
     (the nav panel still opens, the accordion still expands) with
     no travel. Hover transforms are left alone deliberately: with
     no duration, translateY(-2px) is a static 2px offset, not
     motion.
     ============================================================ */
  @media(prefers-reduced-motion:reduce){
    html,.rev2-track{scroll-behavior:auto}
    *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
  }
