/* Fonts, self-hosted (2026-10-20): the Bricolage Grotesque and Tilt Warp files Google Fonts serves to Chrome on Windows,
   with Google's own @font-face rules (subsets, unicode ranges, font-display: swap); only the URLs point here. */
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDFXplDs.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDVXplDs.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawA1Xp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDFXplDs.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDVXplDs.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawA1Xp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDFXplDs.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDVXplDs.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawA1Xp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDFXplDs.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawDVXplDs.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/3y9H6as8bTXq_nANBjzKo3IeZx8z6up5BeSl5jBNz_19PpbpMXuECpwUxJBOm_OJWiawA1Xp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Tilt Warp';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/AlZc_zVDs5XpmO7yn3w7flUoytXJp3z29uEwmEMLEJljLXvT8UJSZQB5C1b8GA.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Tilt Warp';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/AlZc_zVDs5XpmO7yn3w7flUoytXJp3z29uEwmEMLEJljLXvT8UJSZQB4C1b8GA.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Tilt Warp';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/AlZc_zVDs5XpmO7yn3w7flUoytXJp3z29uEwmEMLEJljLXvT8UJSZQB2C1Y.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* BCS generated stylesheet. Tokens and cross-cutting layer only.
   Generated by generator/cross_cutting.py. Do not hand-edit. */

/* Derived values:
   --surface-accent derived from primary at 6% -> #F0F7F7
   --color-secondary-on-light derived from #68B239 -> #487C28 (#FFFFFF 5.01:1, #F0F7F7 4.62:1)
   --color-muted derived from #1B1F1F at 35% -> #6B6D6D (#FFFFFF 5.21:1, #F0F7F7 4.80:1)
   --color-shadow derived from #1B1F1F at 10% alpha -> rgba(27, 31, 31, 0.1)
   --color-focus falls back to secondary-on-light (#487C28); no single colour reaches 3.0:1 on every light and dark surface
   --color-rating from the reference gold #F5B301 -> #B88601 (#FFFFFF 3.26:1, #F0F7F7 3.00:1)
*/
:root {
  --color-primary: #017D7D;
  --color-secondary: #68B239;
  --surface-default: #FFFFFF;
  --surface-accent: #F0F7F7;
  --color-accent: var(--surface-accent);
  --color-secondary-on-light: #487C28;
  --color-neutral-dark: #1B1F1F;
  --color-neutral-light: var(--surface-default);
  --color-contrast: #FFFFFF;
  --color-border-subtle: rgba(27, 31, 31, 0.12);
  --color-muted: #6B6D6D;
  --color-shadow: rgba(27, 31, 31, 0.1);
  --color-shadow-strong: rgba(27, 31, 31, 0.28);
  --color-focus: #487C28;
  --color-rating: #B88601;
  --font-heading: "Tilt Warp", "Tilt Warp Fallback", "Arial Black", Impact, sans-serif;
  --font-body: "Bricolage Grotesque", "Bricolage Fallback", "Segoe UI", system-ui, sans-serif;
  --site-width: 1140px;
  --input-radius: 0;
}
html { --fs: 1; }

/* --- Layout --- */
.site-width {
  width: 100%;
  max-width: var(--site-width);
  margin-inline: auto;
  padding-inline: 20px;
}

*, *::before, *::after { box-sizing: border-box; }

img, svg, video { max-width: 100%; height: auto; }

/* --- Typography --- */
body {
  font-family: var(--font-body);
  font-size: calc(17px * var(--fs, 1));
  line-height: 1.7;
  font-weight: 400;
  color: var(--color-neutral-dark);
  background: var(--surface-default);
  margin: 0;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  margin: 0 0 0.5em;
}

h1 {
  font-size: calc(clamp(32px, 4vw, 48px) * var(--fs, 1));
  font-weight: 800;
  line-height: 1.25;
}

h2 {
  font-size: calc(32px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.25;
}

h3 {
  font-size: calc(24px * var(--fs, 1));
  font-weight: 600;
  line-height: 1.33;
}

h4 {
  font-size: calc(20px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.4;
}

h5 {
  font-size: calc(18px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.4;
}

h6 {
  font-size: calc(16px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.4;
}

/* --- Surfaces --- */
.surface-announcement-banner {
  background: var(--surface-accent);
}

.surface-body-placeholder {
  background: var(--surface-default);
}

.surface-community {
  background: var(--surface-default);
}

.surface-contact-section {
  background: var(--surface-accent);
}

.surface-page-body {
  background: var(--surface-default);
}

.surface-service-area {
  background: var(--surface-default);
}

.surface-services-type-a {
  background: var(--surface-default);
}

.surface-services-type-b {
  background: var(--surface-accent);
}

.surface-services-type-c {
  background: var(--surface-default);
}

.surface-trust-bar-container {
  background: var(--surface-default);
}

.surface-trust-bar-review-card {
  background: var(--surface-accent);
}

/* --- Buttons and focus --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 20px;
  border-radius: 4px;
  border: 2px solid transparent;
  font-family: var(--font-heading);
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  font-size: calc(16px * var(--fs, 1));
  transition: background-color 120ms linear, color 120ms linear,
    border-color 120ms linear;
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-contrast);
  border-color: var(--color-primary);
}

.btn-secondary {
  background: var(--color-secondary);
  color: var(--color-neutral-dark);
  border-color: var(--color-secondary);
}

/* On dark chrome the same class flips to a light fill. The chrome
   classes are .site-header and .site-footer, which is what the
   accessibility class contract names; .header and .footer matched
   nothing and were corrected in Increment 3 (ruling D-7). */
.site-header .btn-secondary:hover,
.hero .btn-secondary:hover,
.site-footer .btn-secondary:hover {
  background: var(--color-contrast);
  color: var(--color-neutral-dark);
  border-color: var(--color-contrast);
}

/* XCUT-SPEC-024 (candidate BTN-KEVIN-HOV-001): a secondary button in a light container
   hovers to primary fill with secondary text, so it never flips
   to white-on-white. It comes AFTER the dark-chrome rule on purpose:
   .hero .btn-secondary:hover and .hero-form .btn-secondary:hover tie
   on specificity, so source order decides the hero form's submit.
   Before Increment 4 the dark rule came last and won. */
.hero-form .btn-secondary:hover,
.contact-form .btn-secondary:hover,
.surface-services-type-b .btn-secondary:hover {
  background: var(--color-primary);
  color: var(--color-secondary);
  border-color: var(--color-primary);
}

.btn-primary:hover {
  background: var(--color-contrast);
  color: var(--color-neutral-dark);
  border-color: var(--color-neutral-dark);
}

/* ADA-SPEC-001 / ADA-WCAG-KEY-002: 3px solid --color-focus at a 3px offset,
   the Accessibility Skill base's own ring. This rule outranks the verbatim
   :focus-visible, so it has to carry the same offset (Stage 4, D-1). */
.btn:focus-visible, a:focus-visible, button:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

/* --- Links --- */
/* Text on light surfaces uses secondary-on-light, never raw secondary. */
.surface-default a, .surface-accent a, main a {
  color: var(--color-secondary-on-light);
  text-decoration: underline;
}

.on-dark a {
  color: var(--color-secondary);
  text-decoration: underline;
}

a:hover { text-decoration: underline; }

/* --- Form inputs --- */
input, select, textarea {
  font-family: var(--font-body);
  font-size: calc(16px * var(--fs, 1));
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--input-radius);
  padding: 12px 14px;
  width: 100%;
}

/* --- Breakpoints --- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Header: system mobile chrome, menu, action bar and pulse call (client-scoped variant) --- */

.header-inner { display: none; }
.mobile-chrome { display: flex; }

@media (min-width: 1024px) {
  .header-inner { display: flex; }
  .mobile-chrome { display: none; }
  .mobile-menu-overlay { display: none; }
}

.site-header {
  background: var(--color-primary);
  color: var(--color-contrast);
  position: sticky;
  top: 0;
  z-index: 100;
  padding: 0;
}

.header-inner {
  width: 100%;
  max-width: var(--site-width);
  margin-inline: auto;
  padding-inline: 20px;
  align-items: center;
  gap: 16px;
  min-height: 100px;
}

.site-header .logo,
.site-header .logo-mobile {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* Kevin ruling K-9 (2026-09-19), the Header-logo correction. The logo
   used to be a fixed 44px (48px in the chrome) while the widget grew all
   the navigation and button text around it, so at 150-175% it read as
   disproportionately small: at 1440px the header grew from 140px to
   439.6px tall and the logo never moved off 118 x 44.

   It now scales with the text setting, responsively: full 1:1 on the
   desktop row, capped in the mobile chrome, and not at all below 480px
   where K-7 owns the space (see LOGO_MOBILE_SCALED_CAP above). This is
   a BCS usability and visual-consistency rule, not a WCAG requirement:
   no success criterion asks a logo to track text size.

   max-height on the real element, so the layout box grows with it: never
   transform: scale(), which would leave the link box behind and paint the
   logo over its neighbours. width stays auto, so the intrinsic aspect
   ratio is preserved and nothing is cropped, stretched or filtered.
   At --fs 1 the calc is exactly the approved value, so 100% text is
   byte-identical.

   Measured at 17 widths x all five steps. The desktop row takes the
   full 1:1 once the dropdown panels are clamped (render_nav_css /
   fitDropdowns); the mobile chrome could not, and its measured caps are
   on LOGO_MOBILE_SCALED_CAP above. See
   docs/STATUS_pre_stage5_footer_logo_checkpoint.md. */
.site-header .logo img { max-height: calc(44px * var(--fs, 1)); width: auto; }
.site-header .logo-mobile img { max-height: min(calc(48px * var(--fs, 1)), 56px); width: auto; }

/* Stage 4 ruling R-4 (ADA-SPEC-041): every mobile tap target is at least
   44px tall. The two that were not grow their hit area, not their
   look. The logo link becomes a 44px-tall box around the unchanged,
   centred image. The banner link takes 10px of padding above and below and
   gives it back as negative margin, so the banner's height, the header's
   and every approved measurement stay exactly as they were. */
@media (max-width: 1023px) {
  .mobile-chrome .logo-mobile { min-height: 44px; }
  .announcement-banner a { padding-block: 11px; margin-block: -11px; }
}

.mobile-chrome {
  background: var(--color-primary);
  color: var(--color-contrast);
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: var(--site-width);
  margin-inline: auto;
  padding-inline: 16px;
  min-height: 100px;
}

.mobile-chrome .btn-compact {
  background: var(--color-secondary);
  color: var(--color-neutral-dark);
  border-color: var(--color-secondary);
  margin-left: auto;
  padding: 14px 16px;
  font-size: calc(13px * var(--fs, 1));
  min-height: 48px;
  max-width: 160px;
  white-space: nowrap;
}

/* Part 5, tablet: shrink horizontal padding before growing vertically. */
@media (max-width: 767px) {
  .mobile-chrome .btn-compact { padding-inline: 12px; }
}

/* Narrow mobile, below 480px (finding H-1; corrected at browser review
   2026-09-18). Normal text keeps ONE row, in markup order: logo, quote,
   phone, hamburger, as the approved wider chrome does. The logo gives
   way first (it shrinks to the space left); gaps and inline padding
   tighten; the quote button stays content-width with its full wording
   and is never stretched. Phone and hamburger keep 44x44. */
@media (max-width: 479px) {
  .mobile-chrome {
    gap: 8px;
    padding-inline: 12px;
  }
  /* K-9 follow-up: the link must not grow past its image, or the
     empty part of it navigates home invisibly (5.2px at 430px, 54.2px
     at 479px). flex-grow drops to 0; the shrink stays, because below
     ~430px the logo is what gives way. Nothing moves: the row's free
     space is simply taken by the quote button's existing
     `margin-left: auto` instead, a layout margin that was already
     there and is not interactive. Measured at 320, 360, 390, 430 and
     479px x all five text steps, menu open and closed: the chrome,
     the image, the quote, the phone, the hamburger, the header and
     the banner all keep identical boxes. */
  .mobile-chrome .logo-mobile {
    flex: 0 1 auto;
    min-width: 0;
  }
  .mobile-chrome .logo-mobile img {
    max-width: 100%;
    height: auto;
    /* K-9: below 480px the logo keeps its approved 48px and does not
       scale. K-7 has already reclaimed every spare pixel here for the
       open menu, and a taller logo takes that band back 1:1: measured
       142px -> 107px at full 1:1, which clips the 124.8px menu item's
       focus ring at 320px and 175%. It would also make the logo change
       size when the menu opens, which K-7 forbids. */
    max-height: 48px;
  }
  .mobile-chrome .btn-compact {
    flex: 0 0 auto;
    padding-inline: 10px;
    line-height: 1.2;
    text-align: center;
  }
}

/* Below 375px the one-line label would leave the logo too little room,
   so the full wording wraps compactly inside the button (GET INSTANT /
   QUOTE). The cap is in em, so it follows the label's own size. */
@media (max-width: 374px) {
  .mobile-chrome .btn-compact {
    white-space: normal;
    max-width: 9.5em;
    padding-block: 8px;
  }
  /* K-7 final pass: at the smallest phones, under enlarged text, while the
     menu is open, the top-level items' vertical padding tightens so the
     tallest two-line item and its whole focus ring fit the reclaimed
     menu area (142px at 320px and 175%). Text size and line-height are
     unchanged; every item keeps well over 44px. */
  html[data-a11y-text="scaled"] body.menu-open .mobile-menu-label {
    padding-block: 12px;
  }
  html[data-a11y-text="scaled"] .mobile-menu-label { overflow-wrap: anywhere; }
}

/* Scaled text in the one-row range (finding H-7): the 160px cap and nowrap
   made the full CTA wording spill out of the button from the first text
   step. Under the widget's scaled state only, the button grows to fit
   its label where the row has room and wraps where it does not. Normal
   text keeps the approved compact button. */
html[data-a11y-text="scaled"] .mobile-chrome .btn-compact {
  max-width: none;
  min-width: 0;
  white-space: normal;
  text-align: center;
}

/* Boundary defect found in the K-9 width sweep, and older than K-9: the
   banner link's hit area and the quote button overlapped by 2.2px at 150%
   and 3px at 175%, at every width from 480 to 580px.

   Measured cause. R-4 gives the banner link padding-block 11px with a
   matching negative margin, so its 44px hit box overhangs the banner's
   painted bottom by 3px. From 480px the chrome is one row again, and at
   150% and above the quote button's label wraps to three or four lines:
   98.3px at 150%, 148px at 175%. That is taller than the row's 100px
   minimum, so align-items: center has no slack left and the button's top
   lands exactly on the chrome's top edge, inside the banner link's
   overhang. Below 480px the two-row fallback already pads the chrome and
   the button sits 64px clear; from 600px the button is 70.7px, shorter
   than the row, and centring leaves 14.7px.

   The correction is the same device the two-row fallback uses, scoped to
   the one-row range and to the widget's scaled state, so the approved
   100% chrome is untouched: the row keeps its own padding, so a button
   taller than the row can never reach the chrome's edge. border-box
   means the 100px minimum absorbs the padding, so every state where the
   button already fits is unchanged. */
@media (min-width: 480px) {
  html[data-a11y-text="scaled"] .mobile-chrome {
    padding-block: 8px;
  }
}

/* Enlarged-text fallback, below 480px only: at 150% and above a single
   row cannot stay readable and collision-free, so under the widget's
   scaled state the chrome takes two controlled rows. Row 1 is the logo
   and the hamburger; row 2 is the quote and the phone, centred, the
   quote wrapping inside its button beside the phone. `order` is visual
   only; the markup and the focus order are unchanged. Normal text never
   uses this. */
@media (max-width: 479px) {
  html[data-a11y-text="scaled"] .mobile-chrome {
    flex-wrap: wrap;
    justify-content: center;
    column-gap: 12px;
    row-gap: 8px;
    padding-block: 8px;
  }
  /* K-9: the link sizes to the logo, and K-7's own spacer below takes
     the rest of row 1. It used to flex across the whole row, so at 390px
     and 150% the link was 310px wide around a 128.8px image: 181px of
     invisible clickable space that navigated home.

     An auto margin was tried first and measured wrong: the large
     flex-basis was not only filling the row, it was what forced the wrap
     into two rows at all. With the logo content-sized the margin only
     ever won 4px of its own line, and the hamburger left the right edge
     at 412 and 479px. The spacer carries the basis, so the row structure
     is exactly K-7's. */
  html[data-a11y-text="scaled"] .mobile-chrome .logo-mobile {
    order: 1;
    flex: 0 0 auto;
  }
  html[data-a11y-text="scaled"] .mobile-chrome .hamburger { order: 2; }
  html[data-a11y-text="scaled"] .mobile-chrome .btn-compact {
    order: 3;
    flex: 0 1 auto;
    margin-left: 0;
    max-width: calc(100% - 44px - 12px);
  }
  html[data-a11y-text="scaled"] .mobile-chrome > a.icon-btn { order: 4; }
  /* Ruling K-1 (pre-Stage-4 checkpoint): in this same state the
     announcement banner scrolls away and the chrome, with both action
     buttons, stays sticky. At 320px and 175% the whole header was 420px
     of a 568px screen; the chrome alone is 147px. The banner is still
     first at the top of the page. --banner-height is measured by the
     header script; without it (no JavaScript, so no widget either) the
     whole header sticks as before. 100% text never uses this. */
  html[data-a11y-text="scaled"] .site-header {
    top: calc(-1 * var(--banner-height, 0px));
  }
  /* Ruling K-7 (pre-Stage-4 checkpoint), in this same state and only
     while the menu is open: the widget launcher moves into the chrome's
     top row so the menu gets back the 88px band below it. At 320px and
     175% that band left 54px for 94px items and clipped their focus
     rings. The logo link, which filled the row, sizes to its image; an
     empty spacer (never interactive) takes the freed width, so the close
     button stays right and the quote and call keep row 2. The spacer's
     width comes from the measured logo width (--logo-width), and the
     launcher's position from the measured logo image and close button
     (--launcher-x, --launcher-y): no fixed offsets. Closing the menu,
     100% text or a viewport over 479px drops every rule at once. */
  html[data-a11y-text="scaled"] body.menu-open .mobile-chrome .logo-mobile {
    flex: 0 0 auto;
  }
  /* K-7's spacer. K-9 applies it throughout the scaled state, not only
     while the menu is open: it is what carries the row-filling basis, so
     the two-row structure and the hamburger's right edge are identical
     open and closed, with the logo link sized to its image in both. */
  html[data-a11y-text="scaled"] .mobile-chrome::after {
    content: "";
    order: 1;
    flex: 1 1 calc(100% - var(--logo-width, 0px) - 44px - 2 * 12px);
    pointer-events: none;
  }
  html[data-a11y-text="scaled"] body.menu-open #a11y-widget {
    left: var(--launcher-x, 12px);
    top: var(--launcher-y, 12px);
    bottom: auto;
  }
  html[data-a11y-text="scaled"] body.menu-open .mobile-menu-content {
    margin-bottom: 0;
  }
  /* At the top of the viewport the launcher's outward ring (and high
     contrast's 6px halo) ran ~2px off the screen. In this state only, the
     ring is drawn inward, between the contrast border and the dark face, in
     the secondary colour (9:1 on the face; high contrast's bright yellow on
     black there). The target stays 56x56 and does not move. */
  html[data-a11y-text="scaled"] body.menu-open .a11y-toggle:focus-visible {
    outline: 3px solid var(--color-secondary);
    outline-offset: -6px;
    box-shadow: 0 6px 18px var(--color-shadow-strong);
  }
}

/* ADA-WCAG-LNK-003 / Part 17: 22px glyph inside a 44x44 tap target. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  padding: 0;
  background: transparent;
  border: 2px solid transparent;
  color: var(--color-contrast);
  cursor: pointer;
}

.icon-btn .icon { width: 22px; height: 22px; }

/* Accessibility Skill Part 3.9: the glyph toggles must honour [hidden]
   so author CSS can never override the attribute. */
.icon-btn [hidden] { display: none; }

/* The overlay starts below the WHOLE sticky header: announcement banner
   plus mobile chrome, not the chrome alone. Both wrap at narrow widths, so
   render_mobile_menu_script() measures .site-header on open and on resize
   and writes --header-offset. The fallback is the two pinned heights added
   together, for the moment before the first measurement. */
.mobile-menu-overlay {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: var(--header-offset, 148px);
  background: var(--color-neutral-light);
  color: var(--color-neutral-dark);
  display: flex;
  flex-direction: column;
  z-index: 90;
  transform: translateY(-8px);
  opacity: 0;
  transition: transform 250ms ease, opacity 250ms ease;
}

.mobile-menu-overlay[hidden] { display: none; }

.mobile-menu-overlay[aria-hidden="false"] {
  transform: translateY(0);
  opacity: 1;
}

/* Ruling K-5: the lifted widget launcher (its approved position, above
   the strip; see the menu-open rule below) sat over menu items, at 320px
   over SERVICE AREAS on first paint. The scroll area now ends a fixed
   band above the strip that is exactly the launcher's footprint, so no
   item is ever under it, before or after focus. The top spacer keeps the
   first item's focus ring inside the scroll area, which clipped its top
   edge, and the bottom one does the same for the last item (K-7 browser
   pass). Both are scrolled content, not padding, so they never push the
   strip off the screen. Pre-Stage-4 checkpoint. */
.mobile-menu-content {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: 88px;
}

.mobile-menu-content::before,
.mobile-menu-content::after {
  content: "";
  display: block;
  height: 8px;
}

/* A focused item is scrolled just into view; the margin keeps its ring
   (which sits outside the item) inside the scroll area too. */
.mobile-menu-content a,
.mobile-menu-content button {
  scroll-margin-block: 8px;
}

.mobile-menu-items,
.mobile-submenu {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Part 18: 1px divider in border-subtle. See the module docstring on
   NAV-SPEC-003 and its literal hex. */
.mobile-menu-item {
  border-bottom: 1px solid var(--color-border-subtle);
}

.mobile-menu-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-left: 24px;
}

.mobile-menu-label {
  flex: 1 1 auto;
  /* Stage 5 (R-6, F-12): a flex item's default min-width is its content,
     so one long word (RESOURCES at 320px and 175%) pushed the chevron
     off screen. The label may shrink; under scaled text it may break
     the word (ADA-ABC-TXT-002), never at 100%. */
  min-width: 0;
  padding: 22px 0;
  color: var(--color-neutral-dark);
  text-decoration: none;
  text-transform: uppercase;
  font-family: var(--font-heading);
  font-size: calc(24px * var(--fs, 1));
  font-weight: 800;
  line-height: 1.2;
}

/* An item with no chevron ran its link to the screen edge, cutting off
   the right side of its focus ring (REVIEWS, K-7 browser pass). It keeps
   the chevron's own 16px inset instead. */
.mobile-menu-row > .mobile-menu-label:last-child { margin-right: 16px; }

/* Part 18: the current page's label turns primary, top level and sub.
   NAV-SPEC-007: so does a hovered one (Stage 4, D-3). */
.mobile-menu-item.active > .mobile-menu-row > .mobile-menu-label,
.mobile-submenu li.active > a,
.mobile-menu-label:hover,
.mobile-submenu a:hover {
  color: var(--color-primary);
}

.chevron-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  margin-right: 16px;
  padding: 0;
  background: transparent;
  border: 2px solid transparent;
  color: var(--color-neutral-dark);
  cursor: pointer;
}

.chevron-btn .icon {
  width: 23px;
  height: 12px;
  transition: transform 150ms ease;
}

.chevron-btn[aria-expanded="true"] .icon { transform: rotate(180deg); }
.chevron-btn[aria-expanded="true"] { color: var(--color-primary); }

.mobile-submenu[hidden] { display: none; }

/* Stage 5 (K5-03): submenu group labels, indented with the sub-items. */
.mobile-submenu-group > ul { list-style: none; margin: 0; padding: 0; }
.mobile-submenu-group-label {
  display: block;
  padding: 14px 24px 2px 44px;
  font-family: var(--font-heading);
  font-size: calc(12px * var(--fs, 1));
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.mobile-submenu a {
  display: block;
  padding: 16px 24px 16px 44px;
  color: var(--color-neutral-dark);
  text-decoration: none;
  font-family: var(--font-heading);
  font-size: calc(13px * var(--fs, 1));
  font-weight: 700;
}

/* Part 18: sticky floating CTA strip, two buttons only. */
.mobile-menu-floating-ctas {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 20px;
  background: var(--color-neutral-light);
  border-top: 1px solid var(--color-border-subtle);
}

/* Pre-Stage-4 checkpoint, strip shape. `flex: 1 1 0` forced two equal
   halves at every width, so below ~444px each label wrapped inside a
   near-square box and the phone number broke after its hyphen. Each
   button now sizes to its one-line label: the two share a row where both
   fit (Part 18, side by side) and each takes the full row where they do
   not. The number never breaks; labels are centred. */
.mobile-menu-floating-ctas .btn {
  flex: 1 1 auto;
  min-height: 56px;
  padding-inline: 16px;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
}

.mobile-menu-floating-ctas .btn-secondary > span { white-space: nowrap; }

/* Stage 5 (K5-11, RULE-7): the strip's two buttons are the brand's own
   hierarchy, quote in primary and call in secondary, on the light strip.
   A third fill (neutral-dark) read as an unrelated black button on a navy
   and grey brand. The call button takes a primary edge and primary text
   so it reads on the light strip (ADA-WCAG-COL-003) and hovers to
   primary fill with secondary text, the light-container rule
   (BTN-KEVIN-HOV-001). */
.mobile-menu-floating-ctas .btn-secondary {
  color: var(--color-primary);
  border-color: var(--color-primary);
  gap: 8px;
}
.mobile-menu-floating-ctas .btn-secondary:hover {
  background: var(--color-primary);
  color: var(--color-secondary);
  border-color: var(--color-primary);
}

/* Enlarged text: the quote label may wrap, centred, rather than overflow
   the strip. The phone number above still never breaks. */
html[data-a11y-text="scaled"] .mobile-menu-floating-ctas .btn {
  white-space: normal;
  min-width: 0;
}

/* Part 18 gives ~10-11px here. Kevin's pre-Stage-4 ruling raised it to a
   comfortably readable size: 14px, the footer's hours line and the
   banner's size. */
.mobile-menu-floating-ctas .hours-line {
  flex: 1 0 100%;
  text-align: center;
  text-transform: uppercase;
  font-size: calc(14px * var(--fs, 1));
  font-weight: 700;
  color: var(--color-neutral-dark);
  max-width: none;
}

.mobile-menu-floating-ctas .icon { width: 18px; height: 18px; }

/* ADA-WCAG-NAV-003: body scroll is locked while the overlay is open. */
body.menu-open { overflow: hidden; }

/* Accessibility Skill Part 5.1 fixes the widget bottom-left at z-index 1200,
   which puts it on top of the floating CTA strip while the menu is open. The
   stored asset is byte-for-byte untouched; this header-layer rule outranks it
   on specificity (id + class + element beats the asset's single class) and
   lifts the widget clear of the strip. It stops applying the moment the
   menu-open class comes off, so the widget returns to its own position. */
body.menu-open #a11y-widget {
  bottom: calc(var(--menu-cta-strip-height, 132px) + 16px);
}

.header-inner > .logo,
.main-nav > ul > li > a,
.header-ctas a,
.mobile-chrome a,
.mobile-chrome button { scroll-margin-top: -100vh; }

/* brand.logo.mobile_height: 56px; ceiling 56px. */
.site-header .logo-mobile img { max-height: min(calc(56px * var(--fs, 1)), 56px); }
@media (max-width: 479px) {
  .mobile-chrome .logo-mobile img { max-height: 48px; }
}

/* --- Dropdown-only menu parents (menu.items[].dropdown_only) --- */
.nav-item > .nav-disclosure {
  display: inline-block;
  margin: 0;
  padding: 12px 0;
  background: none;
  border: 0;
  border-bottom: 6px solid transparent;
  color: var(--color-contrast);
  text-transform: uppercase;
  font-family: var(--font-heading);
  font-size: calc(20px * var(--fs, 1));
  font-weight: 700;
  line-height: inherit;
  white-space: nowrap;
  cursor: pointer;
  scroll-margin-top: -100vh;
}
.nav-item.has-dropdown:hover > .nav-disclosure,
.nav-item.has-dropdown:focus-within > .nav-disclosure,
.nav-item.is-open > .nav-disclosure { border-bottom-color: var(--color-contrast); }
.nav-item.is-open > .dropdown { opacity: 1; visibility: visible; }
/* Closed by its button or Escape while hovered or focused. */
.nav-item.is-collapsed > .dropdown { opacity: 0; visibility: hidden; }
.nav-item.is-collapsed > .nav-disclosure { border-bottom-color: transparent; }
@media (max-width: 1279px) {
  .nav-item > .nav-disclosure { font-size: calc(16px * var(--fs, 1)); }
}
.mobile-menu-toggle {
  margin: 0;
  background: none;
  border: 0;
  text-align: left;
  font-weight: 700;
  cursor: pointer;
}

/* --- Mobile chrome: logo and MENU; bottom action bar (layout.mobile_header: action_bar) --- */
/* Kevin's final pass: a compact navy MENU button with a thin white border, white text and
   slim lines. Closed and open share one box (the X replaces the lines at the same size). */
.mobile-chrome .menu-box {
  flex-direction: column;
  gap: 2px;
  min-width: 48px;
  width: auto;
  height: 44px;
  margin-left: auto;
  padding: 3px 5px;
  background: var(--color-primary);
  border: 1px solid var(--color-contrast);
  border-radius: 4px;
  color: var(--color-contrast);
}
.mobile-chrome .menu-box .menu-word {
  font-family: var(--font-heading);
  font-size: calc(10px * var(--fs, 1));
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
}
.mobile-chrome .menu-box .icon { width: 36px; height: 16px; }
.mobile-chrome { min-height: 76px; }
@media (hover: hover) {
  .mobile-chrome .menu-box:hover { background: var(--color-contrast); color: var(--color-primary); }
}
.mobile-chrome .menu-box:focus-visible { outline: 3px solid var(--color-secondary); outline-offset: 3px; }

/* The bottom bar (Kevin's final reference): navy, a thin red top edge; on the left a navy
   circle with a thin red outline and a white outline handset, CALL US beside it; on the
   right the red quote button. Only the circle's rings move (the desktop pulse's timing). */
.mobile-action-bar { display: none; }
@media (max-width: 1023px) {
  .mobile-action-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 80;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: 16px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--color-primary);
    border-top: 3px solid var(--color-secondary);
    box-shadow: 0 -6px 18px var(--color-shadow-strong);
  }
  .mab-call {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 48px;
    padding-right: 4px;
    color: var(--color-contrast);
    text-decoration: none;
    border-radius: 4px;
  }
  .mab-call-circle {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    flex: 0 0 46px;
    box-sizing: border-box;
    border: 2px solid var(--color-secondary);
    border-radius: 50%;
    background: var(--color-primary);
    color: var(--color-contrast);
  }
  .mab-call-circle .icon { position: relative; z-index: 1; width: 22px; height: 22px; }
  .mab-call-circle::before,
  .mab-call-circle::after {
    content: "";
    position: absolute;
    inset: -2px;
    border: 2px solid var(--color-secondary);
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
    animation: mab-call-pulse 2.4s ease-out infinite;
  }
  .mab-call-circle::after { animation-delay: 1.2s; }
  .mab-call-label {
    font-family: var(--font-heading);
    font-size: calc(15px * var(--fs, 1));
    font-weight: 800;
    letter-spacing: 0.02em;
    line-height: 1.2;
    text-transform: uppercase;
    white-space: nowrap;
  }
  .mab-quote {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 8px 12px;
    background: var(--color-secondary);
    border: 2px solid var(--color-secondary);
    border-radius: 4px;
    color: var(--color-neutral-dark);
    font-family: var(--font-heading);
    font-size: calc(16px * var(--fs, 1));
    font-weight: 800;
    line-height: 1.15;
    text-align: center;
    text-transform: uppercase;
    text-decoration: none;
  }
  .mab-call:focus-visible, .mab-quote:focus-visible { outline: 3px solid var(--color-contrast); outline-offset: 3px; }
  /* The open menu's strip, in the bar's colours (Kevin's final pass): the quote red with
     navy text, the phone navy with white text and icon. Order, size and destinations unchanged. */
  .mobile-menu-floating-ctas .btn-primary,
  .mobile-menu-floating-ctas .btn-primary:hover { background: var(--color-secondary); border-color: var(--color-secondary); color: var(--color-neutral-dark); }
  .mobile-menu-floating-ctas .btn-secondary,
  .mobile-menu-floating-ctas .btn-secondary:hover { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-contrast); }
  .mobile-menu-floating-ctas .btn-secondary .icon { color: var(--color-contrast); }
  /* The phone number at the mobile Contact page's call-button size (19px); the icon and the
     56px button are unchanged. */
  .mobile-menu-floating-ctas .btn-secondary { font-size: calc(19px * var(--fs, 1)); line-height: 19.2px; }
}
/* Where the phone and quote share a row, they keep the widths the 16px number gave them: the
   quote 24px wider than the phone, sharing the row. Below 466px the larger number needs more
   room than those widths allow, so there the two size to their text. Enlarged text keeps its
   own wrapping. */
@media (min-width: 466px) and (max-width: 1023px) {
  html:not([data-a11y-text="scaled"]) .mobile-menu-floating-ctas .btn-secondary { flex: 0 0 calc(50% - 18px); }
  html:not([data-a11y-text="scaled"]) .mobile-menu-floating-ctas .btn-primary { flex: 0 0 calc(50% + 6px); }
}
@media (max-width: 1023px) {
  /* Never two bars: the open menu carries its own call and quote strip. While a typing
     field has focus the bar steps aside for the field and the keyboard. */
  body.menu-open .mobile-action-bar { display: none; }
  body.form-focus .mobile-action-bar { visibility: hidden; transform: translateY(110%); }
  body.form-focus #a11y-widget { bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  /* Page-end clearance: the footer's last row stays above the bar and the launcher.
     Specific enough to follow the footer layer's own rules. */
  html body .site-footer .footer-legal { padding-bottom: calc(152px + env(safe-area-inset-bottom, 0px)); }
  html body .site-footer a, html body main a, html body main button, html body main input, html body main select, html body main textarea { scroll-margin-bottom: calc(calc(68px + 3px + env(safe-area-inset-bottom, 0px)) + 16px); }
  /* The launcher rides above the bar. */
  #a11y-widget { bottom: calc(calc(68px + 3px + env(safe-area-inset-bottom, 0px)) + 12px); }
}
@keyframes mab-call-pulse { 0% { transform: scale(1); opacity: 0.8; } 100% { transform: scale(1.6); opacity: 0; } }
@media (max-width: 1023px) and (hover: hover) {
  .mab-call:hover .mab-call-label { text-decoration: underline; text-underline-offset: 3px; }
  .mab-quote:hover { background: var(--color-contrast); border-color: var(--color-contrast); }
}
/* Static under reduced motion: the OS preference or the widget's motion control. */
@media (prefers-reduced-motion: reduce) {
  .mab-call-circle::before, .mab-call-circle::after { animation: none; opacity: 0; }
  .mab-call-circle::before { opacity: 0.45; transform: scale(1.25); }
}
html[data-a11y-motion="reduce"] .mab-call-circle::before, html[data-a11y-motion="reduce"] .mab-call-circle::after { animation: none; opacity: 0; }
html[data-a11y-motion="reduce"] .mab-call-circle::before { opacity: 0.45; transform: scale(1.25); }
@media (max-width: 767px) {
  #a11y-widget .a11y-panel { bottom: calc(calc(68px + 3px + env(safe-area-inset-bottom, 0px)) + 80px); max-height: calc(100vh - calc(68px + 3px + env(safe-area-inset-bottom, 0px)) - 200px); }
}
/* The smallest phones: both actions stay on one line and fully tappable. */
@media (max-width: 374px) {
  .mobile-action-bar { column-gap: 12px; padding-inline: 14px; }
  .mab-call { gap: 8px; }
  .mab-call-label { font-size: calc(14px * var(--fs, 1)); }
  .mab-quote { padding-inline: 8px; font-size: calc(14px * var(--fs, 1)); }
}
@media (max-width: 339px) {
  .mab-quote { font-size: calc(13px * var(--fs, 1)); }
}

/* --- Mobile submenus, large (layout.mobile_submenus: large) --- */
.mobile-submenu a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 24px 10px 40px;
  font-size: calc(20px * var(--fs, 1));
  line-height: 1.25;
}
.mobile-submenu { padding-bottom: 12px; }
.mobile-submenu-group-label { padding: 16px 24px 4px 40px; font-size: calc(13px * var(--fs, 1)); }
.mobile-menu-overlay .chevron-btn {
  width: 44px;
  height: 44px;
  border: 0;
  position: relative;
}
.mobile-menu-overlay .chevron-btn::before {
  content: "";
  position: absolute;
  width: 40px;
  height: 40px;
  border: 2px solid currentColor;
  border-radius: 50%;
  box-sizing: border-box;
}
.mobile-menu-overlay .chevron-btn .icon { position: relative; width: 17px; height: 9px; margin-top: 2px; }
.mobile-menu-overlay .chevron-btn[aria-expanded="true"] { color: var(--color-contrast); }
.mobile-menu-overlay .chevron-btn[aria-expanded="true"]::before { background: var(--color-primary); border-color: var(--color-primary); }
.mobile-menu-overlay .chevron-btn[aria-expanded="true"] .icon { margin-top: -2px; }
/* A toggle row: the label button fills the row up to the chevron, so the whole row opens it. */
.mobile-menu-row > .mobile-menu-toggle { align-self: stretch; padding-block: 22px; }
.mobile-menu-row > .mobile-menu-toggle[aria-expanded="true"] { color: var(--color-primary); }

/* --- Accessibility launcher on the right edge (layout.a11y_launcher: right) --- */
#a11y-widget { left: auto; right: 18px; }
#a11y-widget .a11y-panel { left: auto; right: 0; }
@media (max-width: 767px) {
  #a11y-widget { left: auto; right: 12px; }
  #a11y-widget .a11y-panel { left: 12px; right: 12px; }
}
/* The open menu: the launcher floats on the right above the call strip. The menu's
   scroll area runs down to the strip (no reserved full-width band, which hid expanded
   links and caught taps across the whole row); its own bottom padding lets the last item
   scroll clear of the launcher. */
body.menu-open #a11y-widget { left: auto; right: 12px; }
.mobile-menu-content { margin-bottom: 0; }
.mobile-menu-items { padding-bottom: 88px; }

/* --- Header call with pulse rings (layout.header_call: pulse) --- */
.header-ctas--pulse { align-items: center; gap: 28px; }
.header-call {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--color-contrast);
  text-decoration: none;
  white-space: nowrap;
  border-radius: 4px;
}
.header-call-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  border-radius: 50%;
  background: var(--color-secondary);
  color: var(--color-neutral-dark);
}
.header-call-icon .icon { position: relative; z-index: 1; width: 22px; height: 22px; }
.header-call-icon::before,
.header-call-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid var(--color-secondary);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: header-call-pulse 2.4s ease-out infinite;
}
.header-call-icon::after { animation-delay: 1.2s; }
@keyframes header-call-pulse {
  0% { transform: scale(1); opacity: 0.8; }
  100% { transform: scale(1.7); opacity: 0; }
}
.header-call-text { display: flex; flex-direction: column; gap: 2px; line-height: 1.2; }
.header-call .phone-number { font-size: calc(18px * var(--fs, 1)); font-weight: 800; letter-spacing: 0.01em; }
.header-call .hours-line { font-size: calc(12px * var(--fs, 1)); max-width: none; }
.header-call:hover .phone-number { text-decoration: underline; text-underline-offset: 3px; }
.header-call:focus-visible { outline: 3px solid var(--color-contrast); outline-offset: 6px; }
@media (max-width: 1279px) {
  .header-ctas--pulse { gap: 24px; }
  .header-call .phone-number { font-size: calc(16px * var(--fs, 1)); }
  .header-call .hours-line { font-size: calc(11px * var(--fs, 1)); }
}
/* Static under reduced motion: the OS preference or the widget's motion control. */
@media (prefers-reduced-motion: reduce) {
  .header-call-icon::before, .header-call-icon::after { animation: none; opacity: 0; }
  .header-call-icon::before { opacity: 0.45; transform: scale(1.3); }
}
html[data-a11y-motion="reduce"] .header-call-icon::before, html[data-a11y-motion="reduce"] .header-call-icon::after { animation: none; opacity: 0; }
html[data-a11y-motion="reduce"] .header-call-icon::before { opacity: 0.45; transform: scale(1.3); }

/* --- Mobile submenus: See all emphasised (layout.mobile_see_all: emphasised) --- */
.mobile-menu-overlay .mobile-submenu a { font-family: var(--font-body); font-weight: 400; color: var(--mobile-submenu-color, var(--color-neutral-dark)); }
.mobile-menu-overlay .mobile-submenu > li:last-child { border-top: 1px solid var(--mobile-see-all-rule, var(--color-border-subtle)); margin: 6px 24px 0 40px; padding-top: 6px; }
.mobile-menu-overlay .mobile-submenu > li:last-child a {
  padding-left: 0; color: var(--color-primary); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; gap: 8px;
}
.mobile-menu-overlay .mobile-submenu > li:last-child a::after {
  content: ""; width: 16px; height: 16px; flex: none; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 16px no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 16px no-repeat;
}
/* --- Mobile menu: Accessibility row (layout.mobile_menu_accessibility: row), drawn as the plain rows --- */
.mobile-menu-overlay button.mobile-menu-a11y { appearance: none; background: transparent; border: 0; border-radius: 0; text-align: left; cursor: pointer; color: inherit; }
/* --- Accessibility launcher hidden on phones over the hero (layout.a11y_launcher_phone: after_hero) --- */
@media (max-width: 767px) {
  html .a11y-widget .a11y-toggle { transition: opacity .2s ease, visibility 0s linear 0s; }
  html .a11y-widget.a11y-off-hero .a11y-toggle { opacity: 0; visibility: hidden; transition: opacity .2s ease, visibility 0s linear .2s; }
  html .a11y-widget.a11y-instant .a11y-toggle, html[data-a11y-motion="reduce"] .a11y-widget .a11y-toggle,
  html[data-a11y-motion="reduce"] .a11y-widget.a11y-off-hero .a11y-toggle { transition: none; }
  @media (prefers-reduced-motion: reduce) { html .a11y-widget .a11y-toggle, html .a11y-widget.a11y-off-hero .a11y-toggle { transition: none; } }
}

/* --- Review carousel: the system's (trust_bar, Part 23 Pattern A), with its shared options --- */

/* Equal-width cells, one per platform (the markup sets --rating-cols),
   so the separators fall evenly and no tile looks offset. */
.trust-bar-ratings {
  display: grid;
  grid-template-columns: repeat(var(--rating-cols, 3), minmax(0, 240px));
  justify-content: center;
  padding: 20px 0;
  margin: 16px 0 24px;
}

/* Each tile centres its badge-and-information group in its cell, and
   the platform name, score, stars and count centre on one axis. The
   same rules for every platform. */
.rating-tile {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-areas: "icon name" "icon value" "icon stars" "icon count";
  justify-content: center;
  justify-items: center;
  column-gap: 12px;
  align-items: center;
  padding: 4px 16px;
  min-width: 0;
  text-align: center;
}

.rating-tile + .rating-tile { border-left: 1px solid var(--color-border-subtle); }

.platform-icon {
  grid-area: icon;
  width: 32px;
  height: 32px;
  max-width: none;  /* the global svg{max-width:100%} squeezed it to 18px */
  font-family: var(--font-heading);
}

/* The visible platform name is the primary identification; the
   lettered badge beside it is a generic mark. */
.rating-platform {
  grid-area: name;
  font-family: var(--font-heading);
  font-size: calc(15px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-neutral-dark);
}

.rating-value {
  grid-area: value;
  font-family: var(--font-heading);
  font-size: calc(28px * var(--fs, 1));
  font-weight: 700;
  line-height: 1.1;
  color: var(--color-neutral-dark);
}

.rating-tile .rating-stars { grid-area: stars; }

.rating-count {
  grid-area: count;
  font-size: calc(15px * var(--fs, 1));
  font-weight: 400;
  line-height: 1.4;
  color: var(--color-neutral-dark);
}

/* ADA-WCAG-IMG-003 star groups. The filled row is clipped to the rating;
   stars are graphics in --color-rating (Stage 5, RULE-2: a gold measured
   to 3:1 on the light surfaces, never a grey that reads as empty), and
   always sit next to the rating number (ADA-WCAG-COL-004). */
.rating-stars,
.review-stars {
  position: relative;
  display: inline-block;
  line-height: 0;
  white-space: nowrap;
}

.stars-empty svg,
.stars-fill svg {
  width: 16px;
  height: 16px;
  margin-right: 2px;
}

.stars-empty svg path {
  fill: none;
  stroke: var(--color-rating);
  stroke-width: 1.6;
}

.stars-fill {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--fill, 100%);
  overflow: hidden;
}

.stars-fill svg path { fill: var(--color-rating); }

@media (max-width: 767px) {
  .trust-bar-ratings {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 16px;
  }
  .trust-bar-ratings.ratings-many { grid-template-columns: minmax(0, 1fr); }
  .rating-tile { padding: 4px 8px; }
  .rating-tile + .rating-tile { border-left: 0; }
  /* A lone final tile (3 platforms) spans the row and centres beneath
     the pair above it, instead of sitting in the left column. */
  .trust-bar-ratings:not(.ratings-many) > .rating-tile:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

/* Below 375px a two-column cell is ~140px, and the badge beside the
   stack needs ~138px of content: the grid squeezed the badge and
   clipped the star row. There the badge sits above the same centred
   stack. */
@media (max-width: 374px) {
  .rating-tile {
    grid-template-columns: auto;
    grid-template-areas: "icon" "name" "value" "stars" "count";
    row-gap: 2px;
  }
}

/* Scaled text on mobile: two columns cannot hold a platform name at 150%
   and above at 320-360px ("Facebook" outgrows its ~136px column and the
   tiles collide), so the row stacks to one centred column. Normal text
   keeps the two-column layout above. */
@media (max-width: 767px) {
  html[data-a11y-text="scaled"] .trust-bar-ratings { grid-template-columns: minmax(0, 1fr); }
}

.review-card {
  background: var(--surface-accent);
  border-radius: 4px;
  padding: 24px 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.review-card > * {
  padding-inline: 15px;
  margin: 0;
}

/* The star row's filled layer is absolutely positioned against the padding
   box, so the row takes its 15px inset as margin, not padding; otherwise the
   fill sits 15px off the outline row. */
.review-card > .review-stars {
  padding-inline: 0;
  margin-inline: 15px;
  align-self: flex-start;
}

/* Stage 5 (register R-5, ADA-WCAG-COL-004): a card's stars sit beside their
   number, as the rating tiles' do, so the score is never colour and shape
   alone. The row is one flex line; the number is body-sized and bold. */
.review-card > .review-rating {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-inline: 0;
  margin-inline: 15px;
}
.review-rating .review-stars { margin: 0; }
.review-rating-value {
  font-family: var(--font-heading);
  font-size: calc(17px * var(--fs, 1));
  font-weight: 700;
  line-height: 1;
  color: var(--color-neutral-dark);
}

/* TRUST-SPEC-020 to 026: the card body. */
.review-text {
  font-family: var(--font-body);
  font-size: calc(17px * var(--fs, 1));
  font-weight: 400;
  line-height: 1.7;
  color: var(--color-neutral-dark);
  background: transparent;
  padding-inline: 15px;
  flex: 1 1 auto;
}

/* Part 26: the first sentence in bold for scannability. */
.review-text strong { font-weight: 700; }

.review-card cite { margin-top: auto; }

.trust-bar-carousel { position: relative; }

.carousel-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  position: relative;
}

.carousel-track::-webkit-scrollbar { display: none; }

.carousel-track > .review-card {
  flex: 0 0 calc((100% - 2 * 24px) / 3);
  scroll-snap-align: start;
}

@media (max-width: 767px) {
  .carousel-track > .review-card { flex-basis: 100%; }
}

/* Scaled text on tablet (768-1023px): three cards leave ~196px of text
   column, and at 150% and above a long word no longer fits it. Two per
   view there; desktop keeps Part 26's three. The script measures cards
   per view, so positions and dots follow. */
@media (min-width: 768px) and (max-width: 1023px) {
  html[data-a11y-text="scaled"] .carousel-track > .review-card {
    flex-basis: calc((100% - 24px) / 2);
  }
}

/* ADA-ABC-TXT-002: under scaled text only, a word longer than the line may
   break rather than clip. At 100% the brand rule against broken words holds. */
html[data-a11y-text="scaled"] .review-text { overflow-wrap: break-word; }

.carousel-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
}

/* ADA-WCAG-LNK-003: controls are real targets; the dot is a 10px mark
   inside a 24px button. */
.carousel-pause {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 2px solid var(--color-neutral-dark);
  border-radius: 50%;
  background: transparent;
  color: var(--color-neutral-dark);
  cursor: pointer;
}

.carousel-pause:hover { background: var(--color-secondary); }
.carousel-pause .icon { width: 18px; height: 18px; }
.carousel-pause [hidden] { display: none; }

.carousel-dots { display: flex; flex-wrap: wrap; justify-content: center; }

.carousel-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

/* Inactive dots are outlined, the active one filled: state is shape as
   well as aria-current, never colour alone (ADA-WCAG-COL-004). */
.carousel-dot::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--color-neutral-dark);
  box-sizing: border-box;
}

.carousel-dot[aria-current="true"]::before { background: var(--color-neutral-dark); }

/* --- Review carousel arrows (shared_patterns.review_carousel.arrows) --- */
.trust-bar-carousel .carousel-arrow {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; cursor: pointer;
  border: 2px solid var(--carousel-control-color, var(--color-neutral-dark)); border-radius: 50%; background: var(--surface-default);
  color: var(--carousel-control-color, var(--color-neutral-dark));
}
.trust-bar-carousel .carousel-arrow:hover { background: var(--carousel-arrow-hover, var(--surface-accent)); }
.trust-bar-carousel .carousel-arrow svg { width: 20px; height: 20px; display: block; }
@media (max-width: 767px) {
  .trust-bar-carousel--arrows .carousel-controls { display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px; grid-template-areas: "prev dots next" ". pause ."; align-items: center; gap: 10px 6px; }
  .trust-bar-carousel--arrows .carousel-prev { grid-area: prev; }
  .trust-bar-carousel--arrows .carousel-next { grid-area: next; }
  .trust-bar-carousel--arrows .carousel-dots { grid-area: dots; }
  .trust-bar-carousel--arrows .carousel-pause { grid-area: pause; justify-self: center; }
}
/* --- Review carousel Read more (shared_patterns.review_carousel.read_more) --- */
.review-card.is-clamped:not(.is-expanded) .review-text-rest { display: none; }
.review-card.is-clamped:not(.is-expanded) .review-text::after { content: "\2026"; }
html[data-a11y-text="scaled"] .review-card.is-clamped .review-text-rest { display: inline; }
html[data-a11y-text="scaled"] .review-card.is-clamped .review-text::after { content: none; }
html[data-a11y-text="scaled"] .review-more { display: none; }
.review-card .review-more {
  justify-self: start; background: none; border: 0; padding: 10px 0; min-height: 44px; cursor: pointer;
  color: var(--color-primary); font-family: var(--font-body); font-weight: 700; font-size: calc(14px * var(--fs, 1)); line-height: 1.2;
  text-decoration: underline; text-underline-offset: 3px;
}

/* --- Client-scoped variant toupin_2026_10_16 --- */

/* Client-scoped variant toupin_2026_10_16 (classification: client_scoped_variant; client: Toupin
   Hauling & Junk Removal; default: false; reusable: false; catalogue: none). Authorized by Kevin,
   2026-10-16 (governance/decisions/2026-10-16_toupin_client_variant.md).

   The approved Toupin mockups' stylesheet (02 - Build Inputs/Mockups: homepage-proposed,
   furniture-removal, nashua-town-page; one shared stylesheet), ported in its normal-mode values with
   the system's mechanical integrations so the accessibility layer reaches it:
     - every selector is .th- scoped, or names a system element (.site-header, .mobile-chrome,
       .mobile-action-bar) the variant styles for Toupin;
     - every font size is calc(<approved value> * var(--fs, 1)); every font shorthand is written as
       longhands;
     - the approved colours are --th-* properties (teal #017D7D, green #68B239, aqua #EFFFFF) that
       the brand tokens also carry;
     - the mockup annotation tags (.pn, .cn) and the mockup controls are not part of the site.
   Departures from the mockups, each marked AUTHORIZED or ACCESSIBILITY CORRECTION with its basis.

   Closeout re-base (2026-10-16): the reusable patterns render through the system's shared code (the header's
   and footer's options, the review carousel's options, generator/shared_patterns.py); this layer sets their
   tokens below and keeps only Toupin's own sections and treatment. The overrides that remain are marked
   OVERRIDE with the reason (preparation/variant-audit-2026-10-16.md in the Toupin repository). */

/* Size-matched fallback faces (layout stability): until Tilt Warp and Bricolage Grotesque arrive, local Arial
   Black and Arial are scaled to their widths (measured in Chromium: Tilt Warp 80.7% of Arial Black; Bricolage,
   at the 14 to 20px text sizes its optical axis widens, about 105% of Arial regular and 101.5% of Arial bold), so
   text keeps its line breaks when the web fonts swap in. */
@font-face { font-family: "Tilt Warp Fallback"; src: local("Arial Black"), local("Arial-Black"); size-adjust: 80.7%; }
@font-face { font-family: "Bricolage Fallback"; font-weight: 100 549; src: local("Arial"), local("ArialMT"), local("Helvetica"), local("Liberation Sans"); size-adjust: 104.6%; }
@font-face { font-family: "Bricolage Fallback"; font-weight: 550 900; src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Bold"), local("Liberation Sans Bold"); size-adjust: 101.5%; }
:root {
  --th-teal: #017D7D;
  --th-teal-dk: #016464;
  --th-teal-deep: #043F3F;
  --th-green: #68B239;
  --th-green-light: #A8ED7C;  /* the light brand green on James's colour sheet (the footer's phone headings) */
  --th-aqua: #EFFFFF;
  --th-white: #FFFFFF;
  --th-ink: #000000;
  /* Body text: the live site's black at 18px/32px, weight 400 (Kevin's review: never lighter or narrower). */
  --th-body: #000000;
  --th-mute: #4E5B5B;
  --th-line: #D3E6E6;
  --th-soft: #F1F1F1;
  --th-x: #B3261E;
  --th-star: #F5B301;
  --th-shadow: 0 0 16px rgba(17, 17, 26, .10);
  /* The system font tokens (from the input's fonts), so the widget's readable-font mode reaches every rule. */
  --th-display: var(--font-heading);
  --th-text: var(--font-body);
  /* SCALE (Kevin's review 2026-10-16, stage B): the system reference build's content container, 1140px with
     20px padding; the header and hero copy sit on the system's fluid gutter (cross_cutting.FLUID_GUTTER),
     capped at 1920px. */
  --th-wrap: 1140px;
  --th-gutter: max(20px, min(clamp(24px, 4.5vw, 104px), calc((100vw - 1000px) / 2)));
  --th-fluid-max: 1920px;
  /* The fixed bottom bar's height (system action bar: 68px + 3px edge) plus the device inset. */
  --th-bar: calc(71px + env(safe-area-inset-bottom, 0px));
  /* Toupin's values for the shared patterns and options (generator/shared_patterns.py, header, trust_bar). */
  --hero-trust-scrim: rgba(4, 63, 63, .78);  /* the deep teal at .78 (photo-contrast check) */
  --hero-trust-star: #FFC83D;                /* the lighter gold that holds 4.5:1 over the photos */
  --hero-pf-rgb: 4, 63, 63;                  /* the hero's darkest teal, behind the photo-first copy */
  --promo-aspect: 291 / 151;                 /* the military badge artwork */
  --ba-fill: var(--th-soft);
  --ba-tag-color: var(--th-ink);
  --partner-border: var(--th-line);
  --partner-shadow: var(--th-shadow);
  --partner-text: var(--th-body);
  --faq-answer-bg: var(--th-aqua);
  --area-card-border: var(--th-line);
  --area-card-color: var(--th-ink);
  --area-card-hover: var(--th-aqua);
  --mobile-submenu-color: var(--th-ink);
  --mobile-see-all-rule: var(--th-line);
  --carousel-control-color: var(--th-teal);
  --carousel-arrow-hover: var(--th-aqua);
}

/* --- Base ------------------------------------------------------------------------------------- */
html { scroll-behavior: smooth; }
/* The header is pinned (Kevin's review, item a): anchors and keyboard focus clear its scrolled height (100px
   desktop, 76px mobile chrome) with a margin; below the desktop row they also clear the bottom bar. */
html { scroll-padding-top: 116px; }
@media (max-width: 1023px) { html { scroll-padding-top: 92px; } }
@media (max-width: 1023px) { html { scroll-padding-bottom: calc(var(--th-bar) + 12px); } }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
html[data-a11y-motion="reduce"] { scroll-behavior: auto; }
body {
  margin: 0;
  background: var(--th-white);
  color: var(--th-body);
  font-family: var(--th-text);
  font-weight: 400;
  font-size: calc(18px * var(--fs, 1));
  line-height: 1.78;
}
.th-page img, .th-footer img { max-width: 100%; height: auto; display: block; }
.th-page a { color: var(--th-teal); }
.th-page h1, .th-page h2, .th-page h3, .th-footer h3, .th-page .th-h3 {
  font-family: var(--th-display);
  font-weight: 400;
  color: var(--th-ink);
  margin: 0;
  text-wrap: balance;
  letter-spacing: 0;
}
/* SCALE: AV production's H2 (32px/40px) and H3 (18px/24px) in Tilt Warp; the homepage takes the live site's
   50px/62px H2 (authorized exception: the live homepage is its proportion reference). */
.th-page h2 { font-size: calc(clamp(26px, 2.6vw, 32px) * var(--fs, 1)); line-height: 1.25; text-transform: uppercase; }
.th-tpl-home h2 { font-size: calc(clamp(32px, 3.6vw, 50px) * var(--fs, 1)); line-height: 1.24; }
.th-page h3 { font-size: calc(18px * var(--fs, 1)); line-height: 1.33; }
.th-page p { margin: 0; }
/* A zero-specificity list reset, so each list's own margins apply. */
:where(.th-page, .th-footer) :where(ul, ol) { margin: 0; padding: 0; list-style: none; }
/* ACCESSIBILITY CORRECTION (non-text contrast 1.4.11): the mockup's green ring is 2.6:1 on white;
   the deep teal ring is 11.6:1 on white and aqua, white is used on teal surfaces. In the widget's high
   contrast mode the system ring (white with a black halo) applies unchanged. */
html:not([data-a11y-contrast="high"]) .th-page :focus-visible, html:not([data-a11y-contrast="high"]) .th-footer :focus-visible, html:not([data-a11y-contrast="high"]) .th-header :focus-visible {
  outline: 3px solid var(--th-teal-deep);
  outline-offset: 3px;
}
html:not([data-a11y-contrast="high"]) .th-hero :focus-visible, html:not([data-a11y-contrast="high"]) .th-footer :focus-visible, html:not([data-a11y-contrast="high"]) .th-header :focus-visible,
html:not([data-a11y-contrast="high"]) .th-ctaband :focus-visible, html:not([data-a11y-contrast="high"]) .th-skipband :focus-visible,
html:not([data-a11y-contrast="high"]) .th-header .mobile-chrome .menu-box:focus-visible { outline-color: var(--th-white); }
/* Run 8, item 4c (rings measured): the skip link appears over the header, the logo and the photo, and the
   accessibility launcher over white and teal surfaces alike, where one ring colour is about 1:1 somewhere; each
   rings deep teal on a white halo, so the ring itself always reads 11.6:1 against what is beside it. The widget's
   own files are unchanged. */
html:not([data-a11y-contrast="high"]) .skip-link:focus-visible { outline: 3px solid var(--th-teal-deep); outline-offset: 3px; box-shadow: 0 0 0 9px var(--th-white); }
html:not([data-a11y-contrast="high"]) .a11y-toggle:focus-visible { outline: 3px solid var(--th-teal-deep); outline-offset: 3px; box-shadow: 0 0 0 9px var(--th-white); }
/* Run 8, item 4d: a third-party frame holding keyboard focus is ringed by this page (the page script's
   th-frame-focus), in the page's own ring; the frame's content cannot be styled from here. */
html:not([data-a11y-contrast="high"]) iframe.th-frame-focus { outline: 3px solid var(--th-teal-deep); outline-offset: 3px; }
html[data-a11y-contrast="high"] iframe.th-frame-focus { outline: 3px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 6px #000; }
/* The bottom bar is white here, so its controls ring in deep teal (the system's white ring is for a dark bar). */
html:not([data-a11y-contrast="high"]) .mobile-action-bar a:focus-visible { outline-color: var(--th-teal-deep); }
.th-sr {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip-link:focus { z-index: 300; }

/* Page frame: the live site insets its hero, bands and footer by 10px with rounded corners. */
.th-frame {
  padding-left: max(10px, env(safe-area-inset-left, 0px));
  padding-right: max(10px, env(safe-area-inset-right, 0px));
}
.th-wrap {
  max-width: var(--th-wrap);
  margin: 0 auto;
  padding-left: max(20px, env(safe-area-inset-left, 0px));
  padding-right: max(20px, env(safe-area-inset-right, 0px));
}
/* The system's fluid container (header, hero copy): the gutter on each side, capped at 1920px. */
.th-fluid {
  max-width: var(--th-fluid-max);
  margin: 0 auto;
  padding-left: max(var(--th-gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--th-gutter), env(safe-area-inset-right, 0px));
}
.th-wrap.th-narrow { max-width: 820px; }
.th-sec { padding-block: 76px; }  /* SCALE: AV production's section padding */
.th-band { background: var(--th-aqua); border-radius: 20px; }
.th-head { display: grid; gap: 10px; text-align: center; justify-items: center; margin-bottom: 36px; }
.th-head p { max-width: 60ch; color: var(--th-mute); }
.th-mt { margin-top: 12px; }
.th-center { display: flex; justify-content: center; margin-top: 22px; }
.th-stack { display: grid; gap: 16px; align-content: start; }
.th-stack > * { min-width: 0; }
.th-fine { font-size: calc(18px * var(--fs, 1)); line-height: 1.78; color: var(--th-body); }
.th-fine b { color: var(--th-ink); }
.th-frame + .th-frame, .th-frame + .th-sec, .th-sec + .th-frame { margin-top: 0; }
.th-page > .th-frame:not(.th-frame-hero) { margin-block: 28px; }

/* --- Buttons (live site) ----------------------------------------------------------------------- */
.th-btns { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.th-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  /* SCALE: AV production's button (16px bold, 16px by 20px padding, about 61px tall). */
  min-height: 44px; padding: 16px 22px; border-radius: 5px;
  font-family: var(--th-text); font-weight: 700; font-size: calc(16px * var(--fs, 1)); line-height: 1.7;
  text-transform: uppercase; letter-spacing: .02em; text-decoration: none; text-align: center;
  border: 1px solid var(--th-teal); cursor: pointer; transition: background .15s, color .15s;
}
.th-btn svg { width: 18px; height: 18px; flex: none; }
.th-page .th-btn-fill { background: var(--th-teal); color: var(--th-white); }
.th-page .th-btn-fill:hover { background: var(--th-teal-dk); }
.th-page .th-btn-line { background: var(--th-white); color: var(--th-teal); }
.th-page .th-btn-line:hover { background: var(--th-aqua); }
.th-page .th-btn-white { background: var(--th-white); color: var(--th-teal); border-color: var(--th-white); }
.th-page .th-btn-white:hover { background: var(--th-aqua); }
.th-page .th-btn-on-dark { border-color: rgba(255, 255, 255, .6); }
.th-txtlink { color: var(--th-white) !important; font-weight: 700; text-underline-offset: 3px; display: inline-flex; align-items: center; min-height: 44px; }
.th-more {
  display: inline-flex; align-items: center; gap: 6px; font-weight: 700; font-size: calc(13px * var(--fs, 1));
  line-height: 1; text-transform: uppercase; color: var(--th-teal); margin-top: 6px; min-height: 24px;
  overflow-wrap: anywhere;  /* run 8, item 2b: a word wider than a narrow card (text at 200%) wraps, never overflows */
}
.th-more svg { width: 14px; height: 14px; }
/* SCALE: the system's 40px card icon. */
.th-ic {
  width: 40px; height: 40px; border-radius: 50%; background: var(--th-teal); color: var(--th-white);
  display: grid; place-items: center; flex: none;
}
.th-ic svg { width: 20px; height: 20px; display: block; }
.th-stars { color: var(--th-star); letter-spacing: 1px; font-size: calc(15px * var(--fs, 1)); line-height: 1; }
.th-stars-row { display: inline-flex; align-items: center; gap: 8px; }
.th-rating { font-weight: 700; font-size: calc(14px * var(--fs, 1)); line-height: 1; color: var(--th-ink); }

/* --- Header: pinned (Kevin's review, item a) ---------------------------------------------------------- */
/* The system's pinned header: fixed to the top on desktop and phones, transparent over the hero at the top of
   the page and solid teal once scrolled (the page script sets .th-js and .is-scrolled; without it the header is
   solid throughout). Sizes are the live site's: logo 151x123, nav 16px bold, call button 200x50 (authorized
   exception, the live homepage's header). It stays outside <main>, before it in the markup. */
.site-header.th-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background: var(--th-teal); color: var(--th-white);
  /* The colour switches at once (a fade would leave the nav briefly below 4.5:1 over the page); the shadow eases. */
  transition: box-shadow .2s ease;
}
.th-js .site-header.th-header:not(.is-scrolled) { background: transparent; }
.site-header.th-header.is-scrolled { box-shadow: 0 2px 16px rgba(0, 0, 0, .18); }
.th-hdr {
  max-width: var(--th-fluid-max); margin: 0 auto; min-height: 0;
  padding: 20px max(var(--th-gutter), env(safe-area-inset-right, 0px)) 20px max(var(--th-gutter), env(safe-area-inset-left, 0px));
  justify-content: space-between; gap: 16px; transition: padding .2s ease;
}
.th-logo { display: inline-flex; min-height: 44px; align-items: center; }
.site-header .th-logo img { width: 151px; height: auto; max-height: none; transition: width .2s ease; }
/* Scrolled: the system's 100px bar. */
.site-header.th-header.is-scrolled .th-hdr { padding-block: 10px; }
.site-header.th-header.is-scrolled .th-logo img { width: 98px; }
.th-nav ul, .th-header ul { margin: 0; padding: 0; list-style: none; }
.th-nav > ul { display: flex; align-items: center; gap: 14px; }  /* a focus ring (6px out) never touches a neighbour */
.th-nav li { position: relative; }
.th-top {
  display: inline-flex; align-items: center; gap: 4px; min-height: 44px;
  color: var(--th-white); text-decoration: none; background: none; border: 0; cursor: pointer;
  font-family: var(--th-text); font-weight: 700; font-size: calc(16px * var(--fs, 1)); line-height: 1.25;
  text-transform: uppercase; letter-spacing: 0; padding: 13px 20px; border-radius: 5px; min-height: 46px;
}
.th-header .th-top { color: var(--th-white); }
.th-chev { width: 14px; height: 14px; transition: transform .15s; }
.th-dd-btn[aria-expanded="true"] .th-chev { transform: rotate(180deg); }
/* Kevin's second review, item l: "Services" and "Service Areas" link to their pages; the arrow button beside each
   opens its list (aria-expanded; Escape closes; hover still opens it). */
.th-dd { display: flex; align-items: center; }
.th-header .th-top-link { padding-right: 6px; border-radius: 5px 0 0 5px; }
.th-header .th-dd-btn { padding: 13px 12px 13px 8px; min-width: 40px; justify-content: center; border-radius: 0 5px 5px 0; }
/* Hover and open: a deep teal tint (white on it stays above 4.5:1; a white tint fell to 3.9:1 on teal). */
.th-top:hover, .th-dd:hover > .th-top, .th-dd-btn[aria-expanded="true"], .th-dd-btn[aria-expanded="true"] ~ .th-top { background: rgba(4, 63, 63, .55); }
.th-current > .th-top, .th-header .th-current > .th-top { background: var(--th-white); color: var(--th-teal); }
/* The current section's label link and arrow button make one white pill, so a white ring outside either half would
   vanish against the other: their ring is the deep teal one, drawn just inside the pill (11.6:1 on white). */
html:not([data-a11y-contrast="high"]) .th-header .th-current > .th-top:focus-visible { outline-color: var(--th-teal-deep); outline-offset: -4px; }
.th-drop {
  position: absolute; top: calc(100% + 8px); left: 0; min-width: 250px; background: var(--th-white); border-radius: 10px;
  box-shadow: var(--th-shadow); padding: 8px; display: none; z-index: 120;
}
/* 8px below its button, so the button's focus ring (6px out) shows clear of the panel; the bridge keeps
   the hover open while the pointer crosses the gap. */
.th-drop::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }
.th-dd:hover > .th-drop, .th-dd-btn[aria-expanded="true"] + .th-drop { display: grid; }
.th-drop a {
  display: block; padding: 10px 12px; border-radius: 6px; color: var(--th-ink); text-decoration: none;
  font-weight: 500; font-size: calc(15px * var(--fs, 1)); line-height: 1.35;
}
.th-drop a:hover { background: var(--th-aqua); color: var(--th-teal); }
.th-drop a[aria-current] { color: var(--th-teal); font-weight: 700; }
.th-drop .th-drop-all { border-top: 1px solid var(--th-line); margin-top: 4px; padding-top: 4px; }
.th-drop .th-drop-all a { color: var(--th-teal); font-weight: 700; }
html:not([data-a11y-contrast="high"]) .th-header .th-drop :focus-visible { outline-color: var(--th-teal-deep); }
/* The system pulse call, adapted to Toupin: the live site's teal call button with the pulse circle. */
.th-call { display: flex; align-items: center; }
.th-header .header-call {
  color: var(--th-white); background: var(--th-teal); border: 1px solid rgba(255, 255, 255, .45);
  border-radius: 5px; padding: 8px 16px 8px 8px; min-height: 50px; min-width: 200px; justify-content: center;
}
.th-header .header-call-icon { width: 32px; height: 32px; flex: 0 0 32px; background: var(--th-green); color: var(--th-teal-deep); }
.th-header .header-call-icon::before, .th-header .header-call-icon::after { border-color: var(--th-green); }
.th-header .header-call-icon .icon, .th-header .header-call-icon svg { width: 17px; height: 17px; }
.th-header .header-call .phone-number { font-family: var(--th-text); font-weight: 700; font-size: calc(16px * var(--fs, 1)); letter-spacing: 0; }
@media (min-width: 1024px) and (max-width: 1240px) {
  .th-top { padding-inline: 10px; }
  .site-header .th-logo img { width: 120px; }
  .th-header .header-call { min-width: 0; }
}
/* The nav sits on the hero photo's top band (the live site's gradient, below); the dark shade the last revision
   put behind it is gone (Kevin's review, item f). */
@media (min-width: 1024px) {
  /* clip: nothing in the header widens the page under enlarged text; the dropdowns open downward, unclipped. */
  .site-header.th-header { overflow-x: clip; }
  /* The call button can sit over the photo: its ring is white inside a deep teal halo, so it shows at 3:1 or
     more against any photo. */
  html:not([data-a11y-contrast="high"]) .th-header .header-call:focus-visible { box-shadow: 0 0 0 9px var(--th-teal-deep); }
}

/* System mobile chrome (logo + MENU) on the hero card, below the desktop row. */
.th-header .mobile-chrome {
  background: transparent; min-height: 76px; max-width: none; position: static;
  padding: 10px max(14px, env(safe-area-inset-right, 0px)) 10px max(14px, env(safe-area-inset-left, 0px));
  justify-content: space-between;
}
.th-header .mobile-chrome .logo-mobile img { max-height: 56px; width: auto; }
/* The MENU box carries its own deep teal fill: white on it stays above 4.5:1 over any hero photo. */
.th-header .mobile-chrome .menu-box {
  color: var(--th-white); background: rgba(4, 63, 63, .78); border: 1px solid rgba(255, 255, 255, .7); border-radius: 5px;
}
body.menu-open .th-header, .th-js body.menu-open .site-header.th-header:not(.is-scrolled) { position: fixed; top: 0; left: 0; right: 0; background: var(--th-teal); border-radius: 0; }
body.menu-open .th-header .mobile-chrome { padding-top: 20px; }
.mobile-menu-overlay { background: var(--th-white); }
.mobile-menu-overlay .mobile-menu-label { font-family: var(--th-text); font-weight: 700; text-transform: uppercase; }
/* The phone menu's Accessibility row (layout.mobile_menu_accessibility: row) and its See all links
   (layout.mobile_see_all: emphasised; Kevin's second review, item m) are the system menu's options. */
.mobile-menu-overlay .btn-primary { background: var(--th-teal); border-color: var(--th-teal); color: var(--th-white); }
.mobile-menu-overlay .btn-secondary { background: var(--th-white); border-color: var(--th-teal); color: var(--th-teal); }

/* System bottom action bar, Toupin colours: Call Us (outline) and the quote (teal). The bar hides while
   the menu is open (system rule, body.menu-open) and steps aside while a typing field has focus. */
.mobile-action-bar { border-top-color: var(--th-teal); background: var(--th-white); box-shadow: 0 -2px 12px rgba(0, 0, 0, .12); }
.mobile-action-bar .mab-call { color: var(--th-teal); font-family: var(--th-text); font-weight: 700; }
.mobile-action-bar .mab-call-circle { background: var(--th-teal); color: var(--th-white); border-color: var(--th-teal); }
.mobile-action-bar .mab-call-circle::before, .mobile-action-bar .mab-call-circle::after { border-color: var(--th-teal); }
.mobile-action-bar .mab-quote {
  background: var(--th-teal); color: var(--th-white); border-color: var(--th-teal);
  font-family: var(--th-text); font-weight: 700; text-transform: uppercase; letter-spacing: .02em; border-radius: 5px;
}
body.menu-open .mobile-action-bar { display: none; }

/* --- Hero ---------------------------------------------------------------------------------------- */
/* The hero is the one section that runs the full width of the screen, on every page (Kevin's review). */
.th-frame.th-frame-hero { padding: 0; }
.th-hero {
  position: relative; border-radius: 0; overflow: hidden; background: var(--th-teal-dk); color: var(--th-white);
  isolation: isolate;
}
.th-hero-pic, .th-hero-img { position: absolute; inset: 0; width: 100%; height: 100%; }
/* The photo takes no clicks: positioned with no z-index, its box sits above the hero's button row (2026-10-19). */
.th-hero-pic { pointer-events: none; }
.th-page .th-hero-img { height: 100%; object-fit: cover; object-position: var(--th-pos, 60% 45%); z-index: -2; }
/* OVERLAY (Kevin's review, item f): the live homepage's gradient, measured from its banner against the plain
   photo: teal from 80% at the left edge to nothing at 75% of the width, and a top band that carries the header.
   The photo shows through and the overlay is gone before the subject. CONTRAST GATE: white on the brand teal
   tops out at 4.9:1 even opaque, so over a light photo the darkening that holds 4.5:1 is deep teal: the top band
   behind the nav is deep teal fading out under the header, and a soft deep-teal scrim confined to the text block
   (blurred edges, --th-scrim per page, the lightest that passes on that photo) holds the copy. Measured against
   the photo pixels behind every line and ring (tools/checks/photo_contrast.py); never a solid fill. */
.th-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(4, 63, 63, var(--th-band, .66)) 0, rgba(4, 63, 63, var(--th-band, .66)) 118px, rgba(4, 63, 63, 0) 250px),
    linear-gradient(90deg, rgba(1, 125, 125, .8) 0, rgba(1, 125, 125, 0) 75%);
}
.th-hero-copy { position: relative; isolation: isolate; display: grid; gap: 18px; }
.th-hero:not(.th-hero-text) .th-hero-copy::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none; inset: -30px -44px -30px -40px;
  border-radius: 48px; background: rgba(4, 63, 63, var(--th-scrim, .6)); filter: blur(24px);
}
.th-hero-text { background: var(--th-teal); }
.th-hero-text::before { background: linear-gradient(90deg, var(--th-teal) 0%, var(--th-teal-dk) 100%); }
/* The badge places against the hero itself (its corner on tablets and desktops). */
.th-hero-in { position: static; }
/* SCALE: AV production's page hero (H1 46px, 560 to 600px copy); the copy starts below the pinned header. */
.th-hero-body { display: grid; gap: 18px; max-width: 600px; padding-top: max(214px, calc(var(--th-header-h, 0px) + 24px)); padding-bottom: 84px; }
/* Run 8: the pinned header grows when its links wrap (1024px with text at 175%: 251px); the hero's content starts
   24px below it then, so the breadcrumb is never under the header. At default sizes the padding is as before. */
.th-hero-text .th-hero-body { max-width: 760px; padding-bottom: 64px; }
.th-hero h1 { color: var(--th-white); font-size: calc(clamp(34px, 4vw, 46px) * var(--fs, 1)); line-height: 1.08; text-transform: uppercase; }
.th-lede { color: var(--th-white); font-size: calc(18px * var(--fs, 1)); line-height: 1.67; max-width: 56ch; }
.th-hero .th-btns { margin-top: 4px; }
/* The military discount badge (Kevin's badge fix, item a) is the shared promotional badge (shared_patterns
   .promo_badge): from 768px the 150px edge tab in the hero's bottom right corner; the artwork is Toupin's. */
.th-mil-text { font-family: var(--th-text); font-weight: 700; }
/* From 768 to 1199px the hero photo can take its own crop (hero.tablet_position) so its subject stays clear of the
   badge's edge tab; elsewhere it is the page's position. */
@media (min-width: 768px) and (max-width: 1199px) {
  .th-page .th-hero-img { object-position: var(--th-pos-t, var(--th-pos, 60% 45%)); }
}
/* Homepage hero (Kevin's review, item g): the live site's proportions: 820px tall, an 870px copy column, the H1
   at 60px/72px (three lines at 1920px), the intro at 20px/36px and 200x50 buttons. */
.th-hero-home { min-height: 820px; }
.th-hero-home .th-hero-body { max-width: 870px; padding-top: max(249px, calc(var(--th-header-h, 0px) + 24px)); padding-bottom: 120px; gap: 20px; }
.th-hero-home .th-hero-copy { gap: 20px; }
.th-hero-home h1 { font-size: calc(clamp(34px, 4.2vw, 60px) * var(--fs, 1)); line-height: 1.2; }
.th-hero-home .th-lede { font-size: calc(20px * var(--fs, 1)); line-height: 1.8; max-width: none; }
.th-hero-home .th-btns { gap: 20px; margin-top: 10px; }
.th-hero-home .th-btn { min-width: 200px; min-height: 50px; padding: 16px 20px; line-height: 1; }
/* Item o4: the hero trust line is the shared one (shared_patterns.hero_trust_line), with its own deep-teal scrim at
   .78 and the lighter gold (the tokens above): 4.5:1 for the stars and the text over every hero photo it is on
   (photo-contrast check; the page's text scrim alone left the stars at 3.4 to 4.4:1). */
.th-crumbs ol { display: flex; flex-wrap: wrap; gap: 6px; font-size: calc(14px * var(--fs, 1)); line-height: 1.4; color: var(--th-white); }
.th-crumbs li { display: inline-flex; align-items: center; gap: 6px; }
.th-crumbs li + li::before { content: "/"; color: var(--th-white); }
.th-crumbs a { color: var(--th-white); display: inline-flex; align-items: center; min-height: 24px; }
.th-crumbs span[aria-current] { color: var(--th-white); font-weight: 600; }

/* --- Award and trust strip ---------------------------------------------------------------------- */
.th-award { display: flex; justify-content: center; padding-top: 28px; }
/* Kevin's review, item h: the Top 3 Nominee badge at the live site's 800x284. */
.th-award-img { width: min(600px, 100%); }
.th-trust { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 3fr); gap: 24px; align-items: center; padding-block: 36px 8px; }
.th-trust-award { width: 100%; max-width: 340px; }
.th-trust-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.th-tr { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 12px; align-items: center; overflow-wrap: anywhere; font-weight: 600; font-size: calc(16px * var(--fs, 1)); line-height: 1.35; color: var(--th-ink); }
.th-tr .th-stars-row { display: flex; margin-top: 4px; }

/* --- Reviews (pull quote plus cards; Review Rules REV-LAY-002) ----------------------------------- */
.th-reviews { padding-block: 64px; }
.th-pq { margin: 0 auto 28px; max-width: 820px; text-align: center; display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; justify-items: center; }
/* Run 8, item 2a: the quote's column never grows past the screen; a word wider than it (320px, text at 200%)
   wraps. At default sizes the column and the words are as before. */
.th-pq blockquote { margin: 0; max-width: 100%; overflow-wrap: break-word; }
.th-pq blockquote p { font-size: calc(clamp(19px, 2.1vw, 23px) * var(--fs, 1)); line-height: 1.55; color: var(--th-ink); }
.th-pq strong { color: var(--th-teal-dk); font-weight: 700; }
.th-pq figcaption { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px 14px; font-size: calc(15px * var(--fs, 1)); line-height: 1.4; color: var(--th-mute); }
.th-pq-by { font-weight: 700; color: var(--th-ink); }
.th-pq-ctx::before { content: "\00B7"; margin-right: 10px; }
.th-revs { --cols: 3; --gap: 18px; }
.th-revs-2 { --cols: 2; max-width: 760px; margin: 0 auto; }
figure.th-rv {
  margin: 0; background: var(--th-white); border-radius: 10px; box-shadow: var(--th-shadow); padding: 26px 24px;
  display: grid; gap: 10px; align-content: start; font-size: calc(15px * var(--fs, 1)); line-height: 1.55;
}
.th-rv-top { display: grid; grid-template-columns: 38px minmax(0, 1fr) 20px; gap: 10px; align-items: center; }
.th-rv-top figcaption { display: grid; }
.th-av { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; color: var(--th-white); background: var(--th-teal); font-weight: 700; font-size: calc(15px * var(--fs, 1)); line-height: 1; }
.th-rv-n { font-weight: 700; font-size: calc(15px * var(--fs, 1)); line-height: 1.2; color: var(--th-ink); }
.th-rv-s { font-size: calc(13px * var(--fs, 1)); color: var(--th-mute); line-height: 1.2; }
.th-rv-g svg { width: 18px; height: 18px; color: #4285F4; display: block; }
.th-rv-ctx { font-weight: 700; font-size: calc(13px * var(--fs, 1)); line-height: 1.3; color: var(--th-teal-dk); text-transform: uppercase; letter-spacing: .04em; }
.th-rv-q { margin: 0; }
.th-rv-q p { margin: 0; }
/* Read more on long review cards, its ellipsis and the enlarged-text behaviour are the carousel's shared option
   (shared_patterns.review_carousel.read_more). */
html:not([data-a11y-text="scaled"]) a[href^="tel:"]:not(.btn) { white-space: nowrap; }
/* Phone and email links reach 44px tall (the BCS target rule): list links grow their box (the contact lists
   below); a link inside a sentence grows its hit area with vertical padding, which leaves the line spacing unchanged. */
.th-page :is(p, li) > a:is([href^="tel:"], [href^="mailto:"], [href^="https://maps."]),
.th-page .th-contact-list a, .th-page .th-ticks a, .th-page .th-room h3 a { padding-block: 13px; }
.th-revs-foot { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 24px; font-size: calc(15px * var(--fs, 1)); color: var(--th-mute); text-align: center; flex-wrap: wrap; }
.th-revs-foot a { font-weight: 700; display: inline-flex; align-items: center; min-height: 44px; }

/* The homepage's review carousel is the system's (trust_bar, Part 23 Pattern A); Toupin's card treatment on it:
   white cards with the soft shadow, equal heights (the track's cards stretch), the review text at 16px. */
.th-reviews .trust-bar-carousel { margin-top: 8px; }
/* Vertical room for the card shadows only: side padding would offset the system script's one-card step. */
.th-reviews .carousel-track { padding: 12px 0 18px; margin: -12px 0 0; align-items: stretch; }
.th-reviews .review-card {
  background: var(--th-white); border-radius: 10px; box-shadow: var(--th-shadow); padding: 26px 0; gap: 12px;
}
.th-reviews .review-card > * { padding-inline: 24px; }
.th-reviews .review-card > .review-rating { margin-inline: 24px; padding-inline: 0; }
.th-reviews .review-stars { color: var(--th-star); }
.th-reviews .review-text { font-family: var(--th-text); font-size: calc(16px * var(--fs, 1)); line-height: 1.6; color: var(--th-body); }
.th-reviews .review-card cite { font-style: normal; font-weight: 700; font-size: calc(15px * var(--fs, 1)); line-height: 1.4; color: var(--th-ink); }
.th-reviews .review-rating-value { font-family: var(--th-text); color: var(--th-ink); }
.th-reviews .carousel-pause { border-color: var(--th-teal); color: var(--th-teal); }
.th-reviews .carousel-pause:hover { background: var(--th-white); }
.th-reviews .carousel-dot::before { border-color: var(--th-teal); }
.th-reviews .carousel-dot[aria-current="true"]::before { background: var(--th-teal); }
/* The arrow buttons (Kevin's second review, item a) are the carousel's shared option, in the teal (tokens above);
   Read more lines up with the card's text. */
.th-reviews .review-card .review-more { padding-inline: 24px; margin: -4px 0 0; align-self: flex-start; text-align: left; }
/* Service and town pages: the pull quote directly below the trust strip (Kevin's review, item m). */
.th-pq-wrap { padding-top: 36px; }
.th-pq-wrap .th-pq { margin-bottom: 0; }

/* --- Three-step process -------------------------------------------------------------------------- */
.th-steps-band { position: relative; isolation: isolate; padding-block: 56px 0; }
.th-steps-band::before { content: ""; position: absolute; inset: 0 0 34% 0; background: var(--th-aqua); border-radius: 20px; z-index: -1; }
.th-steps { --cols: 3; --gap: 20px; }
.th-step-art { display: block; }
.th-step { background: var(--th-white); border-radius: 10px; box-shadow: var(--th-shadow); padding: 26px 24px; display: grid; gap: 8px; justify-items: center; text-align: center; align-content: start; }
.th-page .th-step img { display: block; height: 150px; width: auto; object-fit: contain; margin-bottom: 10px; }
.th-step p { font-size: calc(16px * var(--fs, 1)); line-height: 1.63; }
.th-steps-cta { display: flex; justify-content: center; margin-top: 28px; }

/* --- Home: about band, services, why, haul ------------------------------------------------------- */
.th-about-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; align-items: start; }
.th-ph { position: relative; border-radius: 20px; overflow: hidden; background: var(--th-soft); }
.th-page .th-ph img { width: 100%; height: 100%; object-fit: cover; }
.th-about-photo { margin-top: 40px; aspect-ratio: 1200 / 521; }
.th-vals { --cols: 4; --gap: 20px; text-align: center; margin-top: 28px; }
.th-val { display: grid; gap: 10px; justify-items: center; align-content: start; }
.th-val p { font-size: calc(16px * var(--fs, 1)); line-height: 1.6; }
/* Kevin's review, item j: the four values sit below the photo with clear space, each with the live site's own
   70px icon; at 1440px and up every heading stays on one line (the columns take each heading's width). */
.th-vals-home { margin-top: 44px; }
.th-page .th-val-img { width: 70px; height: 70px; display: block; margin-bottom: 6px; }
.th-vals-home h3 { font-family: var(--th-text); font-weight: 700; font-size: calc(18px * var(--fs, 1)); line-height: 1.33; }
@media (min-width: 1440px) {
  html:not([data-a11y-text="scaled"]) .th-vals-home { display: grid; grid-template-columns: repeat(4, auto); justify-content: space-between; gap: 24px; }
  html:not([data-a11y-text="scaled"]) .th-vals-home > li { flex: none; width: auto; }
  html:not([data-a11y-text="scaled"]) .th-vals-home h3 { white-space: nowrap; }
}
.th-head-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: 16px; margin-bottom: 24px; }
.th-head-row h2 { max-width: 22ch; }
.th-intro-links { max-width: 72ch; margin: 0 0 32px; font-size: calc(17px * var(--fs, 1)); line-height: 1.76; }
.th-intro-links a { font-weight: 600; }
.th-svc-group { display: grid; gap: 14px; }
.th-svc-group + .th-svc-group { margin-top: 28px; }
.th-page .th-svc-lbl { font-family: var(--th-display); font-weight: 400; font-size: calc(18px * var(--fs, 1)); line-height: 1.2; text-transform: uppercase; color: var(--th-teal); }
/* Card grids (Kevin's review, item b): every card in a row is the same height, and a last row that does not
   fill is centred (flex rows of --cols columns; the cards stretch to the row). */
.th-svc-grid, .th-rel, .th-rooms, .th-steps, .th-cards3, .th-near, .th-gallery, .th-vals, .th-partners, .th-revs {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: var(--gap, 20px);
}
.th-svc-grid > li, .th-rel > li, .th-rooms > li, .th-steps > li, .th-cards3 > li, .th-near > li, .th-gallery > li,
.th-vals > li, .th-partners > li, .th-revs > * {
  flex: 0 0 calc((100% - (var(--cols, 3) - 1) * var(--gap, 20px)) / var(--cols, 3)); min-width: 0;
}
.th-svc-grid { --cols: 4; --gap: 20px; }
.th-rel { --cols: 4; --gap: 20px; }
.th-svc-grid > li, .th-rel > li { display: grid; }
.th-rcard { background: var(--th-white); border: 1px solid var(--th-teal); border-radius: 20px; overflow: hidden; display: grid; grid-template-rows: auto 1fr; text-decoration: none; color: inherit; }
.th-page .th-rcard { color: var(--th-body); }
.th-rcard .th-ph { border-radius: 0; aspect-ratio: 4 / 3; }
.th-in { padding: 26px 24px; display: grid; gap: 8px; align-content: start; }  /* SCALE: AV card padding */
.th-in p { font-size: calc(16px * var(--fs, 1)); line-height: 1.6; }
.th-rcard:hover h3 { color: var(--th-teal); }
.th-why-sec { padding-block: 8px; }
.th-why-box { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 36px; align-items: center; padding: 18px 36px 18px 18px; }
.th-why-ph { aspect-ratio: 4 / 3; }
/* Kevin's second review, item f: the before and after pair in the photo's slot is the shared pair
   (shared_patterns.before_after). */
/* Kevin's review, item k: the heading across the container (three lines or fewer at 1440px), the live site's
   list (18px/32px, 5px apart, 20px check icons) beside the collage at the live site's 620px. */
.th-haul-h2 { margin-bottom: 28px; max-width: 26ch; }
.th-haul { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 620px); gap: 40px; align-items: center; }
.th-haul > * { min-width: 0; }
.th-page .th-haul-img { width: 100%; max-width: 620px; justify-self: end; border-radius: 10px; }
.th-ticks { display: grid; gap: 8px; }
.th-ticks li {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 10px; font-size: calc(15.5px * var(--fs, 1)); line-height: 1.45; color: var(--th-body);
  overflow-wrap: anywhere;
}
.th-haul .th-ticks { gap: 0; }
.th-haul .th-ticks li { font-size: calc(18px * var(--fs, 1)); line-height: 1.78; padding-bottom: 5px; }
/* The live site's outlined check-circle list icon (toupinhauling.com, Kevin's review item e), 20px. */
.th-ticks li::before {
  content: ""; width: 20px; height: 20px; margin-top: calc((1lh - 20px) / 2);
  background: url("images/icon-check-circle.svg") center / 20px 20px no-repeat;
}
.th-ticks a { font-weight: 600; }

/* --- Partners ------------------------------------------------------------------------------------ */
/* Every partner section (review fixes, item 4): the band and the three matching cards are the shared partner
   cards (shared_patterns.partner_cards; names on their set lines from 768px, review fixes item 3). */
.th-partners-sec { padding-top: 8px; }
/* Final fixes, item 4: the homepage services intro and button exist in two places; one shows at each width. */
.th-page .th-phone-only { display: none; }

/* --- Service areas and map ------------------------------------------------------------------------ */
.th-areas { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 36px; align-items: center; padding-block: 40px; }
.th-areas > * { min-width: 0; }
.th-areas h2 { overflow-wrap: anywhere; }
/* The town cards, the See all card (Kevin's second review, item h) and the tiles for places served without a page
   (item l) are the shared area cards (shared_patterns.area_cards; two columns on phones). */
.th-also { font-size: calc(15px * var(--fs, 1)); line-height: 1.6; color: var(--th-mute); margin-top: 14px; }
.th-page .th-also-hub { text-align: center; margin-top: 22px; font-size: calc(17px * var(--fs, 1)); }
/* Kevin's review, item n: the schematic map sits square in its card (a square frame; the coverage circle stays
   inside it). */
.th-map { margin: 0; background: var(--th-white); border-radius: 20px; box-shadow: var(--th-shadow); padding: 12px; position: relative; aspect-ratio: 1 / 1; }
.th-map svg { width: 100%; height: 100%; display: block; }
/* James's Google Maps embed (item l): the live site's 450px height, lazy loaded and titled. */
.th-gmap { border-radius: 20px; overflow: hidden; box-shadow: var(--th-shadow); background: var(--th-white); line-height: 0; }
.th-gmap iframe { width: 100%; height: 450px; border: 0; display: block; }
.th-map-cap {
  position: absolute; left: 24px; bottom: 18px; font-weight: 700; font-size: calc(11px * var(--fs, 1)); line-height: 1.3;
  letter-spacing: .08em; text-transform: uppercase; color: var(--th-mute);
}
.th-local-area { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 40px; align-items: center; }
.th-local-area > * { min-width: 0; }

/* --- FAQ (live homepage accordion) ---------------------------------------------------------------- */
/* Kevin's review, item d, and review fixes, item 2: the live site's bars across the full content container, the
   answers sliding by their grid rows: the shared FAQ accordion (shared_patterns.faq_accordion; its defaults are
   these bars, the answer surface in the aqua token above). */
/* --- Closing band ---------------------------------------------------------------------------------- */
.th-final { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; align-items: center; padding-block: 44px; }
.th-final > * { min-width: 0; }
.th-contact-list { margin-top: 18px; display: grid; gap: 10px; }
.th-contact-list li { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 10px; align-items: center; font-size: calc(16px * var(--fs, 1)); line-height: 1.4; overflow-wrap: anywhere; }
.th-contact-list svg { width: 18px; height: 18px; color: var(--th-teal); }
.th-page .th-contact-list a { color: var(--th-ink); font-weight: 600; }
.th-towns { margin-top: 22px; display: grid; gap: 8px; }
/* Kevin's second review, item j: one line and the shared See all link (shared_patterns.see_all_link). */
.th-page .th-serving { margin-top: 18px; font-size: calc(17px * var(--fs, 1)); line-height: 1.6; color: var(--th-body); }
.th-page .th-lbl { font-family: var(--th-text); font-weight: 700; font-size: calc(13px * var(--fs, 1)); line-height: 1.2; text-transform: uppercase; letter-spacing: .06em; color: var(--th-mute); }
.th-towns ul { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 16px; }
.th-towns a { font-size: calc(16px * var(--fs, 1)); line-height: 1.6; color: var(--th-teal); font-weight: 600; display: inline-flex; align-items: center; min-height: 32px; }
@media (max-width: 1023px) { .th-towns a { min-height: 44px; } }
.th-estimate { background: var(--th-white); border-radius: 10px; box-shadow: var(--th-shadow); padding: 28px; display: grid; gap: 14px; }
.th-page .th-estimate h3 { font-size: calc(22px * var(--fs, 1)); text-transform: uppercase; }
.th-estimate p { font-size: calc(16px * var(--fs, 1)); line-height: 1.55; }
.th-estimate .th-alt { font-size: calc(15px * var(--fs, 1)); color: var(--th-mute); }

/* --- Service page: accepted items, can't take, enquiry -------------------------------------------- */
.th-rooms { --cols: 5; --gap: 16px; }
.th-rooms-4 { --cols: 4; }
.th-rooms-3 { --cols: 3; }
.th-rooms-2 { --cols: 2; }
.th-rooms-6 { --cols: 3; }
.th-rooms-7 { --cols: 4; }
.th-room { background: var(--th-white); border-radius: 10px; box-shadow: var(--th-shadow); padding: 26px 24px; display: grid; gap: 12px; align-content: start; border-top: 4px solid var(--th-teal); }
.th-page .th-room h3 { font-size: calc(17px * var(--fs, 1)); color: var(--th-teal); }
.th-page .th-room h3 a { color: var(--th-teal); }
.th-cant { margin-top: 18px; background: var(--th-aqua); border: 1px solid var(--th-line); border-radius: 10px; padding: 22px 24px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 24px; }
.th-cant p { font-size: calc(15px * var(--fs, 1)); line-height: 1.5; color: var(--th-mute); margin-top: 6px; }
.th-xlist { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 24px; }
.th-xlist li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 8px; font-size: calc(15px * var(--fs, 1)); line-height: 1.4; }
.th-xlist li::before { content: "\00D7"; color: var(--th-x); font-weight: 700; font-size: calc(18px * var(--fs, 1)); line-height: 1; margin-top: 1px; }
.th-ctaband { margin-top: 18px; background: var(--th-teal); color: var(--th-white); border-radius: 10px; padding: 22px 24px; display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: center; }
.th-page .th-ctaband h3 { color: var(--th-white); }
.th-ctaband p { font-size: calc(16px * var(--fs, 1)); line-height: 1.5; color: var(--th-white); }

/* --- Cost, local band, hassle, gallery, pair, related, nearby --------------------------------------- */
.th-cost-sec { padding-top: 56px; }
.th-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 48px; align-items: center; }
.th-ph-45 { aspect-ratio: 4 / 5; }
.th-ph-32 { aspect-ratio: 3 / 2; }
.th-ph-43 { aspect-ratio: 4 / 3; }
.th-factors { margin-top: 6px; display: grid; gap: 16px; }
.th-factors li { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 14px; align-items: start; }
.th-page .th-factors h3 { font-size: calc(17px * var(--fs, 1)); line-height: 1.3; margin-bottom: 2px; }
.th-factors p { font-size: calc(16px * var(--fs, 1)); line-height: 1.5; color: var(--th-body); }
.th-local { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 40px; align-items: center; padding-block: 40px; }
.th-local > * { min-width: 0; }
.th-cards3 { --cols: 3; --gap: 20px; }
.th-card { background: var(--th-white); border: 1px solid var(--th-teal); border-radius: 20px; padding: 26px 24px; display: grid; gap: 10px; align-content: start; }
.th-card p { font-size: calc(16px * var(--fs, 1)); line-height: 1.63; }
.th-skipband { margin-top: 20px; background: var(--th-teal); color: var(--th-white); border-radius: 10px; padding: 18px 24px; text-align: center; font-weight: 600; font-size: calc(17px * var(--fs, 1)); line-height: 1.45; }
.th-page p.th-skipband { color: var(--th-white); margin-top: 20px; }  /* the gap between stacked cards (item n) */
.th-gallery-sec { padding-top: 24px; }
.th-gallery { --cols: 4; --gap: 14px; }
.th-tile figure { position: relative; margin: 0; border-radius: 14px; overflow: hidden; aspect-ratio: 3 / 4; background: var(--th-soft); }
.th-page .th-tile img { width: 100%; height: 100%; object-fit: cover; }
.th-pair { margin: 0 auto; max-width: 900px; display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.th-pair-cell { position: relative; }
.th-pair-cell .th-ph { aspect-ratio: 4 / 3; }
.th-ptag { position: absolute; left: 12px; top: 12px; background: var(--th-white); color: var(--th-ink); border-radius: 999px; padding: 4px 12px; font-weight: 700; font-size: calc(13px * var(--fs, 1)); line-height: 1.3; text-transform: uppercase; letter-spacing: .04em; }
.th-ptag-after { background: var(--th-teal); color: var(--th-white); }
.th-pair figcaption { grid-column: 1 / -1; text-align: center; color: var(--th-mute); font-size: calc(15px * var(--fs, 1)); line-height: 1.5; }
.th-near { --cols: 2; --gap: 18px; max-width: 820px; margin: 0 auto; }
.th-near-hub { --cols: 4; max-width: none; }
.th-ncard { background: var(--th-white); border: 1px solid var(--th-line); border-top: 4px solid var(--th-teal); border-radius: 10px; padding: 26px 24px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; box-shadow: var(--th-shadow); align-content: start; overflow-wrap: break-word; }  /* run 8, item 2b: the card's column never grows past the screen */
.th-ncard .th-pin { width: 22px; height: 22px; color: var(--th-teal); }
.th-ncard p { font-size: calc(15px * var(--fs, 1)); line-height: 1.5; }
.th-ncard .th-more { min-height: 44px; }

/* --- About, contact, blog, legal, 404 --------------------------------------------------------------- */
.th-owner { padding-block: 40px; }
.th-owner-name { display: grid; font-weight: 700; color: var(--th-ink); font-size: calc(17px * var(--fs, 1)); line-height: 1.3; }
.th-owner-name span { font-weight: 600; font-size: calc(13px * var(--fs, 1)); text-transform: uppercase; letter-spacing: .06em; color: var(--th-teal-dk); }
.th-contact-sec { padding-top: 56px; }
.th-contact { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 40px; align-items: start; }
.th-contact > * { min-width: 0; }
.th-jobber-col { display: grid; gap: 14px; }
/* Jobber's embed stylesheet centres its container with margin: 0 auto and a 760px cap, which shrinks it to
   the iframe's 300px default inside this grid column; the container takes the column's full width. */
.th-page .th-jobber { width: 100%; max-width: 760px; margin: 0; min-height: 420px; background: var(--th-white); border-radius: 10px; }
.th-jobber iframe { max-width: 100%; }
/* While loading, Jobber's embed stylesheet turns the container into a full-screen absolute overlay
   (.jobber-spinner); here it stays in the page flow at its reserved height, so nothing around it jumps. */
html body .th-page .th-jobber.jobber-spinner { position: relative; top: auto; right: auto; bottom: auto; left: auto; width: 100%; height: auto; min-height: 420px; }
.th-contact-aside { background: var(--th-aqua); border-radius: 20px; padding: 28px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; overflow-wrap: anywhere; }
.th-page .th-h3 { font-size: calc(22px * var(--fs, 1)); line-height: 1.2; text-transform: uppercase; }
.th-a11y-note { border-top: 1px solid var(--th-line); padding-top: 14px; display: grid; gap: 6px; }
.th-a11y-note p { font-size: calc(15px * var(--fs, 1)); line-height: 1.55; }
.th-noscript { background: var(--th-aqua); padding: 16px; border-radius: 10px; }
.th-link-list { margin-top: 24px; display: grid; gap: 4px; }
.th-link-list .th-more { min-height: 44px; font-size: calc(14px * var(--fs, 1)); }
.th-legal { padding-top: 48px; }
/* The retained legal text quotes bare URLs; under enlarged text on a phone they wrap rather than widen the page. */
.th-page .th-legal { overflow-wrap: anywhere; }
.th-prose { display: grid; gap: 14px; }
.th-prose h2 { margin-top: 18px; }
.th-page .th-prose h2 { font-size: calc(26px * var(--fs, 1)); }
.th-page .th-prose h3 { font-size: calc(20px * var(--fs, 1)); margin-top: 8px; }
.th-page .th-prose h4 { font-family: var(--th-display); font-weight: 400; font-size: calc(17px * var(--fs, 1)); margin: 6px 0 0; color: var(--th-ink); }
.th-prose p, .th-prose li { font-size: calc(16px * var(--fs, 1)); line-height: 1.7; }
.th-prose ul { display: grid; gap: 6px; padding-left: 22px; list-style: disc; }
.th-prose li p + p { margin-top: 4px; }
.th-legal-note { color: var(--th-mute); font-size: calc(14px * var(--fs, 1)); }

/* --- Footer (live site: rounded teal band) ---------------------------------------------------------- */
.th-footer {
  background: var(--th-teal); color: var(--th-white); border-radius: 20px;
  margin: 40px max(10px, env(safe-area-inset-right, 0px)) 10px max(10px, env(safe-area-inset-left, 0px));
  padding-block: 44px 22px;
}
.th-footer a { color: var(--th-white); text-decoration: none; }
.th-footer a:hover { text-decoration: underline; }
/* Kevin's review, item c: the system footer at AV production's scale (1140px container, 18px headings, 16px
   links) in Toupin colours, the logo at the live site's 185x150, the tagline on one line and the live site's 40px
   social circles. From 1440px no service name, email or town wraps (the columns take their content's width). */
.th-fgrid { display: grid; grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr)) minmax(0, 1.3fr); gap: 28px; }
.th-fbrand { display: grid; gap: 14px; align-content: start; justify-items: start; }
.th-flogo { display: inline-flex; width: max-content; }
.th-footer .th-flogo img { width: 185px; height: auto; }
.th-tag {
  font-family: var(--th-display); font-weight: 400; font-size: calc(24px * var(--fs, 1)); line-height: 1.1; text-transform: uppercase; margin: 0;
  white-space: nowrap;
}
html[data-a11y-text="scaled"] .th-tag { white-space: normal; }
@media (min-width: 1440px) {
  html:not([data-a11y-text="scaled"]) .th-fgrid { grid-template-columns: max-content max-content max-content max-content max-content; justify-content: space-between; }
  html:not([data-a11y-text="scaled"]) .th-fcol a, html:not([data-a11y-text="scaled"]) .th-fcontact li { white-space: nowrap; }
}
.th-footer .th-tag { color: var(--th-white); }
/* Social links: 44px targets around the live site's 30px green circles. Glyphs are centred by the grid
   with no inherited margin (AV production fix, base.css:3954-3956: margin 0 and centring on the
   glyph). ACCESSIBILITY CORRECTION: deep-teal glyphs on the green circle (4.4:1) instead of white (2.6:1). */
.th-social { display: flex; gap: 6px; margin-left: -2px; }
.th-soc { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%; }
.th-soc::before { content: none; }
.th-soc svg {
  width: 40px; height: 40px; padding: 10px; margin: 0; box-sizing: border-box; display: block;
  border-radius: 50%; background: var(--th-green); color: var(--th-teal-deep); grid-area: 1 / 1;
}
.th-fcol h3 { font-family: var(--th-display); font-weight: 400; font-size: calc(18px * var(--fs, 1)); line-height: 1.3; text-transform: uppercase; margin: 0 0 10px; color: var(--th-white); }
.th-fcol ul { display: grid; gap: 0; }
.th-fcol li { font-size: calc(16px * var(--fs, 1)); line-height: 1.4; font-weight: 600; }
.th-fcol a { display: inline-flex; align-items: center; min-height: 32px; }
.th-fcontact a { min-height: 44px; }
.th-fcontact li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 8px; align-items: center; overflow-wrap: anywhere; }
.th-fcontact svg { width: 16px; height: 16px; }
.th-fcontact span { padding-block: 6px; }
.th-fbottom { border-top: 1px solid rgba(255, 255, 255, .35); margin-top: 32px; padding-top: 18px; display: grid; gap: 8px; font-size: calc(14px * var(--fs, 1)); line-height: 1.5; }
.th-frow { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; }
.th-frow p, .th-credit { margin: 0; }
.th-legal-nav a { display: inline-flex; align-items: center; min-height: 32px; }
/* ACCESSIBILITY CORRECTION: the mockup's 88% white credit is 4.46:1 on teal; full white is 4.96:1. */
.th-credit { text-align: center; color: var(--th-white); }
.th-credit a { text-decoration: underline; text-underline-offset: 2px; }

/* --- Responsive (mockup breakpoints: 1000px, 860px, 560px) -------------------------------------------- */
@media (max-width: 1000px) {
  .th-rooms, .th-rooms-4, .th-rooms-6, .th-rooms-7 { --cols: 3; }
  .th-rel, .th-svc-grid { --cols: 2; }
  .th-fgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .th-fbrand { grid-column: 1 / -1; }
  .th-trust { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  html[data-a11y-text="scaled"] .th-trust-list { grid-template-columns: minmax(0, 1fr); }
  .th-trust-list { width: 100%; }
  .th-vals { --cols: 2; }
  .th-gallery { --cols: 3; }
  .th-near-hub { --cols: 2; }
}
@media (max-width: 1023px) {
  /* Below the desktop row the system chrome replaces the nav; the hero starts under the 76px chrome.
     Inner pages hide their hero Call/Quote on phones (the approved AV inner-page behaviour while the
     bottom bar is present); the homepage keeps its hero buttons (approved Toupin mobile homepage). */
  .th-hero-body, .th-hero-home .th-hero-body { padding-top: 112px; }
  .th-hero-home { min-height: 0; }
  .th-mobile-hidden { display: none; }
  /* The system's page-end clearance (152px: the bar, the launcher above it and their gaps) moves from inside
     the footer's last row to below the rounded footer, so the teal band keeps the live site's shape. */
  html body .site-footer.th-footer .footer-legal { padding-bottom: 0; }
  /* ADA-SPEC-041: every phone tap target is at least 44px (footer, legal, breadcrumb and town links). */
  .th-fcol a, .th-legal-nav a, .th-crumbs a, .th-center .th-more { min-height: 44px; min-width: 44px; }
  .th-towns a { width: 100%; }
  .th-footer { margin-bottom: calc(130px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 860px) {
  .th-split, .th-local, .th-final, .th-cant, .th-areas, .th-local-area, .th-about-top, .th-haul, .th-why-box, .th-contact { grid-template-columns: minmax(0, 1fr); }
  .th-local, .th-final, .th-areas { padding-block: 28px; }
  .th-why-box { padding: 16px; }
  .th-steps, .th-cards3, .th-partners, .th-revs, .th-revs-2 { --cols: 1; }
  .th-haul { grid-template-columns: minmax(0, 1fr); }
  .th-page .th-haul-img { justify-self: center; }
  .th-steps-band::before { inset: 0 0 18% 0; }
  /* Phones: the copy covers the photo top to bottom, so the live gradient turns vertical: lighter at the top,
     where the header and breadcrumb sit, the scrim holding the text. */
  .th-hero::before { background: linear-gradient(180deg, rgba(1, 125, 125, .7) 0%, rgba(1, 125, 125, .45) 45%, rgba(1, 125, 125, .65) 100%); }
  .th-hero:not(.th-hero-text) .th-hero-body::before { inset: -24px -20px; }
  .th-hero-text::before { background: var(--th-teal); }
  .th-hero-body { padding-bottom: 120px; }
  .th-hero-text .th-hero-body { padding-bottom: 48px; }
  .th-sec { padding-block: 56px; }
  .th-near { grid-template-columns: 1fr; }
  .th-ph-45 { aspect-ratio: 4 / 4.2; }
  .th-local-area .th-map { order: 2; }
}
@media (max-width: 700px) {
  .th-page .th-hero-img { object-position: var(--th-pos-m, 50% 40%); }
  /* Run 8, item 2c: three room cards to a row leave their lists narrower than an ordinary word ("Entertainment",
     98px for 104px at 600px); two to a row until the single column at 560px. */
  .th-rooms, .th-rooms-3, .th-rooms-4, .th-rooms-6, .th-rooms-7 { --cols: 2; }
  .th-fcontact { grid-column: 1 / -1; }
}
@media (max-width: 379px) {
  /* Run 8, item 2c: two nearby-town cards to a row leave their names 81px ("Merrimack" needs 91px). */
  .th-near { --cols: 1; }
}
@media (max-width: 560px) {
  .th-rooms, .th-rooms-2, .th-rooms-3, .th-rooms-4, .th-rooms-6, .th-rooms-7, .th-rel, .th-svc-grid, .th-vals, .th-near-hub { --cols: 1; }
  .th-xlist, .th-trust-list { grid-template-columns: 1fr; }
  .th-fgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .th-fcontact { grid-column: 1 / -1; }
  html[data-a11y-text="scaled"] .th-fgrid { grid-template-columns: minmax(0, 1fr); }
  .th-towns ul { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .th-gallery { --cols: 2; --gap: 10px; }
  .th-pair { grid-template-columns: 1fr; }
  .th-room { padding: 18px; }
  .th-head-row h2 { max-width: none; }
  .th-frow { justify-content: center; text-align: center; }
}

/* --- Phones, below 768px (Kevin's second review, items o to r) ------------------------------------------------ */
@media (max-width: 767px) {
  /* Badge fix, item b: below 768px the military badge leaves the hero for the shared phone card (160px, centred),
     directly under the homepage's nominee badge, a page's trust strip, or the hero on /about/.
     Final fixes, item 6: in a trust strip the card sits directly under the nominee artwork, before the trust
     items, 16px below it as on the homepage (the strip's 24px row gap less 8px). */
  .th-trust .th-mil-in { padding-top: 0; margin-top: -8px; }
  /* Final fixes, item 4: on the homepage, the heading, the card groups, the intro, then the button centred. */
  .th-page .th-desk-only { display: none; }
  .th-page p.th-phone-only { display: block; margin-top: 24px; }
  .th-page .th-btns.th-phone-only { display: flex; justify-content: center; margin-top: 16px; }
  /* Review fixes, item 4c (the approved mockup): the partner sections' compact phone rows are the shared partner
     cards' own. */
  /* Review fixes, item 5: an inner-page hero is only as tall as its content, the space below its last line the
     same 36px as from the header to its first line (the homepage hero's phone padding). */
  .th-hero:not(.th-hero-text) .th-hero-body { padding-bottom: 36px; }
  /* Final fixes, item 7: the footer's phone headings are the system footer's option (footer.mobile_headings: 24px,
     a 34 by 3px bar in the green under each, a thin divider above every group after the first), in the light brand
     green token --th-green-light (#A8ED7C, 3.56:1 on the teal, large text). */
  /* With the badge and the buttons out of the phone hero, the text scrim covers the whole hero body again, from just
     above the hero (behind the phone chrome) to below the trust line, as approved in the first review; the trust
     line keeps its own scrim on top, and its stars take a lighter gold, so both hold 4.5:1 over the photo. */
  .th-hero:not(.th-hero-text) .th-hero-body { position: relative; isolation: isolate; }
  .th-hero:not(.th-hero-text) .th-hero-body::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none; inset: -24px -20px;
    border-radius: 48px; background: rgba(4, 63, 63, var(--th-scrim, .6)); filter: blur(24px);
  }
  .th-hero:not(.th-hero-text) .th-hero-copy::before { content: none; }
  /* Trust line fix, item b: the line ends before the accessibility button's column (the shared trust line's own
     96px clearance: 12px from the edge, 56px wide, an 8px gap and the gutter). */
  /* o2. No hero buttons on phones, the homepage included: the bottom Call and Quote bar carries them. */
  .th-hero .th-hero-acts { display: none; }
  /* o3. The homepage intro shows its first sentence only, and the hero ends shortly after the trust line. */
  .th-lede-rest { display: none; }
  .th-hero-home .th-hero-body { padding-bottom: 36px; }
  /* o4. The trust line sits directly under the intro (the buttons above it are hidden). */
  .th-hero-home .th-hero-body { gap: 16px; }
  /* Homepage phone hero, photo first (as the live site), tightened: the shared photo-first hero
     (shared_patterns.hero_photo_first, hero.phone_layout: photo_first) with its approved measurements: the photo
     (its own 1:1.15 crop) 1.15 times the screen width tall, untinted, fading from two thirds down over 111px into the
     deep teal, the H1 50px into the fade (62% teal there), the header band behind the pinned header to 110px, the
     scrims off, the copy and the trust line centred. The band takes the page's own strength. The floating
     accessibility button hides over the hero on phones (layout.a11y_launcher_phone: after_hero). */
  .th-hero { --hero-pf-band: var(--th-band, .66); }
  /* p. Alignment: section headings, intro and standalone paragraphs, small call-to-action cards and buttons
     centred; check and icon lists, contact rows and the contents of cards left-aligned; the hero unchanged. */
  .th-page h2, .th-head, .th-head-row, .th-stack, .th-final > div:first-child, .th-areas > div:first-child,
  .th-about-top, .th-haul .th-stack, .th-pq-wrap { text-align: center; }
  .th-head-row { flex-direction: column; align-items: center; justify-content: center; }
  .th-page .th-head p { margin-inline: auto; }
  .th-page .th-btns { justify-content: center; }
  .th-ctaband { flex-direction: column; align-items: center; text-align: center; }
  .th-estimate { text-align: center; justify-items: center; }
  .th-ticks, .th-factors, .th-xlist, .th-room, .th-card, .th-ncard, .th-in, .th-rcard, .review-card,
  .th-step, .th-cant, .th-trust-list { text-align: left; }
  .th-step { justify-items: start; }
  .th-step .th-step-art { justify-self: center; }
  .th-page .th-contact-list { width: fit-content; max-width: 100%; margin-inline: auto; text-align: left; }
  .th-page .th-contact-list li { justify-items: start; }
  .th-prose, .th-prose p, .th-prose li, .th-legal { text-align: left; }
  /* q. Buttons: AV production's mobile button (full width, 16px bold, 16px by 20px padding, 63px), and two together
     stack at the same width. The hero keeps its alignment. */
  .th-page .th-btns { flex-direction: column; align-items: stretch; width: 100%; }
  .th-page .th-btn, .th-hero-home .th-btn { width: 100%; min-width: 0; min-height: 63px; padding: 16px 20px; font-size: calc(16px * var(--fs, 1)); line-height: 1.7; }
  .th-ctaband .th-btns, .th-estimate .th-btn { width: 100%; }
  .th-ctaband .th-txtlink { justify-content: center; }
  /* f. The before and after pair stacks (shared), h. the area cards keep two columns (area_cards.phone_columns: 2),
     e. the carousel's arrows flank the dots with the pause below (shared): the patterns' own phone layouts. */
  /* r. Footer: one centred column (AV production): logo, tagline and social icons, each column's heading and
     links, then the contact rows; the bottom row centred and stacked. */
  .th-fgrid, html[data-a11y-text="scaled"] .th-fgrid { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; gap: 24px; }
  .th-fbrand { grid-column: auto; justify-items: center; }
  .th-social { justify-content: center; margin-left: 0; }
  .th-fcol { justify-items: center; }
  .th-fcol ul { justify-items: center; }
  .th-fcontact { grid-column: auto; }
  .th-fcontact ul { width: fit-content; margin-inline: auto; justify-items: start; }
  .th-frow { flex-direction: column; align-items: center; justify-content: center; text-align: center; }
  .th-fbottom { justify-items: center; text-align: center; }
}

/* --- Shared patterns (shared_patterns) --- */

/* --- Hero trust line (shared_patterns.hero_trust_line) ---
   Over the hero photo the line carries its own soft scrim (--hero-trust-scrim), spread past the stars so they
   never sit on its faded edge; with --hero-trust-star (a lighter gold where the photo needs it) it holds 4.5:1
   for the stars and the text. On phones it ends before the floating accessibility button's column. */
.hero-trust { position: relative; isolation: isolate; justify-self: start; margin: 0; }
.hero-trust::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none; inset: -16px -32px;
  border-radius: 40px; background: var(--hero-trust-scrim, rgba(0, 0, 0, .55)); filter: blur(18px);
}
.hero-trust a {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: 44px; color: var(--hero-trust-color, var(--color-contrast));
  font-weight: 600; font-size: calc(17px * var(--fs, 1)); line-height: 1.4; text-decoration: none;
}
.hero-trust-text { text-decoration: underline; text-underline-offset: 3px; }
.hero-trust-stars { color: var(--hero-trust-star, var(--color-rating)); font-size: calc(20px * var(--fs, 1)); letter-spacing: 2px; line-height: 1; }
@media (max-width: 767px) {
  .hero-trust { max-width: calc(100vw - var(--hero-trust-clear, 96px)); }
}
/* --- Phone hero, photo first (shared_patterns.hero_photo_first; a hero with class hero--photo-first) ---
   Below 768px the photo (its own phone crop, hero-pf-photo) fills a top area --hero-pf-ratio times the screen
   width tall, untinted, then fades from --hero-pf-fade-at into the solid --hero-pf-rgb colour behind the copy
   (solid --hero-pf-fade-len below the fade start). The copy starts --hero-pf-text-offset into the fade, where
   the fade is already at --hero-pf-fade-mid, so a white first line keeps 3:1 over the photo. One exception to
   "no tint above the fade": a band behind the pinned header (solid to --hero-pf-band-solid, gone by
   --hero-pf-band-end) so the header's controls and rings keep their contrast. The text scrims are off; the
   copy and the trust line are centred, the line clear of the accessibility button's column on both sides. */
@media (max-width: 767px) {
  .hero.hero--photo-first { --hero-pf-h: calc(100vw * var(--hero-pf-ratio, 1.15)); background: rgb(var(--hero-pf-rgb, 27, 31, 31)); }
  .hero--photo-first .hero-pf-photo { inset: 0 0 auto 0; height: var(--hero-pf-h); }
  .hero--photo-first .hero-pf-photo img { height: 100%; }
  .hero.hero--photo-first::before {
    inset: 0 0 auto 0; height: var(--hero-pf-h);
    background:
      linear-gradient(180deg, rgba(var(--hero-pf-rgb, 27, 31, 31), var(--hero-pf-band, .66)) 0, rgba(var(--hero-pf-rgb, 27, 31, 31), var(--hero-pf-band, .66)) var(--hero-pf-band-solid, 76px), rgba(var(--hero-pf-rgb, 27, 31, 31), 0) var(--hero-pf-band-end, 110px)),
      linear-gradient(180deg, rgba(var(--hero-pf-rgb, 27, 31, 31), 0) 0, rgba(var(--hero-pf-rgb, 27, 31, 31), 0) var(--hero-pf-fade-at, 66.7%), rgba(var(--hero-pf-rgb, 27, 31, 31), var(--hero-pf-fade-mid, .62)) calc(var(--hero-pf-fade-at, 66.7%) + var(--hero-pf-text-offset, 50px)),
        rgb(var(--hero-pf-rgb, 27, 31, 31)) calc(var(--hero-pf-fade-at, 66.7%) + var(--hero-pf-fade-len, 111px)), rgb(var(--hero-pf-rgb, 27, 31, 31)) 100%);
  }
  .hero.hero--photo-first .hero-pf-body::before, .hero--photo-first .hero-trust::before { content: none; }
  .hero--photo-first .hero-pf-body { padding-top: calc(var(--hero-pf-h) * var(--hero-pf-text-at, .667) + var(--hero-pf-text-offset, 50px)); justify-items: center; text-align: center; }
  .hero--photo-first .hero-pf-copy { justify-items: center; }
  .hero--photo-first .hero-trust { justify-self: center; max-width: calc(100vw - var(--hero-pf-trust-clear, 152px)); }
  .hero--photo-first .hero-trust a { justify-content: center; text-align: center; }
}
/* --- Promotional badge (shared_patterns.promo_badge) ---
   From 768px the artwork is a small tab on the hero's bottom edge (--promo-tab-width, the same at every width;
   the hero places it); below 768px the tab hides and a centred card (--promo-card-width) shows where the page
   puts it. --promo-aspect: the artwork's width / height. Inline SVG artwork stays sharp at any size. */
.promo-tab {
  position: absolute; right: 0; bottom: var(--promo-tab-bottom, 24px); width: var(--promo-tab-width, 150px); height: auto;
  aspect-ratio: var(--promo-aspect, 2 / 1); z-index: 1; filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .25));
}
.promo-card { display: none; }
@media (max-width: 767px) {
  .promo-tab { display: none; }
  .promo-card { display: flex; justify-content: center; padding-top: var(--promo-card-gap, 16px); }
  .promo-card-art { display: block; width: var(--promo-card-width, 160px); height: auto; aspect-ratio: var(--promo-aspect, 2 / 1); }
}
/* --- Before and after pair (shared_patterns.before_after) ---
   Two equal cells (--ba-aspect) side by side, each image covering its cell, each labelled on the image; phones
   stack them, Before first. */
.ba-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ba-gap, 12px); }
.ba-cell { position: relative; margin: 0; border-radius: var(--ba-radius, 14px); overflow: hidden; aspect-ratio: var(--ba-aspect, 3 / 4); background: var(--ba-fill, var(--surface-accent)); }
.ba-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ba-tag {
  position: absolute; left: 12px; top: 12px; background: var(--surface-default); color: var(--ba-tag-color, var(--color-neutral-dark));
  border-radius: 999px; padding: 4px 12px; font-weight: 700; font-size: calc(13px * var(--fs, 1)); line-height: 1.3;
  text-transform: uppercase; letter-spacing: .04em;
}
.ba-tag--after { background: var(--color-primary); color: var(--color-contrast); }
@media (max-width: 767px) {
  .ba-pair { grid-template-columns: minmax(0, 1fr); }
}
/* --- Partner band and cards (shared_patterns.partner_cards) ---
   The band names the partnership; the cards (--partner-cols, three by default) share their rows (subgrid), so
   logos, names and lines line up across them; the logo slot is one fixed height (--partner-logo-h) and the
   logo is fitted inside it, never past its native size. From 768px a name may sit on set lines. Below 768px
   compact rows: a 96px logo column with a 72px slot, the name and line beside it, left-aligned. */
p.partner-band {
  margin: 0 0 24px; padding: 14px 24px; border-radius: var(--partner-radius, 10px); background: var(--color-primary); color: var(--color-contrast);
  font-family: var(--font-heading); font-weight: 400; font-size: calc(22px * var(--fs, 1)); line-height: 1.25; text-align: center;
}
.partner-cards { display: grid; grid-template-columns: repeat(var(--partner-cols, 3), minmax(0, 1fr)); grid-template-rows: auto auto auto; column-gap: 24px; }
.partner-card {
  display: grid; grid-row: span 3; grid-template-rows: subgrid; row-gap: 8px; justify-items: center; text-align: center;
  background: var(--surface-default); border: 1px solid var(--partner-border, var(--color-border-subtle)); border-top: 4px solid var(--color-primary);
  border-radius: var(--partner-radius, 10px); padding: 24px; box-shadow: var(--partner-shadow, 0 0 16px var(--color-shadow));
}
.partner-card-txt { display: contents; }
.partner-card-logo { height: var(--partner-logo-h, 110px); width: 100%; display: flex; align-items: center; justify-content: center; margin-bottom: 8px; }
.partner-card-logo img { max-height: 100%; max-width: 100%; width: auto; height: auto; }
.partner-cards .partner-card h3 { font-size: calc(18px * var(--fs, 1)); line-height: 1.3; }
.partner-card p { font-size: calc(15px * var(--fs, 1)); line-height: 1.45; color: var(--partner-text, var(--color-neutral-dark)); }
@media (min-width: 768px) { .partner-name-line { display: block; } }
@media (max-width: 767px) {
  p.partner-band { font-size: calc(15.5px * var(--fs, 1)); padding: 12px 14px; margin-bottom: 12px; }
  .partner-cards { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: 12px; }
  .partner-card {
    grid-row: auto; grid-template-rows: none; grid-template-columns: 96px minmax(0, 1fr); column-gap: 14px;
    justify-items: stretch; align-items: center; text-align: left; padding: 14px; border-radius: var(--partner-row-radius, 12px);
  }
  .partner-card-logo { height: 72px; margin: 0; }
  .partner-card-txt { display: grid; gap: 2px; align-content: center; }
  .partner-cards .partner-card h3 { font-size: calc(16px * var(--fs, 1)); line-height: 1.3; }
  .partner-card p { font-size: calc(14px * var(--fs, 1)); line-height: 1.4; }
}
/* --- FAQ accordion (shared_patterns.faq_accordion) ---
   Question bars (--faq-bar-bg, --faq-bar-color; 82px, 18px bold; compact at 860px and below: 70px,
   16px) over the answer surface (--faq-answer-bg). Each answer's wrapper slides by its grid rows, 0fr to 1fr over
   250ms ease-out; the inner element clips with min-height 0 and the padding is inside it, so nothing jumps at
   the start or end; the chevron turns over the same time. The script sets data-state as the answer starts to
   open or close and closes the details when the slide ends. Without the script the answer shows whenever its
   details is open. Reduced motion (the system's or the widget's): no transition. */
.faq-accordion { display: grid; gap: var(--faq-gap, 12px); max-width: none; margin: 0; }
.faq-accordion details { border-radius: var(--faq-radius, 5px); overflow: hidden; background: var(--faq-answer-bg, var(--surface-accent)); }
.faq-accordion summary {
  list-style: none; cursor: pointer; background: var(--faq-bar-bg, var(--color-primary)); color: var(--faq-bar-color, var(--color-contrast)); padding: 24px 30px; min-height: 82px;
  display: flex; justify-content: space-between; gap: 16px; align-items: center; font-weight: 700; font-size: calc(18px * var(--fs, 1)); line-height: 1.78;
}
.faq-accordion summary::-webkit-details-marker { display: none; }
.faq-accordion summary::after {
  content: ""; width: 10px; height: 10px; border-right: 2px solid var(--faq-bar-color, var(--color-contrast)); border-bottom: 2px solid var(--faq-bar-color, var(--color-contrast));
  transform: rotate(45deg) translateY(-3px); flex: none; transition: transform .25s ease-out;
}
.faq-accordion details[open] summary::after { transform: rotate(-135deg) translateY(-3px); }
.faq-answer { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .25s ease-out; }
.faq-accordion details[data-state="closed"] > .faq-answer { grid-template-rows: 0fr; }
.faq-answer-in { min-height: 0; overflow: hidden; }
.faq-accordion details[data-state="open"] summary::after { transform: rotate(-135deg) translateY(-3px); }
.faq-accordion details[data-state="closed"] summary::after { transform: rotate(45deg) translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .faq-accordion summary::after, .faq-answer { transition: none; } }
html[data-a11y-motion="reduce"] .faq-accordion summary::after, html[data-a11y-motion="reduce"] .faq-answer { transition: none; }
.faq-answer-in > p { padding: 20px 30px 24px; font-size: calc(18px * var(--fs, 1)); line-height: 1.78; }
@media (max-width: 860px) {
  .faq-accordion summary { padding: 20px; min-height: 70px; font-size: calc(16px * var(--fs, 1)); line-height: 1.75; }
  .faq-answer-in > p { padding: 16px 20px 20px; font-size: calc(16px * var(--fs, 1)); }
}
/* Phones: questions and answers read left to right whatever the section's own alignment. */
@media (max-width: 767px) {
  .faq-accordion { text-align: left; }
}
/* --- Area cards (shared_patterns.area_cards) ---
   Two columns of equal rows; each card a pin, the name and an arrow; the See all card in --color-primary,
   bold and underlined, with the arrow; a place without a page is the same tile, not a link. Phones: the
   grid's own text runs left to right whatever the section's alignment; area_cards.phone_columns columns. */
.area-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 10px; margin-top: 20px; }
.area-cards > li { display: grid; }
.area-card {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) 16px; gap: 8px; align-items: center; min-height: 48px;
  background: var(--surface-default); border: 1px solid var(--area-card-border, var(--color-border-subtle)); border-radius: var(--area-card-radius, 10px); padding: 12px 14px;
  text-decoration: none; font-weight: 600; font-size: calc(16px * var(--fs, 1)); line-height: 1.3;
  overflow-wrap: break-word;  /* a name wider than its card (a narrow screen, enlarged text) wraps, never overflows */
}
.area-cards .area-card { color: var(--area-card-color, var(--color-neutral-dark)); }
.area-card:hover { border-color: var(--color-primary); }
.area-card svg { width: 18px; height: 18px; color: var(--color-primary); }
.area-cards .area-card--all { grid-template-columns: minmax(0, 1fr) 16px; border-color: var(--color-primary); color: var(--color-primary); text-decoration: underline; text-underline-offset: 3px; font-weight: 700; }
.area-card--all:hover { background: var(--area-card-hover, var(--surface-accent)); }
.area-card--plain { grid-template-columns: 22px minmax(0, 1fr); }
.area-card--plain:hover { border-color: var(--area-card-border, var(--color-border-subtle)); }
@media (max-width: 767px) {
  .area-cards { text-align: left; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .area-cards .area-card { padding: 12px 10px; gap: 6px; grid-template-columns: 18px minmax(0, 1fr) 14px; }
  .area-cards .area-card--all { grid-template-columns: minmax(0, 1fr) 14px; }
}
@media (max-width: 379px) {
  .area-cards { grid-template-columns: minmax(0, 1fr); }
}
/* --- See all link (shared_patterns.see_all_link): bold, underlined, with the arrow. The words wrap when they do not
   fit (a narrow screen with enlarged text); the last word and the arrow never part. The arrow sits 6px after the
   last word, centred on its line, where a single line of text and the arrow are centred together. --- */
a.see-all-link {
  display: inline-flex; align-items: center; padding-block: 11px; color: var(--color-primary); font-weight: 700;
  text-decoration: underline; text-underline-offset: 3px;
}
.see-all-label { min-width: 0; }
.see-all-arrow::before { content: "\2060"; }  /* a word joiner: the arrow never wraps away from the last word */
.see-all-link svg { width: 16px; height: 16px; margin-left: 6px; vertical-align: top; position: relative; top: calc((1lh - 16px) / 2); }

@media (max-width: 767px) {
  .footer-column .footer-heading { color: var(--th-green-light); font-size: calc(24px * var(--fs, 1)); line-height: 1.2; margin-bottom: 14px; }
  .footer-column .footer-heading::after { content: ""; display: block; width: 34px; height: 3px; margin: 10px auto 0; border-radius: 2px; background: var(--color-secondary); }
  .footer-column ~ .footer-column { border-top: 1px solid color-mix(in srgb, var(--color-contrast) 25%, transparent); padding-top: 24px; width: 100%; }
}

/* --- Accessibility base (BCS Accessibility Skill v1, Part 2, verbatim) --- */
html{scroll-behavior:smooth;--fs:1}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
:focus-visible{outline:3px solid var(--color-focus);outline-offset:3px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link:focus{position:fixed;z-index:10000;top:10px;left:10px;padding:12px 16px;background:var(--color-neutral-light);color:var(--color-primary);font-weight:800}

/* --- Accessibility supplemental --- */
/* ADA-SPEC-015: contact and footer contact columns reflow.
   Supplemental to the Accessibility Skill, not part of any verbatim block.
   Class names pinned 2026-09-17; the Contact and Footer modules must match. */
.contact-details,
.footer-contact-details {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* --- Accessibility widget (BCS Accessibility Skill v1, Part 5.1, verbatim) --- */
/* ===== ADA / accessibility widget (self-contained, no third-party script) ===== */
.a11y-widget{position:fixed;left:18px;bottom:18px;z-index:1200;font-family:var(--font-body)}
.a11y-toggle{width:56px;height:56px;border-radius:50%;border:3px solid var(--color-contrast);background:var(--color-primary);color:var(--color-secondary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 6px 18px var(--color-shadow-strong);padding:0}
.a11y-toggle:hover{background:var(--color-secondary);color:var(--color-primary);border-color:var(--color-primary)}
.a11y-toggle svg{width:30px;height:30px}
.a11y-panel{position:absolute;left:0;bottom:68px;width:min(360px,calc(100vw - 36px));max-height:min(78vh,640px);overflow:auto;background:var(--surface-default);color:var(--color-neutral-dark);border:2px solid var(--color-primary);border-radius:8px;box-shadow:0 14px 40px var(--color-shadow-strong)}
.a11y-panel[hidden]{display:none}
.a11y-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:14px 16px;background:var(--color-primary);color:var(--color-contrast);border-bottom:3px solid var(--color-secondary)}
.a11y-title{font-family:var(--font-heading);font-weight:800;font-size:calc(17px * var(--fs,1));margin:0}
.a11y-close{width:40px;height:40px;border:2px solid var(--color-contrast);border-radius:4px;background:transparent;color:var(--color-contrast);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.a11y-close:hover{background:var(--color-contrast);color:var(--color-primary)}
.a11y-body{padding:14px 16px 16px}
.a11y-section-label{font-size:calc(13px * var(--fs,1));font-weight:800;margin:0 0 8px;color:var(--color-muted)}
.a11y-text-row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px;padding:10px 12px;border:1px solid var(--color-border-subtle);border-radius:6px}
.a11y-text-row span{font-weight:700;font-size:calc(15px * var(--fs,1))}
.a11y-stepper{display:inline-flex;align-items:center;gap:6px}
.a11y-stepper button{min-width:44px;height:44px;border:2px solid var(--color-primary);border-radius:4px;background:var(--surface-default);color:var(--color-primary);font-weight:800;cursor:pointer;font-size:calc(15px * var(--fs,1))}
.a11y-stepper button:hover{background:var(--color-primary);color:var(--color-secondary)}
.a11y-stepper button:disabled{opacity:.35;cursor:not-allowed}
.a11y-stepper output{min-width:52px;text-align:center;font-weight:800;font-size:calc(14px * var(--fs,1))}
.a11y-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.a11y-opt{min-height:64px;padding:10px 8px;border:2px solid var(--color-border-subtle);border-radius:6px;background:var(--surface-default);color:var(--color-neutral-dark);cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;font-weight:700;font-size:calc(13px * var(--fs,1));line-height:1.2;text-align:center}
.a11y-opt svg{width:24px;height:24px;flex:0 0 auto}
.a11y-opt:hover{border-color:var(--color-primary)}
.a11y-opt[aria-pressed="true"]{background:var(--color-primary);color:var(--color-secondary);border-color:var(--color-primary)}
.a11y-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:14px;padding-top:12px;border-top:1px solid var(--color-border-subtle);font-size:calc(13px * var(--fs,1))}
.a11y-reset{min-height:44px;padding:8px 14px;border:2px solid var(--color-primary);border-radius:4px;background:transparent;color:var(--color-primary);font-weight:800;cursor:pointer}
.a11y-reset:hover{background:var(--color-primary);color:var(--color-secondary)}
.a11y-foot a{color:var(--color-neutral-dark);font-weight:700}
@media (max-width:767px){.a11y-widget{left:12px;bottom:12px}.a11y-panel{position:fixed;left:12px;right:12px;bottom:80px;width:auto;max-height:72vh}}
/* --- modes set by the widget on <html> --- */
html[data-a11y-contrast="high"]{--color-primary:#000000;--color-secondary:#FFD100;--color-secondary-on-light:#5A4600;--color-neutral-dark:#000000;--color-contrast:#FFFFFF;--surface-accent:#FFFFFF;--color-border-subtle:#000000;--color-muted:#1A1A1A;--color-shadow:rgba(0,0,0,0);--color-shadow-strong:rgba(0,0,0,0);--color-overlay:rgba(0,0,0,.9)}
html[data-a11y-contrast="high"] a{text-decoration:underline}
html[data-a11y-contrast="high"] .btn{border-width:2px;border-color:currentColor}
html[data-a11y-contrast="high"] .service-card,html[data-a11y-contrast="high"] .review-card,html[data-a11y-contrast="high"] .hero-form,html[data-a11y-contrast="high"] .contact-form,html[data-a11y-contrast="high"] .accordion-item{border:2px solid #000}
html[data-a11y-contrast="high"] .footer-hours-label,html[data-a11y-contrast="high"] .rating-count,html[data-a11y-contrast="high"] .review-source{opacity:1;color:inherit}
html[data-a11y-contrast="high"] :focus-visible{outline:3px solid #FFFFFF;outline-offset:2px;box-shadow:0 0 0 6px #000000}
html[data-a11y-mono="1"] :is(.announcement-banner,.site-header,.mobile-chrome,.mobile-menu-overlay,.hero,main,.site-footer){filter:grayscale(1)}
html[data-a11y-links="1"] a:not(.btn):not(.a11y-foot a){text-decoration:underline!important;text-decoration-thickness:2px;text-underline-offset:3px;outline:2px dashed currentColor;outline-offset:2px}
html[data-a11y-font="readable"]{--font-heading:Arial,Helvetica,sans-serif;--font-body:Verdana,Arial,sans-serif}
html[data-a11y-font="readable"] body{letter-spacing:.02em;word-spacing:.06em}
html[data-a11y-spacing="1"] body{line-height:2}
html[data-a11y-spacing="1"] p,html[data-a11y-spacing="1"] li,html[data-a11y-spacing="1"] label{line-height:2}
html[data-a11y-spacing="1"] p{margin-bottom:1.4em}
html[data-a11y-text="scaled"] h1,html[data-a11y-text="scaled"] h2,html[data-a11y-text="scaled"] h3{overflow-wrap:anywhere}
html[data-a11y-text="scaled"] .header-inner{flex-wrap:wrap;row-gap:8px;padding-top:12px;padding-bottom:12px}
html[data-a11y-text="scaled"] .main-nav{flex:1 1 320px}
html[data-a11y-text="scaled"] .main-nav>ul{flex-wrap:wrap;justify-content:flex-start;row-gap:0}
html[data-a11y-text="scaled"] .nav-item>a{white-space:normal}
html[data-a11y-text="scaled"] .header-ctas{flex-wrap:wrap;margin-left:auto}
html[data-a11y-text="scaled"] .header-ctas .btn{white-space:normal}
html[data-a11y-text="scaled"] .btn-phone .hours-line{max-width:none}
html[data-a11y-motion="reduce"]{scroll-behavior:auto}
html[data-a11y-motion="reduce"] *,html[data-a11y-motion="reduce"] *::before,html[data-a11y-motion="reduce"] *::after{transition:none!important;animation:none!important}
html[data-a11y-cursor="big"],html[data-a11y-cursor="big"] *{cursor:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 48 48'><path d='M6 4 L6 40 L16 30 L22 44 L30 41 L24 27 L38 27 Z' fill='%23000' stroke='%23fff' stroke-width='3' stroke-linejoin='round'/></svg>") 6 4,auto!important}
