/* Patty's Pressure Washing - site.css. Light-first, no frameworks. Tokens and colour pairings: DESIGN_V2_SPEC 2 +
   3.1-3.7, DESIGN_V4_SPEC 4 + 8. Cap: perf_check CSS_MAX_BYTES. Text rem, photos/gutters px. */

/* 1. Tokens */
:root {
  --bg: #f7f8f6; /* V3 FULL FRAME (docs/DESIGN_V3_SPEC.md 3.2): a neutral off-white; the cream "letter" ground is retired (#15). Recomputed contrast table: DESIGN_V3_SPEC 12 */
  --surface: #ffffff;
  --surface-2: #eef3e9;
  --ink: #14201a; /* every sentence: 15.75:1 on --bg, 16.78:1 on white */
  --muted: #44524a; /* secondary text that is still a sentence: 7.73:1 on --bg, 8.23:1 on white, 7.30:1 on --surface-2 (AAA) */
  --caption: #3f4d44; /* captions, card text, ledger labels, meta: 8.37:1 on --bg, 8.91:1 on white (AAA) */
  --line: #e0e7db;
  --line-strong: #7f8d86; /* control boundaries + FAQ rules that must read without hover: 3.18:1 on --bg, 3.47:1 on white */
  --brand: #0c600f;
  --brand-2: #0a4d0c;
  --brand-deep: #07400a; /* top of the hero / CTA-band gradient (white 12.02:1, --gold-soft 9.78:1); as text on --bg 11.01:1 */
  --brand-ink: #0c600f; /* links: 7.14:1 on --bg, 7.79:1 on white */
  --brand-soft: #e3efe2;
  --gold: #b9820f; /* RULES ONLY (3.07:1 non-text) - never text, never a fill under text */
  --gold-ink: #6b4a06; /* gold as text on light: eyebrows, numerals, arrows, card meta, stars (7.38:1 on --bg, 8.05:1 on white, 6.55:1 on --gold-soft) */
  --gold-soft: #f3e7c9; /* text on green (9.78:1 on --brand-deep, 6.34:1 on --brand); the step numeral chip */
  --gold-bright: #e6b84e; /* the CTA-band button fill (ink 9.06:1), stars + icons on green, the footer rule */
  --ink-2: #0f2a14; /* h1 on cream (14.13:1), the dark footer ground */
  --brand-soft-line: #26402b; /* hairlines on the dark footer */
  --danger: #a12b2b;
  --shadow: 0 1px 2px rgba(14,32,20,.05), 0 10px 30px rgba(14,32,20,.07); /* nav dropdown + the editorial photos / plates only */
  --shadow-sm: 0 1px 2px rgba(14,32,20,.06); /* card hover only, never at rest */
  /* 4.1 (DECISION #24): rhythm. `84px 0` becomes an ASYMMETRIC scale (pt : pb ~ 4:3). >= 900px: 168px -> 112px. */
  --band-pt: 40px; --band-pb: 32px;      /* standard band                      */
  --band-pt-lg: 48px; --band-pb-lg: 40px; /* the one dark band, the closing CTA */
  --band-pt-sm: 28px; --band-pb-sm: 24px; /* a band continuing the previous idea */
  --radius: 14px;
  --radius-sm: 8px;
  --wrap: 1060px;
  --wrap-header: 1440px; /* the sticky header may run wider than the content column */
  --gutter: 22px;
  --header-h: 5.5rem; /* 88px at a 16px root; scales with the reader's font setting like the nav rows inside it */
  --font-body: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-head: "Bricolage Grotesque", "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230c600f' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5l2.5 2.5L16 9.5'/%3E%3C/svg%3E");
  color-scheme: light;
}

/* 2. Reset / base - body 18px / 1.6 (17px under 560px), root stays 100 % */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h) + .75rem); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1.125rem/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg, video { max-width: 100%; height: auto; display: block; }
[hidden] { display: none !important; } /* wins over the display rules below (lazy Jobber iframe pre-JS) */
img { font-style: italic; background: var(--surface-2); } /* alt text shows nicely while loading */
iframe { border: 0; max-width: 100%; }
a { color: var(--brand-ink); text-underline-offset: .15em; }
a[href^="mailto:"] { overflow-wrap: anywhere; word-break: break-all; } /* Sales@PattysPressureWashing.com breaks at a 24px root instead of scrolling the page sideways */
a:hover { color: var(--brand-2); }
button { font: inherit; color: inherit; }
ul, ol { padding-left: 1.25em; }
hr { border: 0; border-top: 1px solid var(--line); margin: 2rem 0; }
/* Focus: two-tone ring (halo + ink outline) >= 3:1; flipped on green */
:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; box-shadow: 0 0 0 2px var(--surface); }
.cta-band :focus-visible, .skip-link:focus-visible { outline-color: #fff; box-shadow: 0 0 0 2px var(--brand-2); }
::selection { background: var(--gold-soft); color: var(--ink); }
.skip-link {
  position: absolute; left: 12px; top: -4rem; z-index: 1000; /* -4rem, not -60px: the pill is 2.8rem tall (1.6 line-height + .6em x 2) and scaled with the root, so a fixed offset let it peek in at a 24px root */
  background: var(--brand); color: #fff; padding: .6em 1em; border-radius: 999px; font-weight: 600; font-size: 1rem;
}
.skip-link:focus { top: 12px; }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.draft-banner {
  background: var(--gold-soft); color: #5c3f05; border-bottom: 1px solid var(--gold); /* #5c3f05: 7.88:1 on --gold-soft (AAA); --gold-ink was 6.55 here */
  padding: 10px var(--gutter); text-align: center; font-size: .875rem;
}

/* 3. Typography - Bricolage 700 (800 retired), sentence-case eyebrows with a gold rule */
h1, h2, h3, h4 {
  font-family: var(--font-head);
  line-height: 1.08;
  letter-spacing: -.02em;
  text-wrap: balance;
  margin: 0 0 .5em;
  font-weight: 700;
}
h1 { font-size: clamp(2.5rem, 5.2vw, 3.75rem); line-height: 1.02; font-variation-settings: 'opsz' 96; } /* 40-60px */
h2 { font-size: clamp(1.875rem, 3.4vw, 2.625rem); } /* 30-42px (V4 4.6: scale contrast against 18px body) */
h3 { font-size: clamp(1.1875rem, 2vw, 1.3125rem); } /* 19-21px */
h4 { font-size: 1.0625rem; }
p { margin: 0 0 1em; text-wrap: pretty; }
.lead { font-size: clamp(1.1875rem, 1.9vw, 1.3125rem); line-height: 1.5; color: var(--ink); max-width: 48ch; } /* 19-21px, a sentence: ink */
/* Eyebrow: 15px sentence case + a 22 x 1 px gold rule on the first line (the only tracked caps left are the BEFORE / AFTER tags) */
.eyebrow {
  display: inline-flex; align-items: flex-start; gap: 12px; margin: 0 0 14px; text-wrap: balance; max-width: 40ch;
  font: 600 .9375rem/1.4 var(--font-body); letter-spacing: .01em; color: var(--gold-ink);
}
.eyebrow::before { content: ""; width: 22px; height: 1px; margin-top: .65em; background: var(--gold); flex: none; }
.eyebrow--light, .cta-band .eyebrow { color: rgba(255,255,255,.86); }
.eyebrow--light::before, .cta-band .eyebrow::before { background: var(--gold-bright); }
strong { font-weight: 700; }
small { font-size: .875rem; }
@media (max-width: 559px) {
  body { font-size: 1.0625rem; }
  h1 { font-size: clamp(2rem, 8.6vw, 2.5rem); } /* 32-40px */
  .page-header--inner h1, .page-header--landing h1 { font-size: clamp(1.75rem, 7.6vw, 2.125rem); } /* 28-34px */
  h2 { font-size: clamp(1.5rem, 6.4vw, 1.75rem); } /* 24-28px */
  .lead { font-size: 1.125rem; line-height: 1.5; max-width: 34ch; }
  .eyebrow { font-size: .875rem; }
  .cta-band .eyebrow { max-width: none; } /* the full copy width: two balanced lines, not three */
}

/* 4. Layout */
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.page-body { padding-block: 24px 40px; display: flow-root; }
.page-body > * + * { margin-top: 40px; }
.page-body--landing > * + * { margin-top: 32px; }
/* CV-05 FORM FIRST: the landing (estimate) header is the h1 + helper only, so the form sits close beneath it in one
   centred column (~760px on desktop) - the form is the focus, not an empty right half. */
.layout-landing .page-header { padding: 32px 0 4px; }
.layout-landing .page-body--landing { padding-block: 10px 40px; }
@media (min-width: 700px) {
  .layout-landing .page-header > .wrap, .layout-landing .page-body--landing { max-width: 760px; }
}
main { display: block; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* Bands. 4.2 ladder: G0 paper (--surface) / G1 page (--bg) / G2 stone (--surface-2) / G3 forest (--ink-2) /
   G4 a full-bleed photograph. G0-G2 are 1.07-1.13:1 apart, so contrast comes from G3 and G4. */
.band { padding: var(--band-pt) 0 var(--band-pb); }
.band--cont { padding: var(--band-pt-sm) 0 var(--band-pb-sm); } /* S-1: continues the previous idea */
.band--surface { background: var(--surface); }
.band--bg { background: var(--bg); }
.band--stone { background: var(--surface-2); --brand-ink: #0a4d0c; --gold: #ad7a0e; } /* re-scoped to 8.96:1 / 3.35:1 - the global #0c600f is 6.91 and #b9820f 2.98 here (V4 8.1) */
.band--forest {
  background: var(--ink-2); padding: var(--band-pt-lg) 0 var(--band-pb-lg); color: #edf3e9;
  --surface: #17331d; --ink: #edf3e9; --muted: #a9bbad; --caption: #a9bbad; --line: var(--brand-soft-line);
  --brand-ink: #9ad89c; --brand-2: #c3ecc4; --gold-ink: var(--gold-bright); --gold: var(--gold-bright);
} /* 13.66 / 7.64 / 9.31 / 8.32:1, the .site-footer technique. No form control here. `color` on the BAND, not just
     h2/h3: a plain <p> inherited the light ink at 1.15:1 - measured, invisible. */
.band--forest h2, .band--forest h3, .band--forest .card__title a { color: var(--ink); }
/* 4.2 amended (V4 FIX 2): TWO forest bands when CONSECUTIVE - one dark room, seam unpadded (home OI-1 + OI-2). */
.band--forest + .band--forest { padding-top: 0; }
.band--forest:has(+ .band--forest) { padding-bottom: var(--band-pb-sm); } /* the seam INSIDE one dark room */
/* S-1: a hairline still marks a same-ground seam UNLESS the second band declares itself a continuation */
.band--surface + .band--surface:not(.band--cont), .band--bg + .band--bg:not(.band--cont),
.band--stone + .band--stone:not(.band--cont) { border-top: 1px solid var(--line); }
.band__inner > :first-child, .band__head > :first-child { margin-top: 0; }
.band__head { margin-bottom: 16px; }
.band__head > .eyebrow + h2 { margin-top: 0; }
.band__head > h2 { margin-bottom: 0; }
/* L-3 / L-5 / L-12: a heading that links its hub still reads as a heading - ink, no rule at rest, underlined on hover */
.band__head h2 a, .services__title a, .areas__title a, .projects__title a { color: inherit; text-decoration: none; }
.band__head h2 a:hover, .services__title a:hover, .areas__title a:hover, .projects__title a:hover { color: var(--brand-ink); text-decoration: underline; text-underline-offset: .12em; }
.band__head h2 a::after, .services__title a::after, .areas__title a::after, .projects__title a::after { content: "\2192"; margin-left: .35em; color: var(--gold-ink); font-weight: 400; font-size: .8em; } /* V5 residual: the REST cue - the /services hub's gold arrow (the same rule further down), so 66 linked headings read as links before hover */
.band__body > :last-child { margin-bottom: 0; }
.band:not(.band--split) .band__body > p:first-child { color: var(--muted); font-size: 1.125rem; max-width: 56ch; } /* intro line under a band heading */
.band__inner > section { margin: 0; }
/* V4 FIX 2: `.prose > section` (28px) + `.prose ul` (1.25em) re-applied under a band's own padding - 50px of dead
   ground under the last thing in almost every band (home steps: 5,713 vs 5,764). */
.band__inner > section:last-child, .band__inner > section > :last-child { margin-bottom: 0; }
.band__inner > section > :is(.services__title, .areas__title, .faq__title, .projects__title, .steps-block__title) { margin-bottom: 8px; }
.band .services__intro, .band .areas__intro, .band .faq__sub, .band .projects__intro, .band .steps-block__intro { margin: 0 0 22px; }
/* Inner-page prose bands (service + town): Markdown between section shortcodes */
.band--prose { padding: var(--band-pt-sm) 0 var(--band-pb-sm); }  /* V4 FIX: pt > pb, 4.1 */
.band--prose .prose > :first-child { margin-top: 0; }
.band--prose .prose > :last-child { margin-bottom: 0; }
.band--prose + .band--prose { border-top: 0; }
/* S-2 IS CONTINUATION, NOT ADJACENCY (V4 FIX 2). The V2-era rule flattened every ground change on the service and
   town pages (/house-wash 4-6 measured pt=0). Same-ground pairs only. */
.band--surface.band--prose + .band--surface.band--prose,
.band--bg.band--prose + .band--bg.band--prose,
.band--stone.band--prose + .band--stone.band--prose { padding-top: 0; }
.page-header + .band--prose { padding-top: 40px; }
@media (min-width: 560px) { :root { --band-pt: 48px; --band-pb: 36px; --band-pt-lg: 56px; --band-pb-lg: 48px; --band-pt-sm: 32px; --band-pb-sm: 28px; } }
@media (min-width: 900px) {
  :root { --band-pt: 56px; --band-pb: 44px; --band-pt-lg: 72px; --band-pb-lg: 60px; --band-pt-sm: 36px; --band-pb-sm: 30px; }
  /* L-1: head left (1fr), body right (1.6fr) when the head is short and the body is a list or grid. A 42px heading
     beside 18px body is where 4.6's type contrast is felt. */
  .band--split .band__inner { display: grid; grid-template-columns: 1fr 1.6fr; gap: 24px 56px; align-items: start; }
  .band--split .band__head { margin-bottom: 0; }
  /* a shortcode band holds ONE <section>: it spans both tracks and runs the split itself (else the outer grid hands
     it a 369px column and wraps the 42px heading to three lines - measured) */
  .band--split .band__inner > section { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1.6fr; column-gap: 56px; align-items: start; }
  .band--split .band__inner > section > * { grid-column: 1; }
  .band--split .band__inner > section > :is(ul, ol) { grid-column: 2; grid-row: 1 / span 20; }
  .band--split .steps { grid-template-columns: minmax(0, 1fr); } /* 3 columns in a 610px track is 190px each */
}

/* 5. Buttons - pills, >= 48px tall, em padding so they grow with the text, no lifts, no rest shadows */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: .75em 1.375em; border-radius: 999px; border: 1.5px solid transparent;
  font-weight: 600; font-size: 1rem; letter-spacing: .01em; line-height: 1.2; text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease), box-shadow .2s var(--ease);
  min-height: 3rem;
}
.btn .ico { width: 18px; height: 18px; fill: currentColor; flex: none; }
.btn--primary { background: var(--brand); color: #fff; }
.btn--primary:hover { background: var(--brand-2); color: #fff; }
.btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); } /* boundary visible at rest (3.18:1 on --bg) */
.btn--secondary:hover { border-color: var(--brand); color: var(--brand-ink); background: var(--brand-soft); }
.btn--gold { background: var(--gold-bright); color: #14201a; } /* the ONE gold-filled control: ink 9.06:1 */
.btn--gold:hover { background: #d9a33a; color: #14201a; } /* 7.39:1 */
.btn--outline-light { background: transparent; color: #fff; border-color: rgba(255,255,255,.55); }
.btn--outline-light:hover { background: rgba(255,255,255,.12); color: #fff; border-color: #fff; }
.btn--tel { background: var(--surface-2); color: var(--brand-ink); border-color: var(--line); padding: .6em .875em; min-width: 3rem; font-size: .9375rem; } /* 48 x 48 icon-only */
.btn--tel:hover { background: var(--brand-soft); }
.btn--lg { font-size: 1.0625rem; min-height: 3.25rem; padding: .8em 1.5em; }
.btn--xl { font-size: clamp(1.125rem, 3vw, 1.375rem); min-height: 3.5rem; padding: .8em 1.4em; }
.btn--xl .ico { width: 24px; height: 24px; }
.btn--block { width: 100%; }

/* 6. Header / nav - cream glass, 500 links, a gold rule under the current section */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(243,246,239,.92);
  -webkit-backdrop-filter: saturate(160%) blur(8px); backdrop-filter: saturate(160%) blur(8px);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  display: flex; align-items: center; gap: 14px; min-height: var(--header-h); flex-wrap: wrap;
  max-width: var(--wrap-header);
}
.brand { display: inline-flex; align-items: center; flex: none; }
.brand__img { width: auto; height: 80px; background: transparent; } /* renditions trimmed of ~32% baked-in padding 2026-09-06: this is the MARK, not the box */
/* 56 -> 80px where there is room (owner, 2026-09-06). NOT ON PHONES: measured at 375px only 82px is left
   after the estimate pill, call and Menu, so 56px (81px wide) is the widest mark that stays on ONE row -
   at 66px the sticky bar doubles to 143px. --header-h tracks the real bar height. */
@media (max-width: 559px) { :root { --header-h: 4.5rem; } .brand__img { height: 56px; } }
.header-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.header-actions .btn, .nav-toggle { white-space: nowrap; } /* pills never break into two lines */
/* the estimate pill is visible at every width (spec 3.1): 15px, 48px tall */
.header-cta { display: inline-flex; padding: .6em .8em; font-size: .9375rem; }
.header-cta__full { display: none; } /* the full label from 1500px, .header-cta__short below */
.btn--tel__num { display: none; } /* CV-02.2: the header phone pill is icon-only at every width; the aria-label carries the number */
.nav-toggle {
  display: inline-flex; align-items: center; gap: 8px; background: transparent; border: 1.5px solid var(--line);
  border-radius: 999px; padding: .5em .9em; font-weight: 600; font-size: .9375rem; cursor: pointer; min-height: 3rem; min-width: 3rem; justify-content: center;
}
.nav-toggle__bars { display: inline-flex; flex-direction: column; gap: 4px; width: 18px; }
.nav-toggle__bars i { display: block; height: 2px; background: var(--ink); border-radius: 2px; transition: transform .2s var(--ease), opacity .2s; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars i:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
@media (max-width: 419px) { /* icon-only Menu; the label stays in the accessible name */
  .nav-toggle { padding: .5em .8em; }
  .nav-toggle__label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
}
@media (max-width: 359px) { .header-inner { gap: 8px; } .header-actions { gap: 6px; } .btn--tel { padding: .6em .75em; } } /* one row down to 340px */
@media (max-width: 339px) { .header-cta { display: none; } } /* safety net: the drawer keeps its own full-label pill */

/* Mobile drawer (default): 17px rows, 52px tall */
.site-nav { display: none; flex-basis: 100%; padding: 6px 0 16px; }
.site-nav.is-open { display: block; }
.no-js .site-nav { display: block; } /* no JS: menu always visible */
.no-js .nav-toggle { display: none; }
.nav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.nav-item { position: relative; }
/* :not(.btn): the drawer pills keep their .btn colours */
.nav-item > a:not(.btn) {
  display: flex; align-items: center; min-height: 3.25rem; padding: .5em 12px; border-radius: var(--radius-sm); text-decoration: none; color: var(--ink);
  font-weight: 500; font-size: 1.0625rem; white-space: nowrap; transition: color .2s var(--ease);
}
.nav-item > a:not(.btn):hover { color: var(--brand-ink); }
.nav-item.is-current > a:not(.btn) { box-shadow: inset 0 -2px 0 var(--gold); color: var(--ink); } /* current page / section: a rule, not colour alone */
.nav-item > a[aria-current="page"] { color: var(--ink); }
.nav-item--cta > .btn--primary, .nav-item--cta > .btn--primary:hover { color: #fff; }
.nav-item.has-children > a { padding-right: 56px; }
.nav-sub-toggle {
  position: absolute; right: 4px; top: 4px; width: 44px; height: 44px; border: 0; border-radius: 8px;
  background: transparent; cursor: pointer; display: grid; place-items: center;
}
.nav-sub-toggle svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; transition: transform .2s var(--ease); }
.nav-sub-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
.nav-sub { list-style: none; margin: 0; padding: 2px 0 6px 14px; display: none; }
.nav-item.is-open > .nav-sub, .no-js .nav-sub { display: block; }
.nav-sub a { display: flex; align-items: center; min-height: 2.75rem; padding: .4em 12px; border-radius: 8px; text-decoration: none; color: var(--muted); font-weight: 500; font-size: .9375rem; }
.nav-sub a:hover, .nav-sub a[aria-current="page"] { color: var(--brand-ink); background: var(--surface-2); }
.nav-item--mobile-only { margin-top: 8px; }
.nav-item--tel { margin-top: 0; }
html.nav-open body { overflow: hidden; }
/* Open drawer: capped to the viewport, shadow while more is below */
html.nav-open .site-nav {
  max-height: calc(100vh - var(--header-h)); max-height: calc(100dvh - var(--header-h)); overflow: auto; overscroll-behavior: contain;
  background:
    linear-gradient(#fff 30%, rgba(255,255,255,0)) top / 100% 32px,
    linear-gradient(rgba(255,255,255,0), #fff 70%) bottom / 100% 32px,
    radial-gradient(farthest-side at 50% 0, rgba(14,32,20,.2), transparent) top / 100% 12px,
    radial-gradient(farthest-side at 50% 100%, rgba(14,32,20,.2), transparent) bottom / 100% 12px;
  background-repeat: no-repeat; background-attachment: local, local, scroll, scroll;
}

/* Desktop header tiers (drawer bp 900px = site.js `mq`): 900-1059 15px links, Home + Portal hidden (a 1366px
   laptop at 150% zoom keeps its nav); 1060+ Portal; 1140+ phone; 1280+ Home; 1500+ label. */
@media (min-width: 900px) {
  .header-inner { gap: 8px; } /* stays flex-wrap: wrap - a very large browser text setting drops the menu to a second row instead of scrolling the page sideways */
  .site-nav { display: block; flex-basis: auto; padding: 0; margin-left: 4px; }
  .nav-toggle { display: none; }
  .header-cta { padding: .6em .8em; font-size: .9375rem; }
  .btn--tel { padding: .6em .75em; }
  .nav-list { flex-direction: row; align-items: center; gap: 0; }
  .nav-item > a:not(.btn) { padding: .5em 5px; font-size: .9375rem; min-height: 2.75rem; } /* :not(.btn) = same specificity as the drawer base rule, so the tier wins (fixer 2026-09-02) */
  .nav-item.has-children > a { padding-right: 26px; }
  .nav-item--desktop-wide { display: none; }
  .nav-sub-toggle { width: 26px; height: 26px; right: 0; top: 50%; margin-top: -13px; }
  .nav-sub-toggle::before { content: ""; position: absolute; inset: -9px -5px; } /* 36x44 hit area around the 26px glyph */
  .nav-sub-toggle svg { width: 16px; height: 16px; }
  /* Dropdown: :hover / :focus-within or .is-open (site.js); ::before bridges the 6px gap */
  .nav-sub {
    display: none; position: absolute; left: 0; top: calc(100% + 6px); min-width: 240px; padding: 8px;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); z-index: 20;
  }
  .nav-sub::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 6px; } /* hover bridge = exactly the gap */
  .nav-sub a { white-space: nowrap; }
  .nav-item.has-children:not(.is-closed):hover > .nav-sub,
  .nav-item.has-children:not(.is-closed):focus-within > .nav-sub,
  .nav-item.is-open > .nav-sub { display: block; }
  .nav-item.is-open > a:not(.btn) { color: var(--brand-ink); } /* the link stays lit while its panel is open */
  .nav-item--mobile-only { display: none; }
  html.nav-open body { overflow: auto; }
}
@media (min-width: 1060px) {
  .nav-item > a:not(.btn) { padding: .5em 6px; }
  .nav-item.has-children > a { padding-right: 28px; }
  .nav-item--desktop-wide:not(.nav-item--home) { display: block; }
  .nav-sub-toggle { right: 1px; }
}
@media (min-width: 1140px) { /* CV-02.2: the phone pill is ICON-ONLY at every width (the number is in the footer, the form's call line and the
   aria-label); links keep the 1060 tier until 1280 */
  .btn--tel { padding: .6em .875em; }
}
@media (min-width: 1280px) {
  .header-inner { gap: 14px; }
  .site-nav { margin-left: 18px; }
  .header-cta { padding: .6em 1em; }
  .nav-list { gap: 2px; }
  .nav-item > a:not(.btn) { padding: .5em 12px; font-size: 1rem; }
  .nav-item.has-children > a { padding-right: 30px; }
  .nav-item--desktop-wide { display: block; }
  .nav-sub-toggle { right: 2px; }
}
@media (min-width: 1500px) {
  .nav-item > a:not(.btn) { padding: .5em 14px; }
  /* the shorthand above wipes the 1340px tier's padding-right at equal specificity, dropping the caret on the
     label (owner, 2026-09-06, >=1500px only). */
  .nav-item.has-children > a { padding-right: 30px; }
  .header-cta { padding: .6em 1.25em; }
  .header-cta__full { display: inline; }
  .header-cta__short { display: none; }
}

/* 7. Breadcrumb bar (V3 3.2 / B-5, #15): inner pages carry a plain 15px breadcrumb line above the h1; home,
   landing, legal and 404 render nothing between the site header and the page header. */
.crumb-bar { background: var(--bg); border-bottom: 1px solid var(--line); }
.crumb-bar > .wrap { padding-block: 10px; }
.breadcrumb { font-size: .9375rem; color: var(--muted); margin: 0; }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 6px; }
.breadcrumb li + li::before { content: "/"; color: var(--line-strong); margin-right: 6px; }
.breadcrumb a { color: var(--brand-ink); text-decoration: none; }
.breadcrumb a:hover { color: var(--brand-2); text-decoration: underline; }
.breadcrumb [aria-current] { color: var(--ink); font-weight: 600; }
@media (max-width: 559px) { .breadcrumb { font-size: .875rem; } }

/* The demoted call line (B-3 / CV-05.5): body size, a phone glyph, a 44px tap row, never a button. One per page. */
.form-call { margin: 14px 0 0; font-size: 1rem; color: var(--ink); }
.form-call a, .page-header__call a { display: inline-flex; align-items: center; gap: 7px; min-height: 2.75rem; font-weight: 600; color: var(--brand-ink); text-underline-offset: .18em; }
.form-call .ico, .page-header__call .ico { width: 20px; height: 20px; fill: currentColor; flex: none; }

/* 7b. PAGE HEADER (2.2 / 2.3, DECISIONS #18 + #22): eyebrow, h1, lead, CTA, call, meta, on G1. Never a photograph -
   in <main> the first rendered text is the <h1>. Replaces hero.html. */
.page-header { background: var(--bg); padding: 40px 0 24px; }
/* /thank-you header: the site's own dark room. .page-header is declared AFTER .band--forest, so its background
   wins on source order and must be re-stated; and .page-header h1 uses --ink-2, a token the forest ground does
   not remap, so the heading needs an explicit light colour or it renders near-black on near-black. */
.page-header.band--forest { background: var(--ink-2); padding: 40px 0 28px; }
.page-header.band--forest h1, .page-header.band--forest .lead, .page-header.band--forest .eyebrow { color: var(--ink); }
.page-header__inner { max-width: 62ch; }
.page-header h1 { margin: 0; color: var(--ink-2); }
.page-header h1 em { font-style: normal; color: var(--brand-deep); } /* 11.01:1 */
.page-header .eyebrow { margin-bottom: 12px; }
.page-header__lead { margin: 14px 0 0; max-width: 46ch; }
.page-header__actions { margin-top: 20px; }
.page-header__call { margin: 12px 0 0; font-size: .9375rem; color: var(--caption); } /* #33 "less visual": matched to .page-header__meta, so the demotion is type as well as position. 8.37:1, AAA. */
.page-header__meta { margin: 10px 0 0; font-size: .9375rem; line-height: 1.5; color: var(--caption); max-width: 62ch; } /* 8.37:1 */
.page-header__stars { color: var(--gold-ink); letter-spacing: 2px; }
/* #32: the BBB badge opens the header rail, above the call line (#33). 132px is 0.44x of the 300px master, so a DPR-3
   phone is still served natively; the badge is the only bitmap in the letterhead, so it gets no border and no plate. */
.page-header__badge { display: block; width: 132px; height: auto; }
/* V6: BBB + Google seal in a row. The 899px clearance is on the ROW: on the badge it would step mark 2 down 24px. */
.page-header__badges { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
/* OWNER 2026-09-06: img{background:--surface-2} at :58 showed through the CIRCULAR seal as a pale box. Opt out,
   as .brand__img already does. Opaque badges never revealed it. */
.page-header__badge img, .trust-bar__badge { background: transparent; }
.page-header__badge--seal { width: 140px; }
@media (max-width: 899px) { .page-header__badges { margin-top: 24px; } }
.page-header--inner h1 { font-size: clamp(2.125rem, 4.2vw, 3rem); } /* 34-48px */
.page-header--landing h1 { font-size: clamp(2rem, 3.9vw, 2.75rem); } /* unchanged from V3: a bigger h1 pushes the form down */
.page-header--landing .lead { font-size: clamp(1.0625rem, 1.8vw, 1.1875rem); }
.page-header--center .page-header__inner { margin-inline: auto; text-align: center; }
.page-header--center .btn-row { justify-content: center; }
.page-header--center .eyebrow { flex-direction: column; align-items: center; gap: 8px; }
.page-header--center .eyebrow::before { margin-top: 0; }
@media (min-width: 560px) { .page-header { padding: 48px 0 28px; } .page-header__lead { margin-top: 16px; } .page-header__actions { margin-top: 22px; } }
@media (min-width: 900px) { .page-header { padding: 64px 0 24px; } .page-header__lead { margin-top: 18px; } .page-header__actions { margin-top: 24px; } }
/* V4 FIX (OI-9): from 1100px a two-column letterhead - h1 + lead + CTA left, the rail right. Measure unchanged. */
@media (min-width: 1100px) {
  :is(.page-header--inner, .page-header--home) .page-header__inner { display: grid; max-width: none;
    grid-template-columns: minmax(0, 62ch) minmax(230px, 1fr); column-gap: 64px; align-items: start; }
  :is(.page-header--inner, .page-header--home) .page-header__inner > * { grid-column: 1; }
  /* V4 FIX 2 (OI-9): call + meta are ONE rail over the header's full height, ends distributed - pinned to rows 1-2
     they left 173-253px of bare ground and the gold rule 56px ABOVE the h1. */
  /* `1 / -1` collapses here - no explicit ROWS, so -1 is line 1. `span 4` = eyebrow/h1/lead/CTA; on home the 4th
     implicit row is 0 high at row-gap 0. Measured both ways. */
  :is(.page-header--inner, .page-header--home) .page-header__rail { grid-column: 2; grid-row: 1 / span 4;
    align-self: stretch; display: flex; flex-direction: column; justify-content: space-between; margin-top: 6px;
    border-top: 2px solid var(--gold); padding-top: 10px; }
  .page-header__rail .page-header__call, .page-header__rail .page-header__meta { margin: 0; }
}

/* G4 - THE LEAD FRAME (4.3 R-A). One full-bleed photograph a page, rendered OUTSIDE .wrap as a direct child of its
   section: `grid-column` needs a grid ITEM (OB-11). Never `50% - 50vw` (town-strip scroll bug). */
.band--lead { padding: 0 0 var(--band-pb-sm); }  /* a photograph IS the ground: 112px to the next heading was the ritual again */
/* The 1,500px cap and centring belong on the SECTION: on a grid item `margin-inline: auto` cancels stretch. */
.band--bleed { display: grid; max-width: 1500px; margin-inline: auto; grid-template-columns: [full-start] minmax(var(--gutter), 1fr) [wrap-start] minmax(0, 1016px) [wrap-end] minmax(var(--gutter), 1fr) [full-end]; }
.result--bleed { display: contents; }
.result--bleed .result__frames { grid-column: full; }
.result--bleed .result__caption { grid-column: full; padding-inline: var(--gutter); } /* aligned to the picture */

/* The result component (B-2, 3.3): two halves - stacked on phones, side by side from 700px - then the three-tier
   caption. No reveal, no slider. */
.result { margin: 0; }
.result__frames { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.result__half, .result__whole { position: relative; display: block; overflow: hidden; border-radius: var(--radius-sm); background: var(--surface-2); }
.result__half img { display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }
/* LF-1 (4.4). A 3:4 half in a 672px slot is 896px tall - only its top 341px cleared a 900px fold, and a landscape
   master's top is sky. From 900px the bleed halves run 13:12 low: -276px a page. */
@media (min-width: 900px) { .result--bleed .result__half img { aspect-ratio: 13 / 12; object-position: 50% 58%; } }
/* R-D2 - a LEAD PAIR: two DIFFERENT photographs in one row. No midline seam, no BEFORE/AFTER tag (the pair branch
   emits none), and the halves keep their own frame instead of the 3:4 a composite half takes (:427) or 13:12 (:430).
   The aerials are 1182x665 and 1118x629, both 1.7774 - within 0.02% of 16:9, so cover crops <0.1 native px. */
.result__frames--pair .result__half img { aspect-ratio: 16 / 9; }
.result--bleed .result__frames--pair .result__half img { aspect-ratio: 16 / 9; object-position: 50% 50%; }
/* #43 + A8: --high moves the visible window UP the source; the global 58% anchor (:430) decapitates this chapel.
   Re-measured on photo 696 (owner A8): cross top = src row 58, gable apex = row 90, and the croppable band is
   854 - (12/13)*640 = 263.2 src rows at EVERY width >= 900px, so one number holds. 30% opened at row 79 and cut
   the cross by 21px; the cross needs <= 22.03%. 15% opens at row 39.5 - 18.5px of sky above it. */
@media (min-width: 900px) { .result--bleed .result__frames--high .result__half img { object-position: 50% 15%; } }
.result__whole img { display: block; width: 100%; height: auto; }
.result__frames--split { container-type: inline-size; }
.result__caption { display: block; margin: 10px 2px 0; }
.result__object { display: block; font-size: 1rem; font-weight: 600; color: var(--ink); line-height: 1.35; }
.result__method { display: block; font-size: .9375rem; font-weight: 400; color: var(--caption); line-height: 1.4; }
.result__place { display: block; font-size: .875rem; font-weight: 500; color: var(--gold-ink); line-height: 1.4; }
@media (min-width: 700px) {
  .result__frames--split { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 559px) {
  /* caption lines 2 and 3 share a row, separated by a middot; DOM order never changes */
  .result__method { display: inline; }
  .result__place { display: inline; }
  .result__method + .result__place::before { content: " \00B7  "; color: var(--line-strong); } /* TWO spaces after the escape: the tokenizer consumes one whitespace as the escape terminator (even after six digits), so a single space computed to " (middot)" with nothing after it - measured in the browser */
}
/* R-B: one fixed interval between frames at every width */
.result + .result { margin-top: 32px; }
/* R-D2b - the two-up RESULT ROW (L4, /commercial-pressure-washing only; 4.3 R-D permits a pair row on a service
   gallery of four or more frames). TWO INDEPENDENT figure.result objects, each keeping its OWN three-tier caption -
   NOT #62's one-figure pair, because rows 1 and 3 pair different towns and one place= over two towns is false (L8).
   F2 (owner 2026-09-05, "2 sets of images sized incorrectly - FIX to match others"): every cell is ONE 3:2 box - the
   ratio six of the eight already have. At 1366 (cell 504) heights were 330.7 split / 336 whole / 189 (g9, 2.67:1) /
   672 (906, portrait); now 336 on all eight. The old "never object-fit" rail is ANSWERED, not waived: 906 left the
   rows under F3, and g9's centre 900x600 was opened at 504x336 - the whole curved wall survives in both halves.
   L7 still bites: 906 and 761 were cropped, opened and REJECTED here. NEVER object-position (:684 draws the seam at
   50%, true only while the crop is centred). >= 700px only - below it a split cell is one column and 3:2 would
   flatten each stacked half to 504x164. `aspect-ratio: auto` or :428's 3/4 wins inside a split half. */
.results-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 32px; align-items: start; }
.results-row .result + .result { margin-top: 0; }
@media (min-width: 700px) {
  .results-row { grid-template-columns: 1fr 1fr; gap: 8px; }
  .results-row .result__frames { aspect-ratio: 3 / 2; }
  .results-row .result__frames > * { height: 100%; }
  .results-row .result__frames img { height: 100%; aspect-ratio: auto; object-fit: cover; }
}

/* The plate (C-03): a photograph mounted like a print - white mat, hairline, the ONE allowed shadow */
.plate { display: block; margin: 0; background: var(--surface); padding: 12px; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.plate__media { display: block; position: relative; }
.plate img { display: block; width: 100%; height: auto; border: 0; border-radius: var(--radius-sm); }
.plate__caption { display: block; margin: 10px 2px 0; font-size: .9375rem; line-height: 1.45; color: var(--caption); max-width: 52ch; } /* 8.91:1 on white */
@media (max-width: 559px) {
  .plate { padding: 10px; }
  /* a very large browser text setting (24px root) never scrolls the page sideways: pills wrap instead of clipping */
  .btn-row .btn, .contact-list .btn { max-width: 100%; white-space: normal; text-align: center; }
  .header-actions { flex-wrap: wrap; justify-content: flex-end; }
  .cta-band__inner { grid-template-columns: minmax(0, 1fr); }
}

/* The ledger ([[ledger]], C-04): the particulars as a ruled <dl>; two columns from 700px, 48px rows */
.ledger__heading { margin-bottom: 10px; } /* an eyebrow like every other band's (.eyebrow) */
.ledger { margin: 0; border-top: 1px solid var(--line); display: grid; grid-template-columns: minmax(0, 1fr); } /* minmax(0, ...): a row's label + value can shrink into a narrow card at a 24px root */
.ledger > div { display: grid; grid-template-columns: minmax(min(7.5em, 120px), auto) minmax(0, 1fr); gap: 4px 14px; align-items: baseline; min-height: 3rem; padding: 10px 0; border-bottom: 1px solid var(--line); }
.ledger__time { white-space: nowrap; } /* "8 AM - 11 PM" is one unit; the day range wraps (nowrap overflowed the phone at a 24px root). */
.band:has(> .band__inner > .ledger-block) { padding-block: 44px; } /* home: the particulars sit close under the letter, not in an 84px band */
@media (max-width: 559px) {
  .ledger > div { grid-template-columns: minmax(min(6em, 96px), auto) minmax(0, 1fr); }
  .hours-block .ledger > div { grid-template-columns: minmax(0, 1fr); gap: 2px; } /* inside the contact card the label sits above the value: no row is ever wider than the card */
}
.ledger dt { font-size: .9375rem; font-weight: 500; color: var(--caption); }
.ledger dd { margin: 0; font-size: 1.0625rem; color: var(--ink); }
.band .ledger-block { max-width: 60ch; }
@media (min-width: 700px) {
  .ledger { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; }
  .band .ledger-block { max-width: none; }
}

/* 8. Trust bar (/thank-you; home uses the ledger) - fine-line icons, 500 labels at 15px on every width */
.trust-bar {
  list-style: none; margin: 18px 0 0; padding: 10px 6px;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 32px;
  border-bottom: 1px solid var(--line);
}
.trust-bar__item { display: inline-flex; align-items: center; gap: 8px; font-size: .9375rem; font-weight: 500; letter-spacing: .01em; color: var(--muted); padding: 6px 0; }
.trust-bar__item .ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; color: var(--brand); flex: none; }
.trust-bar__item .ico--gold { color: var(--gold-ink); }
.trust-bar__item a { color: var(--brand-ink); text-decoration: underline; text-underline-offset: .18em; display: inline-block; padding: 6px 0; } /* ~44px tap row; reads as a link at rest */
.trust-bar__item a:hover { color: var(--brand-2); }
@media (max-width: 559px) {
  .trust-bar { display: grid; grid-template-columns: 1fr 1fr; justify-items: start; gap: 2px 16px; }
  .trust-bar__item--badge, .trust-bar__item:nth-child(n+4) { grid-column: 1 / -1; } /* the badge link + the long labels own a row */
}

/* 9. Cards / services grid */
.services__title, .areas__title, .faq__title, .jobber-embed__title, .topduck__title, .steps-block__title, .hours-block__title { margin-bottom: 14px; }
.services__intro, .areas__intro, .steps-block__intro { color: var(--muted); font-size: 1.125rem; max-width: 56ch; margin-top: -6px; }
.card-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; grid-template-columns: 1fr; }
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column; position: relative;
  transition: box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.card:hover { box-shadow: var(--shadow-sm); border-color: var(--line-strong); }
.card__media { display: block; }
.card__meta { margin: -4px 0 0; font: 600 .875rem/1.3 var(--font-body); color: var(--gold-ink); } /* /locations "Photographed in {town}" - sentence case */
.town-card--text .card__body { padding-top: 24px; } /* the three towns without a local photo */
.town-card__plate { padding: 8px 8px 0; } /* /locations: the town hero as a plate inside the card (DESIGN_V2_SPEC 4.7) */
.town-card__plate img { border-radius: var(--radius-sm); }
.card__body { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.card__title { font-size: 1.1875rem; margin: 0; }
.card__title a { color: var(--ink); text-decoration: none; }
.card__title a::after { content: ""; position: absolute; inset: 0; } /* whole card clickable */
.card:hover .card__title a { color: var(--brand-ink); }
.card__text { margin: 0; color: var(--caption); font-size: 1rem; }
.card__service { position: relative; z-index: 1; margin: 0; font-size: .9375rem; }
.card__service a { color: var(--brand-ink); }
.card__more { margin-top: auto; color: var(--brand-ink); font-weight: 600; font-size: .9375rem; }
.services--compact .card__body { padding: 14px 16px; }
.services--compact .card__text { display: none; }
@media (min-width: 560px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .card-grid { grid-template-columns: repeat(3, 1fr); } }

/* Photo cards: 3:2 composite + title / blurb / arrow on a hairline card; 1/2/3 at 0/480/900px */
.services--photo .card-grid { display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; }
.card-grid__item { list-style: none; display: flex; flex: 0 1 100%; }
.photo-card {
  position: relative; display: flex; flex-direction: column; width: 100%; overflow: hidden; border-radius: var(--radius);
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); text-decoration: none;
  transition: box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.photo-card:hover { box-shadow: var(--shadow-sm); border-color: var(--line-strong); color: var(--ink); }
.photo-card__media { display: block; overflow: hidden; background: var(--brand-2); }
.photo-card__img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transition: transform .4s var(--ease); background: var(--brand-2); }
.photo-card:hover .photo-card__img { transform: scale(1.02); } /* the one allowed photographic motion */
.photo-card__body { padding: 16px 18px 18px; border-top: 1px solid var(--line); display: flex; flex-direction: column; flex: 1; }
.photo-card__title { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0; color: var(--ink-2); font-size: 1.1875rem; }
.photo-card:hover .photo-card__title { color: var(--brand-ink); }
.photo-card__arrow { width: 20px; height: 20px; flex: none; fill: none; stroke: var(--gold-ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.photo-card__text { margin: 6px 0 0; color: var(--caption); font-size: 1rem; line-height: 1.5; } /* three-sentence blurbs at 16px, not 15 */
.photo-card__line { margin: 6px 0 0; color: var(--caption); font-size: .9375rem; line-height: 1.4; } /* the one-line home tile caption (V3 C-3) */
.photo-card:focus-visible { outline-color: var(--ink); }
.services--photo-titles .card-grid { gap: 12px; }
.services--photo-titles .card-grid__item { flex-basis: calc((100% - 12px) / 2); }
.services--photo-titles .photo-card__body { padding: 10px 12px 12px; }
.services--photo-titles .photo-card__title { font-size: 1rem; line-height: 1.15; }
.services--photo-titles .photo-card__arrow { width: 18px; height: 18px; }
@media (min-width: 480px) { .card-grid__item { flex-basis: calc((100% - 20px) / 2); } }
@media (min-width: 900px) { .card-grid__item, .services--photo-titles .card-grid__item { flex-basis: calc((100% - 40px) / 3); } .services--photo-titles .card-grid__item { flex-basis: calc((100% - 24px) / 3); } }
/* L-3: like items go 4-up from 1200px - eight tiles in two rows, not three */
@media (min-width: 1200px) { .card-grid__item { flex-basis: calc((100% - 60px) / 4); } .services--photo-titles .card-grid__item { flex-basis: calc((100% - 36px) / 4); } .card-grid { grid-template-columns: repeat(4, 1fr); } }

/* "Why us" pillars (home): the drone plate left, list right from 900px; 3px gold rule */
.pillars { display: grid; gap: 26px; margin: 28px 0 32px; }
.pillars__img { aspect-ratio: 4 / 3; object-fit: cover; }
.pillars__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
.pillar { padding-left: 18px; border-left: 3px solid var(--gold); }
.pillar__title { font-size: 1.1875rem; margin: 0 0 4px; }
.pillar__text { margin: 0; color: var(--muted); font-size: 1.0625rem; }
@media (min-width: 900px) {
  .pillars { grid-template-columns: 1fr 1.25fr; gap: 44px; align-items: center; }
}
/* V5 r4: [[pillars]] breaks out of the 56ch measure (plate 203->460px). Keep `.prose >`: `.prose > div` is (0,1,1). */
@media (min-width: 1080px) { .prose > .pillars { width: 1016px; margin-inline: calc((100% - 1016px) / 2); grid-template-columns: 1fr 1fr; } }

/* Google reviews (home): pull-quotes one size up, attribution after, names as written */
.reviews__grid { display: grid; gap: 26px; margin-top: 22px; }
.reviews__img { aspect-ratio: 4 / 3; object-fit: cover; }
.reviews__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.review { display: flex; flex-direction: column; border-top: 1px solid var(--line); padding: 20px 0 6px; }
.review:first-child { border-top: 0; padding-top: 4px; }
.review__head { order: 2; margin: 10px 0 0; font-size: .9375rem; letter-spacing: .02em; color: var(--muted); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.review__stars { color: var(--gold-ink); letter-spacing: 1px; font-size: .875rem; }
.review__name { color: var(--muted); font-weight: 600; }
.band .review__quote, .review__quote { order: 1; margin: 0; padding: 0; border: 0; background: none; border-radius: 0; }
.review__quote p { margin: 0; font-family: var(--font-head); font-weight: 700; font-size: clamp(1.125rem, 2vw, 1.375rem); line-height: 1.35; letter-spacing: -.01em; color: var(--ink); }
.review__quote p::before { content: "\201C"; color: var(--gold); font-size: 1.6em; line-height: 0; margin-right: 4px; vertical-align: -.35em; }
.reviews__more { margin: 18px 0 0; font-weight: 600; }
@media (min-width: 900px) {
  .reviews__grid { grid-template-columns: 1fr 1.4fr; gap: 44px; align-items: start; }
  .reviews__media { position: sticky; top: calc(var(--header-h) + 24px); }
  /* L-4: image=false retires the sticky plate and runs the quotes two-up, so a reader judges both at once */
  .reviews__grid--quotes { grid-template-columns: minmax(0, 1fr); }
  .reviews__grid--quotes .reviews__list { grid-template-columns: 1fr 1fr; gap: 0 44px; }
  .reviews__grid--quotes .review { border-top: 0; padding-top: 4px; }
}

/* OI-1 / DECISION #16: four reasons, plain text, no plaques. 4-up from 1200px, 3-up 900-1199, 2-up from 560px. */
.band--reasons .prose--home .band__body > ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px 24px; max-width: none; }
.band--reasons .prose--home .band__body > ul > li { font-size: 1.0625rem; color: var(--muted); border-top: 2px solid var(--gold); padding-top: 12px; } /* 7.73:1 text, 3.15:1 rule */
.band--reasons .prose--home .band__body > ul > li strong { display: block; margin-bottom: 4px; font-family: var(--font-head); font-size: 1.125rem; line-height: 1.25; color: var(--ink); }
@media (min-width: 560px) { .band--reasons .prose--home .band__body > ul { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .band--reasons .prose--home .band__body > ul { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .band--reasons .prose--home .band__body > ul { grid-template-columns: repeat(4, 1fr); } }

/* Founder note (home, C-06): the story-teaser copy as a signed note at 58ch; an optional small plate */
.founder-note__grid { display: grid; gap: 28px; }
.founder-note__copy p { max-width: 58ch; font-size: 1.125rem; }
.founder-note__sig { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line); max-width: 58ch; }
.founder-note__name { display: block; font-family: var(--font-head); font-weight: 700; font-size: 1.375rem; letter-spacing: -.01em; color: var(--ink-2); }
.founder-note__role { display: block; margin: 2px 0 10px; font-size: .9375rem; color: var(--caption); }
.founder-note__tel { display: inline-flex; align-items: center; min-height: 2.75rem; font-weight: 600; text-underline-offset: .18em; } /* a 44px tap target */
.founder-note__actions { margin: 16px 0 0; }
.founder-note__plate { width: min(100%, 470px); max-width: 470px; } /* #30 / #72: 470px plate = a 444px photograph inside .plate's 12px mat + 1px hairline (the 440-480 target; the 779px master caps an honest render at 677). P7: a definite width - as a shrink-to-fit grid item the lazy img had no box before load (+223px CLS) */
@media (min-width: 900px) { .founder-note--image .founder-note__grid { grid-template-columns: minmax(0, 1fr) 470px; gap: 40px; align-items: start; } .founder-note__plate { justify-self: end; } }

/* Town strip ([[town-strip]], home, C-07): nine plate links - a scroll-snap row on phones, a 3 x 3 grid from 900px */
.town-strip__title { margin-bottom: 22px; }
.town-strip__intro { color: var(--muted); font-size: 1.125rem; max-width: 56ch; margin: -8px 0 22px; }
.town-strip__list { list-style: none; margin: 0 calc(-1 * var(--gutter)); padding: 4px var(--gutter) 14px; display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); -webkit-overflow-scrolling: touch; }
.town-strip__list > li { flex: 0 0 260px; scroll-snap-align: start; display: flex; }
.town-strip__link { position: relative; width: 100%; text-decoration: none; color: inherit; } /* position: relative = the containing block for the visually-hidden span inside the overflow-x scroller; without it the body scrolled sideways ~2,000px on phones (fixer 2026-09-02) */
.town-strip__link img { aspect-ratio: 3 / 2; object-fit: cover; }
.town-strip__name { display: block; margin: 10px 2px 0; font-family: var(--font-head); font-weight: 700; font-size: 1.0625rem; line-height: 1.2; color: var(--ink-2); }
.town-strip__link:hover .town-strip__name { color: var(--brand-ink); }
.town-strip__link .plate__caption { margin-top: 2px; }
@media (min-width: 900px) {
  .town-strip__list { margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; overflow: visible; }
  .town-strip__list > li { flex: none; }
}

/* 10. Chips / areas served */
.chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; min-height: 2.75rem; padding: .5em .9em; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink); text-decoration: none;
  font-weight: 600; font-size: .9375rem; transition: border-color .2s, background-color .2s, color .2s;
}
.chip:hover { border-color: var(--brand); background: var(--brand-soft); color: var(--brand-ink); }
.areas__note { margin: 14px 0 0; color: var(--muted); font-size: 1rem; max-width: 52ch; }
.areas__actions { margin-top: 18px; }
/* Areas grid: inner pages = ruled list; home (.areas--blurbs) = card per town; 1/2/3 at 0/480/900px. Town names are
   underlined (hairline colour, hover brand) so they read as links in the check list (T-06) */
.areas-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 0 24px; grid-template-columns: minmax(0, 1fr); } /* minmax(0, 1fr) at every tier: a long town name at a 24px root wraps instead of widening the page */
.areas-grid__item { display: grid; grid-template-columns: 22px 1fr; gap: 10px; align-items: start; padding: 10px 0; border-top: 1px solid var(--line); }
.areas-grid__check { width: 22px; height: 22px; fill: none; stroke: var(--brand); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; margin-top: 2px; }
.areas-grid__link { font-family: var(--font-head); font-weight: 700; font-size: 1.0625rem; color: var(--ink); text-decoration: underline; text-decoration-color: var(--line-strong); text-decoration-thickness: 1px; text-underline-offset: .18em; }
.areas-grid__link:hover { color: var(--brand-ink); text-decoration-color: var(--brand-ink); }
.areas-grid__text { margin: 2px 0 0; color: var(--caption); font-size: 1rem; }
.areas--blurbs .areas-grid { gap: 12px 20px; }
.areas--blurbs .areas-grid__item { padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.areas--blurbs .areas-grid__link { font-size: 1.125rem; }
@media (max-width: 479px) { .areas--blurbs .areas-grid { gap: 6px; } .areas--blurbs .areas-grid__item { padding: 8px 10px; } }
@media (min-width: 480px) { .areas-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .areas-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* 11. Composites (.figure--composite = midline seam + two labels), galleries, figures - all plates (section 7) */
figure { margin: 0; }
figcaption { font-size: .9375rem; color: var(--caption); margin-top: 10px; max-width: 52ch; }
.figure--composite { position: relative; display: block; container-type: inline-size; }
.figure--composite::before { content: ""; position: absolute; inset: 0 auto 0 50%; width: 2px; transform: translateX(-1px); background: var(--bg); opacity: .95; z-index: 1; pointer-events: none; }
/* BEFORE / AFTER: the one tracked one-word caps run on the site (aria-hidden; the alt says it) */
.figure__tag {
  position: absolute; left: 10px; bottom: 10px; z-index: 1; pointer-events: none;
  font: 600 .8125rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase; padding: 6px 10px; border-radius: 4px;
  background: rgba(20,32,26,.78); color: #fff; /* 8.21:1 worst case over a white photo */
}
.figure__tag::before { content: "Before"; }
.figure__tag--after::before { content: "After"; }
.figure__tag--after { left: auto; right: 10px; }
.figure__tag--after-left { left: 10px; right: auto; } /* the two-file [[before-after]] cells label each plate at its left */
@container (max-width: 239px) { .figure__tag { font-size: .75rem; padding: 5px 7px; } } /* 2-up phone tiles */
@media (max-width: 479px) { .services--photo-titles .figure__tag { display: none; } } /* too small to read; the title carries it */
/* [[image: wide=true]] (the /services figures): the figure bleeds to the content column and the mat sits on the media so it centres on the page */
.figure--wide { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); padding: 0 var(--gutter); background: none; border: 0; box-shadow: none; border-radius: 0; }
.figure--wide .plate__media { max-width: 760px; margin: 0 auto; padding: 12px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.figure--wide .figure__tag { bottom: 22px; left: 22px; }
.figure--wide .figure__tag--after { left: auto; right: 22px; }
.figure--wide .figure--composite::before { inset: 12px auto 12px 50%; }
.figure--wide .plate__caption { max-width: 760px; margin-inline: auto; padding-inline: 14px; }
.prose > .figure--portrait, .figure--portrait { width: min(100%, 480px); max-width: 480px; margin-inline: auto; } /* [[image: portrait=true]]: 3:4, uncropped, centred; definite width = no CLS before the lazy file lands (P7) */
.figure--portrait .plate__caption { text-align: center; margin-inline: auto; }
/* V5 P4 (6), 2026-09-05: inside a service prose band the (0,3,1) span rule (.band--prose > .wrap > .prose >
   :is(section, figure, aside, div) { max-width: none }) outranked the 480px cap above (0,2,0) - computed max-width "none"
   on both /driveway-pressure-washing portraits; only the srcset sizes held the 480 render. (0,4,0) makes the cap real, and
   caps the one plain plate in a prose band ([[image: portrait=false]], the 725px brick-home master) at its 1.15x honesty
   ceiling: 725 x 1.15 = 833px, instead of the 990px the span rule gave it at 1366. */
.band--prose > .wrap > .prose > .figure--portrait { max-width: 480px; }
.band--prose > .wrap > .prose > .figure.plate:not(.figure--wide, .figure--portrait) { width: min(100%, 676px); max-width: 833px; margin-inline: auto; } /* P7: 676 = the 650px sizes hint + 26px mat (its loaded width); definite so the box exists before load */
.card__media img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }

/* 12. FAQ accordion - a ruled list on --line-strong rules (3.18:1), 18px questions, 56px rows, the whole row the target */
.faq__list { display: flex; flex-direction: column; gap: 0; }
.faq__item { border-top: 1px solid var(--line-strong); }
.faq__item:last-child { border-bottom: 1px solid var(--line-strong); }
.faq__q {
  position: relative; display: flex; align-items: center; min-height: 3.5rem; cursor: pointer;
  padding: 1rem 2.75rem 1rem .25rem; font-family: var(--font-head); font-weight: 700; font-size: 1.125rem; line-height: 1.3; list-style: none;
  transition: color .2s var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover, .faq__item[open] .faq__q { color: var(--brand-ink); }
.faq__chev { position: absolute; right: .25rem; top: 50%; width: 22px; height: 22px; margin-top: -11px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s var(--ease); }
.faq__item[open] .faq__chev { transform: rotate(180deg); }
.faq__a { padding: 0 .25rem 1.25rem; color: var(--ink); font-size: 1.125rem; max-width: 60ch; }
.faq__a > :last-child { margin-bottom: 0; }
.faq__sub { color: var(--muted); max-width: 56ch; margin-top: -6px; }
.faq__q:focus-visible { border-radius: 6px; }
/* Band FAQ from 900px: eyebrow + h2 + sub-line (+ the aside plate) left, the list right */
@media (min-width: 900px) {
  .band .faq { display: grid; grid-template-columns: 1fr 1.7fr; grid-template-rows: auto auto auto 1fr; gap: 0 56px; align-items: start; align-content: start; }
  .band .faq > .eyebrow { grid-column: 1; grid-row: 1; justify-self: start; }
  .band .faq > .faq__title { grid-column: 1; grid-row: 2; }
  .band .faq > .faq__sub { grid-column: 1; grid-row: 3; }
  .band .faq > .faq__list { grid-column: 2; grid-row: 1 / span 4; }
}
@media (max-width: 559px) { .faq__a { font-size: 1.0625rem; } }

/* 13. CTA band + inline CTA */
.cta-band {
  background: linear-gradient(180deg, var(--brand-deep), var(--brand-2));
  color: #fff; padding: var(--band-pt-lg) 0 var(--band-pb-lg);
}
.cta-band__inner { display: grid; gap: 24px; align-items: center; }
.cta-band h2 { color: #fff; margin-bottom: 10px; max-width: 22ch; }
.cta-band__text { color: rgba(255,255,255,.86); max-width: 60ch; margin: 0; font-size: 1.125rem; }
/* F1 (owner 2026-09-05, "green on green ... keep green background - change text for backlink"): the ONE dark
   ground that never re-scoped the link tokens, so a link took :60's light --brand-ink #0c600f = 1.54:1 top /
   1.30:1 bottom, and :62's a:hover resolved to --brand-2, the gradient's OWN bottom stop = 1.00:1. Now
   9.23/8.52/7.75 rest, 10.65/9.83/8.94 hover - AAA at every stop. Ground untouched. The underline survives
   and is the SC 1.4.1 distinguisher (body copy composites to #dde6dd; no colour is both readable and 3:1
   from it). ON __copy, NEVER .cta-band - there --brand-2 is the gradient's 2nd stop and would bleach it. */
.cta-band__copy { --brand-ink: #c3ecc4; --brand-2: #edf3e9; }
@media (min-width: 900px) { .cta-band__inner { grid-template-columns: 1.4fr 1fr; } .cta-band .btn-row { justify-content: flex-end; } }
/* Inline CTA ([[cta]]): a ruled pause in the prose, not a box */
.cta-inline { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 24px 0; margin: 36px 0; }
.cta-inline__title { font-size: 1.25rem; margin-bottom: 6px; }
.cta-inline p { color: var(--muted); font-size: 1.0625rem; max-width: 60ch; }
.cta-inline--lead .btn--primary .ico { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } /* the button jumps to the on-page form */

/* 14. Embeds: Jobber / TOP DUCK / video / project cards */
.jobber-embed, .topduck { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; }
.jobber-embed__title,
/* T-4/4.6: a --cont section is the same room as the one above, so its heading drops one step - every shortcode
   title, not just .band__head (V4 FIX 2: two 42px h2 landed on the same forest ground). Tag stays <h2>. */
.band--cont :is(.band__head h2, .projects__title, .faq__title, .reviews__title, .services__title, .areas__title, .steps-block__title) { font-size: clamp(1.5rem, 2.6vw, 1.875rem); }
.jobber-embed__helper { margin: 0 0 16px; font-size: 1.25rem; line-height: 1.4; color: var(--ink); font-weight: 500; max-width: 46ch; } /* B-4 / CV-05.3: the large-print line above the frame (>= 20px per spec section 4) - facts only */
.topduck__fallback, .jobber-embed__fallback { color: var(--muted); font-size: 1rem; max-width: 52ch; }
/* V3 CV-05.3: the framing above the frame is gone; the chips reuse the tick. */
.check-list li { position: relative; padding-left: 26px; }
.check-list li::before { content: ""; position: absolute; left: 0; top: .25em; width: 18px; height: 18px; background: var(--tick) center / 18px no-repeat; }
/* The iframe branch of jobber-form.html (site.yaml jobber.embed_form: true; today it is false and the link-out
   branch ships). There is NO height reserve any more: Jobber's multi-step Form pages make a step ~1000px, the old
   3,600px reserve left ~2,600px empty, so the frame takes only the height Jobber posts (site.js) - min-height 0. */
.jobber-embed__frame { background: var(--surface-2); border-radius: var(--radius-sm); overflow: hidden; min-height: 0; }
.topduck__frame { background: var(--surface-2); border-radius: var(--radius-sm); overflow: hidden; min-height: 320px; }
.jobber-embed__frame iframe, .topduck__frame iframe { width: 100%; display: block; }
/* CV-05.3: the compact "good to know" line under the frame (same-day / no-need-to-be-home / callback promise) */
.jobber-embed__go { margin: 0 0 4px; } .jobber-embed__go .btn { width: 100%; max-width: 26rem; }
.jobber-embed__chips { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: .9375rem; color: var(--muted); }
.jobber-embed__chips li { position: relative; padding-left: 22px; }
.jobber-embed__chips li::before { content: ""; position: absolute; left: 0; top: .2em; width: 16px; height: 16px; background: var(--tick) center / 16px no-repeat; }
.jobber-embed__fallback { margin: 12px 0 0; }
.jobber-embed__noscript { padding: 24px; text-align: center; }
@media (min-width:1000px){.jobber-embed__media{float:right;width:340px;margin:0 0 16px 32px}}
/* phones: the card bleeds to 8px from the screen edge and keeps 8px of its own padding, so the frame gets 326px of
   form at 360 and 356 at 390 (measured 2026-09-02; the 12px-padding version gave 290) */
@media (max-width: 559px) { .jobber-embed, .prose > .jobber-embed { margin-inline: calc(8px - var(--gutter)); padding: 14px 8px; } }
.topduck { padding: 12px; }
.topduck__title { padding: 8px 10px 0; }
.topduck__fallback { margin: 10px 10px 4px; }
/* desktop-only TOP DUCK gallery: site.js sets the src at >= 900px */
.topduck--desktop { border: 1px solid var(--line); margin-top: 32px; }
.topduck--desktop .topduck__frame { border: 1px solid var(--line); }
.topduck__caption { margin: 12px 10px 2px; text-align: center; font-weight: 600; color: var(--brand-ink); font-size: .9375rem; }

/* TOP DUCK project cards: 1 / 2 / 3 columns at 0 / 560 / 900px; the city links to its town page (served towns only) */
.projects__title { margin-bottom: 14px; }
.projects__intro { color: var(--muted); font-size: 1.125rem; max-width: 56ch; margin-top: -6px; }
.projects__grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; grid-template-columns: 1fr; }
.project-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column; position: relative;
  transition: box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.project-card:hover { box-shadow: var(--shadow-sm); border-color: var(--line-strong); }
.project-card__media { display: block; }
/* OWNER 2026-09-06: whole photo, no crop. 3/2+cover cut ~50% off the 4 cards with 3:4 sources (4 of 18 -> 0). */
.project-card__img { width: 100%; height: auto; }
/* Portrait TOP DUCK job photos in the 3:2 card used to keep the TOP, which cropped to sky: in these photographs
   the sky is above and the WORK is in the lower half. Owner spotted it on /recent-projects 2026-09-04 - three
   cards showed sky, a roofline, or a shop sign instead of the job. They now use the default centre crop. */
.project-card__body { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.project-card__pill { align-self: flex-start; font: 600 .875rem/1.3 var(--font-body); color: var(--gold-ink); } /* the service label, sentence case */
a.project-card__pill { position: relative; z-index: 1; text-decoration: underline; text-underline-offset: .18em; } /* L-5: above the card's stretched link */
a.project-card__pill:hover { color: var(--brand-ink); }
.project-card__title { font-size: 1.125rem; margin: 0; line-height: 1.2; }
.project-card__title a { color: var(--ink); text-decoration: none; }
.project-card__title a::after { content: ""; position: absolute; inset: 0; } /* whole card clickable */
.project-card:hover .project-card__title a { color: var(--brand-ink); }
.project-card__meta { margin: 0; color: var(--caption); font-size: .9375rem; font-weight: 500; }
.project-card__meta a { position: relative; z-index: 1; color: var(--brand-ink); text-underline-offset: .18em; } /* above the card's stretched link */
.project-card__text { margin: 0; color: var(--caption); font-size: 1rem; }
.projects__empty { color: var(--muted); }
.projects__actions { margin-top: 22px; justify-content: center; }
.projects__actions .btn { width: 100%; }
@media (min-width: 560px) { .projects__grid { grid-template-columns: repeat(2, 1fr); } .projects__actions .btn { width: auto; } }
@media (min-width: 900px) { .projects__grid { grid-template-columns: repeat(3, 1fr); } }
.video-figure { margin: 24px 0; }
.video { width: 100%; border-radius: var(--radius); background: #000; }
.video-figure--portrait .video { max-width: 420px; margin: 0 auto; } /* phone-shot 9:16 clips: never the full column width */

/* 15. Landing: the call block (one column at every width - the ledger under the form replaced the sticky aside, C-14) */
.call-block { text-align: center; }
.call-block__note { margin: 10px auto 0; color: var(--muted); font-size: 1rem; max-width: 52ch; }
/* the landing prose runs the full 1016px column so the call button, the Jobber card, the ledger and the grids span it; sentences stay at 60ch */
.page-body--landing .prose { max-width: none; }
.page-body--landing .prose > :is(p, h2, h3, ul, ol, blockquote, .figure, .cta-inline) { max-width: 60ch; }

/* 16. Hours / contact / lists / steps */
.hours-block { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; }
.hours-block__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px; } /* minmax(0, 1fr): the e-mail link breaks at a 24px root instead of widening the card */
.hours-block__sub { font-size: 1.0625rem; margin-bottom: 8px; }
.hours-block .ledger { grid-template-columns: minmax(0, 1fr); } /* the card sits in the 60ch column: one ledger column under the contact row */
.contact-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 22px; }
.contact-list li { padding: 4px 0; min-width: 0; max-width: 100%; }
/* The Patty's Way standard ([[standard]], C-05): a ruled check list of sentences already on the site; three small crew plates beside it from 900px */
.standard__title { margin-bottom: 14px; }
.standard__grid { display: grid; gap: 28px; }
.standard__list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); max-width: 60ch; }
.standard__list li { position: relative; padding: 12px 0 12px 30px; border-bottom: 1px solid var(--line); font-size: 1.0625rem; color: var(--ink); }
.standard__list li::before { content: ""; position: absolute; left: 0; top: .95em; width: 18px; height: 18px; background: var(--tick) center / 18px no-repeat; }
.standard__plates { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; align-content: start; }
.standard__plates img { aspect-ratio: 4 / 3; object-fit: cover; }
@media (max-width: 559px) { .standard__plates { gap: 8px; } .standard__plates .plate--sm { padding: 5px; } } /* a compact 3-across row on phones */
@media (min-width: 900px) {
  .standard__grid--aside { grid-template-columns: 1.4fr 1fr; gap: 56px; align-items: start; }
  .standard__plates { grid-template-columns: 1fr 1fr; gap: 16px; }
  .standard__plates > li:first-child { grid-column: 1 / -1; }
}
.check-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px 18px; grid-template-columns: 1fr; }
@media (min-width: 560px) { .check-list { grid-template-columns: repeat(var(--cols, 2), 1fr); } }
/* Steps: a ruled list, gold numeral chip (18px bold on --gold-soft, 6.55:1 large); 3-up from 760px */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: s; display: grid; gap: 0 24px; }
.step { display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: start; border-top: 1px solid var(--line); padding: 16px 0; }
.step::before {
  counter-increment: s; content: counter(s); font-family: var(--font-head); font-weight: 700; font-size: 1.125rem;
  width: 2.25rem; height: 2.25rem; display: grid; place-items: center; border-radius: 10px; background: var(--gold-soft); color: var(--gold-ink);
}
.step h3 { font-size: 1.1875rem; margin: 4px 0 4px; }
.step p { margin: 0; color: var(--ink); font-size: 1.0625rem; }
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); } }

/* 17. Prose (Markdown body) - 60ch measure everywhere (~76 characters), nothing on the site over 70ch */
.prose { max-width: 60ch; }
.prose--wide, .prose--home { max-width: none; }
.prose--wide > p, .prose--wide > ul, .prose--wide > ol, .prose--home .band__body > p, .prose--home .band__body > ul { max-width: 60ch; }
.band__inner { max-width: var(--wrap); } /* the band wrapper is .prose--home too: 1060px column, paragraphs capped above */
.prose--legal { max-width: 60ch; overflow-wrap: anywhere; } /* the long e-mail / profile strings in the legal copy break at a 24px root */
/* content_align: center (/our-story): a centred 56ch column */
.prose--center { max-width: 56ch; margin-inline: auto; }
.prose--center > h2, .prose--center > h3, .prose--center > p, .prose--center > figure, .prose--center > figure figcaption, .prose--center > blockquote { text-align: center; }
.prose--center > figure img, .prose--center > figure figcaption { margin-inline: auto; }
.prose--center > section > :is(h2, .eyebrow) { display: flex; justify-content: center; text-align: center; } /* the ledger / standard headings on /our-story */
.prose--center .ledger { grid-template-columns: 1fr; }
.prose > h2 { margin-top: 1.6em; }
.prose > h3 { margin-top: 1.3em; }
.prose > h2:first-child, .prose > h3:first-child { margin-top: 0; }
.prose p, .prose ul, .prose ol { margin-bottom: 1.25em; }
.prose li + li { margin-top: .55em; }
.prose :is(.check-list, .card-grid, .projects__grid, .steps, .reviews__list, .standard__plates, .chip-list,
  .areas-grid, .jobber-embed__chips, .town-strip__list, .contact-list, .pillars__list,
  .band--reasons .band__body > ul) > li + li { margin-top: 0; }
/* ^ V4 FIX 2: grids and ruled lists keep their own gap. Written for stacked prose, this .55em staggered items 2..n
   of five grids by 10px on 26 pages. */
.prose img { border-radius: var(--radius-sm); }
.prose blockquote { margin: 1.4em 0; padding: 14px 20px; border-left: 4px solid var(--gold); background: var(--surface); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--muted); }
.prose blockquote p:last-child { margin: 0; }
.prose > section, .prose > figure, .prose > aside, .prose > div { margin: 28px 0; }
/* Pull-quotes: /our-story mission line + the /free-estimate quote */
.prose--center blockquote, .layout-landing .prose > blockquote { position: relative; margin: 1.6em 0; padding: 24px 0 8px; border: 0; background: none; border-radius: 0; color: var(--ink); }
.prose--center blockquote::before, .layout-landing .prose > blockquote::before { content: ""; position: absolute; top: 0; left: 0; width: 40px; height: 2px; background: var(--gold); }
.prose--center blockquote::before { left: 50%; margin-left: -20px; }
.prose--center blockquote p, .layout-landing .prose > blockquote > p:first-child { font-family: var(--font-head); font-weight: 700; font-size: clamp(1.25rem, 2.6vw, 1.625rem); line-height: 1.3; letter-spacing: -.01em; }
.layout-landing .prose > blockquote > p + p { margin: 0; font-size: .9375rem; font-family: var(--font-body); font-weight: 500; letter-spacing: .02em; color: var(--muted); } /* the attribution, sentence case */
.prose--center > p > em:only-child { color: var(--muted); } /* the signature line */
/* /services hub (spec 3.18): ink headings + gold arrow; "Learn More" links as pills */
.layout-article .prose > h2 > a { color: var(--ink-2); text-decoration: none; }
.layout-article .prose > h2 > a::after { content: "\2192"; margin-left: .35em; color: var(--gold-ink); font-weight: 400; font-size: .8em; }
.layout-article .prose > h2 > a:hover { color: var(--brand-ink); }
.layout-article .page-body .prose > p > a:only-child[href^="/"] { display: inline-flex; align-items: center; min-height: 3rem; padding: .6em 1.1em; border: 1px solid var(--line-strong); border-radius: 999px; text-decoration: none; font-weight: 600; font-size: 1rem; transition: border-color .2s, color .2s; }
.layout-article .page-body .prose > p > a:only-child[href^="/"]:hover { border-color: var(--brand); }
/* Two-column prose on service / town bands from 1000px (spec 3.17): h2 left, copy right at 58ch */
@media (min-width: 1000px) {
  .band--prose > .wrap > .prose { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr); column-gap: 56px; align-items: start; }
  /* not sticky: sibling h2s stacked on scroll */
  .band--prose > .wrap > .prose > h2 { grid-column: 1; margin-top: 0; font-size: clamp(1.5rem, 2.6vw, 1.875rem); }
  .band--prose > .wrap > .prose > :not(h2) { grid-column: 2; max-width: 58ch; }
  /* lead paragraphs before the first h2 (towns) span both columns at the 60ch measure */
  .band--prose > .wrap > .prose > :not(h2, h2 ~ *) { grid-column: 1 / -1; max-width: 60ch; }
  .band--prose > .wrap > .prose > :not(h2 ~ *):has(+ h2) { margin-bottom: 28px; }
  .band--prose > .wrap > .prose > :is(section, figure, aside, div) { grid-column: 1 / -1; max-width: none; }
  /* V5 F3 (owner mark 2026-09-05, "BAKERY HERE"): [[image: aside=true]] parks a plate in the EMPTY left
     column of a two-column prose band, beside the h3 stack - the `grid-row: N / span 20` idiom from :193.
     The h2 holds row 1 col 1 and the first h3 is already in col 2, so row 2 is the top of the void. The span
     is deliberately generous so an editor adding or removing an h3 does not strip the placement. */
  .band--prose > .wrap > .prose > .figure--aside { grid-column: 1; grid-row: 2 / span 20; }
  /* #53: /our-story is the site's one centred page (content_align: center -> .prose--center, build.py:725). The
     two-column stagger centres its h2s and its paragraphs on different axes - 523.7px apart at 1366. Revert to one
     centred 56ch measure here; the grid-column declarations above go inert with no grid parent. */
  .band--prose > .wrap > .prose--center { display: block; max-width: 56ch; margin-inline: auto; }
}
.legal-updated { color: var(--muted); font-size: 1rem; }
.legal-contact { margin-top: 2em; padding-top: 1em; border-top: 1px solid var(--line); color: var(--muted); font-size: 1rem; }

/* 18. Footer - dark; tokens re-scoped on .site-footer (ink 13.66:1, muted 7.64:1, links 9.31:1) */
.site-footer {
  --surface: var(--ink-2); --surface-2: #17331d; --ink: #edf3e9; --muted: #a9bbad; --line: var(--brand-soft-line);
  --brand-ink: #9ad89c; --brand-2: #c3ecc4; --brand: #2a9631; --brand-soft: #1f4a26; --gold: var(--gold-bright);
  border-top: 2px solid var(--gold-bright); background: var(--surface); color: var(--ink); padding: 48px 0 28px; margin-top: 0; font-size: .9375rem;
}
.site-footer :focus-visible { outline-color: #fff; box-shadow: 0 0 0 2px var(--ink-2); }
.site-footer .brand__img { background: #fff; border-radius: 14px; padding: 8px; height: 60px; } /* the logo is drawn for a light ground */
.site-footer a { color: var(--brand-ink); }
.site-footer a:hover { color: var(--brand-2); }
.footer-grid { display: grid; gap: 30px; grid-template-columns: 1fr; }
.footer-nap { font-style: normal; line-height: 1.7; margin-bottom: 10px; font-size: 1rem; overflow-wrap: anywhere; } /* the email address breaks at a 24px root instead of scrolling the page sideways */
.footer-nap a[href^="tel:"] { font-family: var(--font-head); font-weight: 700; font-size: 1.25rem; }
.footer-legal-line { font-weight: 600; color: var(--brand-ink); font-size: .875rem; letter-spacing: .02em; }
.footer-heading { font: 600 .875rem/1.3 var(--font-body); color: var(--muted); padding-bottom: 10px; border-bottom: 1px solid var(--line); margin: 0 0 12px; } /* sentence case */
.footer-links { list-style: none; margin: 0; padding: 0; }
.footer-links li { padding: 0; }
.footer-links a { color: var(--ink); text-decoration: none; display: flex; align-items: center; min-height: 2.75rem; padding: .3em 0; font-size: .9375rem; } /* 44px rows, no shared edges between targets */
.footer-links a:hover { color: var(--brand-ink); text-decoration: underline; }
.footer-links--2col { columns: 2 10em; column-gap: 18px; } /* two columns only while each is >= 10em: a 24px root gets one column instead of sideways scroll */
.footer-links--2col li { break-inside: avoid; }
.footer-links--2col a { white-space: nowrap; } /* town names never split */
.social-list__text { font-family: var(--font-head); font-weight: 700; font-size: .875rem; letter-spacing: .02em; line-height: 1; } /* "BBB" text mark (aria-hidden; the link's label names it) */
.social-list { list-style: none; margin: 14px 0 0; padding: 0; display: flex; gap: 8px; }
.social-list a {
  display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  background: transparent; border: 1px solid var(--line); color: var(--ink);
}
.social-list a:hover { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand); }
.social-list .ico { width: 20px; height: 20px; fill: currentColor; }
.footer-bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--line); color: var(--muted); font-size: .875rem; }
.footer-bottom p { margin: 0; }
@media (max-width: 699px) { .footer-col--contact { order: -1; } } /* phones: the contact column first */
@media (min-width: 700px) { .footer-grid { grid-template-columns: 1fr 1fr; gap: 34px 40px; } } /* tablets: 2 x 2 */
@media (min-width: 960px) { .footer-grid { grid-template-columns: 1.2fr 1.5fr 1fr 1.15fr; gap: 30px; } } /* Services | Areas (2 cols) | Company | Contact */

.footer-brand { display: flex; align-items: center; gap: 16px; margin-bottom: 26px; }
.footer-brand .brand__img { margin: 0; }
.footer-tagline { margin: 0 0 2px; font-size: 1rem; }
@media (max-width: 559px) { .footer-tagline__sep { display: none; } .footer-tagline__text { display: block; } } /* no dangling middot at a line start */
.footer-hours { margin: 10px 0 12px; color: var(--muted); max-width: 300px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px; }
.footer-hours div { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 7px 0; border-bottom: 1px solid var(--line); }
.footer-hours dt { font-weight: 700; color: var(--ink); }
.footer-hours dd { margin: 0; }
.footer-reviews { margin: 0 0 6px; font-size: .9375rem; }
.footer-reviews span[aria-hidden] { color: var(--gold); }
.footer-legal-links { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.footer-legal-links a { color: var(--muted); display: inline-block; padding: 6px 0; }
.trust-bar__badge { width: auto; height: 22px; background: transparent; }

/* 19. Utilities */
.ico { width: 1em; height: 1em; }

/* (Dark mode - former section 20 - removed 2026-09-02, docs/DESIGN_V2_SPEC.md 2.6; restore from commit 6941025.) */

/* 20. Reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
  .photo-card:hover .photo-card__img { transform: none; }
}

/* 21. Print */
@media print {
  :root { --bg: #fff; --surface: #fff; --surface-2: #fff; --shadow: none; --shadow-sm: none; }
  .site-header, .nav-toggle, .cta-band, .jobber-embed, .topduck, .skip-link, .to-top, .page-header__actions, .social-list, .draft-banner { display: none !important; }
  body { font-size: 12pt; color: #000; }
  a { color: #000; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 90%; color: #444; }
  a[href^="tel:"]::after, a[href^="mailto:"]::after { content: none; }
  .card, .faq__item, .hours-block, .project-card, .photo-card, .plate { border: 1px solid #999; box-shadow: none; break-inside: avoid; }
  .crumb-bar { background: none; border-bottom: 1px solid #999; }
  .breadcrumb, .breadcrumb a, .breadcrumb [aria-current] { color: #000; }
  .ledger > div { break-inside: avoid; }
  .faq__item { display: block; } .faq__a { display: block !important; }
  details > summary { list-style: none; }
  .page-header { background: none; padding: 0 0 12pt; }
  .page-header h1, .page-header h1 em { color: #000; }
  .band, .band--forest { background: none; color: #000; padding: 12pt 0; }
  .photo-card { aspect-ratio: auto; background: none; color: #000; }
  .photo-card__img { display: none; }
  .photo-card__body { position: static; padding: 6pt 0; background: none; border: 0; }
  .site-footer { --surface: #fff; --ink: #000; --muted: #444; --brand-ink: #000; border-top: 1px solid #999; }
  img { max-width: 60%; }
}
