/* ==========================================================================
   Georgian Bay Cleaners - site.css
   Brand inherited from the July 2026 brand kit.
   See DESIGN.md in ..\georgian-bay-cleaners-private\build-docs\ (moved out of
   this folder 26 Aug 2026, because everything in here gets published).
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */
:root {
  /* Palette (fixed, from the delivered brand kit) */
  --navy:        #0B2848;
  --navy-deep:   #071B31;
  --paper:       #F3EDEB;
  --paper-warm:  #EAE1DD;
  --white:       #FFFFFF;
  --grey:        #6A6E77;   /* large text + labels ONLY - 4.3:1 on paper */
  --hairline:    #CDD0D6;

  /* Derived, contrast-safe text colours */
  --ink:         var(--navy);
  --ink-soft:    rgba(11, 40, 72, 0.84);  /* body on paper - clears 4.5:1 */
  /* Secondary text. Measured at 0.62 alpha this was 4.19:1 on paper and failed
     AA wherever it landed on small text, which in practice was most places it
     was used. Raised until it clears 4.5:1 so it is safe at any size. */
  --ink-faint:   rgba(11, 40, 72, 0.72);
  --on-navy:     #F3EDEB;
  --on-navy-soft: rgba(243, 237, 235, 0.80);
  --rule:        rgba(11, 40, 72, 0.16);
  --rule-navy:   rgba(243, 237, 235, 0.22);

  /* Type */
  --display: "EB Garamond", "Iowan Old Style", Georgia, serif;
  --ui: "Hanken Grotesk", "Segoe UI", system-ui, -apple-system, sans-serif;

  --step--1: clamp(0.82rem, 0.79rem + 0.14vw, 0.9rem);
  --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --step-1:  clamp(1.25rem, 1.17rem + 0.38vw, 1.5rem);
  --step-2:  clamp(1.56rem, 1.42rem + 0.7vw, 2rem);
  --step-3:  clamp(1.95rem, 1.7rem + 1.24vw, 2.75rem);
  --step-4:  clamp(2.3rem, 1.95rem + 1.75vw, 3.5rem);
  --step-5:  clamp(2.8rem, 2.15rem + 3.2vw, 4.5rem);

  /* The header is now the wordmark plus the nav, with no logo tile, so its
     height is set directly rather than derived from the tile. The hero still
     offsets by --header-h so the two can never drift apart. */
  --logo-size: 120px;   /* footer tile */
  --header-pad: 0.75rem;
  --header-inner-h: 74px;   /* fallback; site.js measures the real value */
  /* The header also carries a 1px bottom border (transparent until it goes
     solid), so its real occupied height is one pixel more than its inner box.
     The hero must offset by the real height or a 1px sliver of body colour
     shows above it. */
  --header-h: calc(var(--header-inner-h) + 1px);

  /* Space */
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --band:   clamp(3.5rem, 9vw, 7.5rem);
  --band-tight: clamp(2.5rem, 6vw, 4.5rem);
  --max: 1200px;
  --measure: 68ch;

  /* Motion */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --dur: 280ms;

  /* Layers */
  --z-base: 0;
  --z-raised: 10;
  --z-header: 40;
  --z-overlay: 60;
}

/* --- Reset -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-soft);
  font-family: var(--ui);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.018em;
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { margin: 0; text-wrap: pretty; }
p + p { margin-top: 1em; }

a { color: inherit; }

:focus-visible {
  outline: 2.5px solid var(--navy);
  outline-offset: 3px;
  border-radius: 2px;
}
.band--navy :focus-visible,
.site-footer :focus-visible,
.nav[data-open="true"] :focus-visible { outline-color: var(--paper); }

::selection { background: var(--navy); color: var(--paper); }

/* --- Utilities ---------------------------------------------------------- */
.wrap { width: min(100% - (var(--gutter) * 2), var(--max)); margin-inline: auto; }
.prose { max-width: var(--measure); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: var(--gutter); top: -100px;
  z-index: var(--z-overlay);
  background: var(--navy); color: var(--paper);
  padding: 0.75rem 1.25rem; border-radius: 2px;
  font-size: var(--step--1); text-decoration: none;
}
.skip-link:focus { top: 0.75rem; }

.label {
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-faint);
}

/* Section bands */
.band { padding-block: var(--band); }
.band--tight { padding-block: var(--band-tight); }
.band--navy { background: var(--navy); color: var(--on-navy-soft); }
.band--navy h1, .band--navy h2, .band--navy h3, .band--navy h4 { color: var(--on-navy); }
.band--navy .label { color: rgba(243, 237, 235, 0.62); }
.band--warm { background: var(--paper-warm); }

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.55em;
  min-height: 48px;
  padding: 0.85em 1.6em;
  font-family: var(--ui);
  font-size: var(--step-0);
  font-weight: 600;
  text-decoration: none;
  border: 1.5px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease-out-quart),
              color var(--dur) var(--ease-out-quart),
              border-color var(--dur) var(--ease-out-quart),
              transform 160ms var(--ease-out-quart);
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--navy); color: var(--paper); border-color: var(--navy); }
.btn--primary:hover { background: var(--navy-deep); border-color: var(--navy-deep); }

.btn--ghost { background: transparent; color: var(--navy); border-color: var(--rule); }
.btn--ghost:hover { border-color: var(--navy); background: rgba(11, 40, 72, 0.05); }

.btn--light { background: var(--paper); color: var(--navy); border-color: var(--paper); }
.btn--light:hover { background: var(--white); border-color: var(--white); }

.btn--outline-light { background: transparent; color: var(--paper); border-color: rgba(243, 237, 235, 0.42); }
.btn--outline-light:hover { border-color: var(--paper); background: rgba(243, 237, 235, 0.09); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.link-underline {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 100% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  padding-bottom: 2px;
  transition: background-size var(--dur) var(--ease-out-quart);
}
.link-underline:hover { background-size: 100% 2px; }

/* --- Header ------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0;
  z-index: var(--z-header);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur) var(--ease-out-quart),
              border-color var(--dur) var(--ease-out-quart),
              color var(--dur) var(--ease-out-quart);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
  min-height: var(--header-inner-h);
  padding-block: var(--header-pad);
}

.site-header--over { color: var(--paper); }
/* Measured: the hero photo peaks at luminance 247 behind the nav, which put the
   14px links at 3.0:1 against the hero scrim alone. This gradient carries the
   header's own legibility so the photograph can stay bright. */
.site-header--over::before {
  content: "";
  position: absolute; inset: 0 0 auto 0;
  height: 190%;
  background: linear-gradient(to bottom, rgba(7, 27, 49, 0.58) 0%, rgba(7, 27, 49, 0.34) 45%, rgba(7, 27, 49, 0) 100%);
  pointer-events: none;
  z-index: -1;
}
.site-header { isolation: isolate; }
.site-header--solid,
.site-header--plain {
  background: var(--paper);
  border-bottom-color: var(--rule);
  color: var(--navy);
}

/* Logo.
   The delivered mark is a square lockup, and the brand kit is explicit that it
   "is designed for its cream background - that soft, embossed paper look is
   part of the brand." So it always sits on its own cream plate, never keyed
   out and never recoloured. --logo-cream is sampled from the file itself so
   the plate and the image edge are seamless. */
:root { --logo-cream: #F5F4F0; }

/* The lockup's own "CLEANERS" line is 19px tall in a 1000px file, so the type
   inside it only becomes legible above ~420px wide. At header size the mark
   reads as an emblem, which means the business name has to be set beside it.
   The brand kit sanctions exactly this: navy is "the one-colour brand shade
   for any text set beside it." */
.logo {
  display: inline-flex; align-items: center; gap: 0.85rem;
  text-decoration: none; color: inherit;
}
.logo__tile {
  background: var(--logo-cream);
  /* Clear space: brand rule is at least the height of the word "CLEANERS". */
  padding: 4px;
  border-radius: 1px;
  line-height: 0;
  flex: none;
}
.logo__tile img { width: var(--logo-size); height: var(--logo-size); display: block; }
.site-footer .logo { align-items: flex-start; }
.logo__text { display: flex; flex-direction: column; gap: 0.26rem; }
.logo__name {
  font-size: 0.95rem; font-weight: 600;
  letter-spacing: 0.15em; text-transform: uppercase; line-height: 1;
}
.logo__sub {
  font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.32em; text-transform: uppercase; line-height: 1;
  opacity: 0.78;
}
.site-footer .logo__tile img { width: var(--logo-size); height: var(--logo-size); }
@media (max-width: 560px) {
  .logo { gap: 0.6rem; }
  :root { --logo-size: 92px; }
  .logo__name { font-size: 0.8rem; letter-spacing: 0.12em; }
  .logo__sub { font-size: 0.54rem; letter-spacing: 0.28em; }
}

/* Nav */
.nav { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 2rem); }
.nav__list { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 2rem); list-style: none; margin: 0; padding: 0; }
.nav__link {
  font-size: var(--step--1); font-weight: 500; letter-spacing: 0.04em;
  text-decoration: none; padding: 0.8rem 0; position: relative; white-space: nowrap;
  display: inline-block; min-height: 44px;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0.15rem;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease-out-quart);
}
.nav__link:hover::after,
.nav__link[aria-current="page"]::after { transform: scaleX(1); }
.nav .btn { padding: 0.6em 1.2em; min-height: 44px; font-size: var(--step--1); }

.nav-toggle { display: none; }
.nav-scrim { display: none; }

@media (max-width: 899px) {
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; min-width: 44px;
    padding: 0.5rem 0.85rem;
    background: none; border: 1px solid currentColor; border-radius: 2px;
    color: inherit; font-family: var(--ui); font-size: var(--step--1);
    font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
    cursor: pointer;
  }
  .nav {
    position: fixed; inset: 0 0 0 auto;
    width: min(88vw, 360px);
    background: var(--navy); color: var(--on-navy);
    flex-direction: column; align-items: stretch; justify-content: center;
    gap: 0; padding: var(--gutter);
    transform: translateX(101%);
    transition: transform 320ms var(--ease-out-quart);
    z-index: var(--z-overlay);
  }
  .nav[data-open="true"] { transform: translateX(0); }
  /* The closed drawer is only off-screen, so its links would still be in the
     tab order and the accessibility tree. site.js marks it `inert` instead,
     which is deterministic; a delayed visibility transition was tried first
     and could not be relied on, because a suspended transition left the drawer
     focusable. Belt and braces: also hide it once it is fully out of the way. */
  .nav:not([data-open="true"])[inert] { visibility: hidden; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; width: 100%; }
  .nav__list li + li { border-top: 1px solid var(--rule-navy); }
  .nav__link { display: block; padding: 1rem 0; font-size: var(--step-1); font-family: var(--display); letter-spacing: 0; }
  .nav__link::after { display: none; }
  .nav__link[aria-current="page"] { opacity: 0.62; }
  .nav .btn { margin-top: 1.75rem; width: 100%; }
  .nav__close {
    position: absolute; top: 1rem; right: 1rem;
    min-height: 44px; min-width: 44px;
    background: none; border: 0; color: inherit; cursor: pointer;
    font-size: 1.6rem; line-height: 1;
  }
  .nav-scrim {
    display: block;
    position: fixed; inset: 0; background: rgba(7, 27, 49, 0.55);
    opacity: 0; pointer-events: none;
    transition: opacity 320ms var(--ease-out-quart);
    z-index: calc(var(--z-overlay) - 1);
  }
  .nav-scrim[data-open="true"] { opacity: 1; pointer-events: auto; }
}
@media (min-width: 900px) { .nav__close { display: none; } }

/* --- Hero --------------------------------------------------------------- */
.hero {
  position: relative;
  margin-top: calc(var(--header-h) * -1);
  padding-top: var(--header-h);
  min-height: min(88svh, 800px);
  display: grid;
  align-items: end;
  isolation: isolate;
  background: var(--navy);
  overflow: hidden;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 46%; }
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    rgba(7, 27, 49, 0.95) 0%,
    rgba(7, 27, 49, 0.78) 30%,
    rgba(7, 27, 49, 0.38) 66%,
    rgba(7, 27, 49, 0.5) 100%);
}
.hero__inner { padding-block: clamp(3rem, 8vw, 5.5rem) clamp(3rem, 7vw, 5rem); position: relative; }
.hero__content { max-width: 24ch; }
.hero h1 { color: var(--paper); }
.hero__tagline {
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(0.95rem, 1.5vw, 1.2rem);
  color: rgba(243, 237, 235, 0.88);
  letter-spacing: 0.01em;
  margin: 0;
  white-space: nowrap;   /* Lisa asked for it on one line */
  text-align: center;
}
.hero__lede { color: var(--on-navy-soft); max-width: 48ch; margin-top: 1.5rem; }
.hero .btn-row { margin-top: 2.25rem; }
.hero__meta {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule-navy);
  display: flex; flex-wrap: wrap; gap: 0.4rem 2rem;
  font-size: var(--step--1);
  color: rgba(243, 237, 235, 0.72);
  letter-spacing: 0.03em;
}

/* --- Section heading ---------------------------------------------------- */
.section-head { display: grid; gap: 1rem; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section-head h2 { max-width: 20ch; }
.section-head p { max-width: 54ch; }

.split { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: start; }
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: clamp(3rem, 6vw, 5.5rem); }
  .split__aside { position: sticky; top: 112px; }
}

/* --- Service rows (rule-separated, not cards) --------------------------- */
.rows { border-top: 1px solid var(--rule); }
.row-item { border-bottom: 1px solid var(--rule); }
.row-link {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0.35rem 1.5rem;
  padding-block: clamp(1.4rem, 2.6vw, 2rem);
  text-decoration: none; color: inherit;
  transition: padding-inline-start var(--dur) var(--ease-out-quart);
}
.row-link:hover { padding-inline-start: 0.7rem; }
.row-item__name { font-family: var(--display); font-size: var(--step-2); color: var(--ink); line-height: 1.15; }
.row-item__tag {
  font-size: var(--step--1); letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint); white-space: nowrap;
}
.row-item__desc { grid-column: 1 / -1; max-width: 56ch; margin-top: 0.35rem; }
.row-arrow { display: inline-block; transition: transform var(--dur) var(--ease-out-quart); }
.row-link:hover .row-arrow { transform: translateX(5px); }

/* --- Photo grid --------------------------------------------------------- */
.figure-grid { display: grid; gap: clamp(0.7rem, 1.5vw, 1.15rem); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 900px) {
  .figure-grid { grid-template-columns: repeat(4, 1fr); }
  .figure-grid > *:nth-child(1) { grid-column: span 2; grid-row: span 2; }
  .figure-grid > *:nth-child(4) { grid-column: span 2; }
}
.shot { position: relative; margin: 0; overflow: hidden; background: var(--paper-warm); }
.shot img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; transition: transform 620ms var(--ease-out-quart); }
@media (min-width: 900px) { .figure-grid > .shot:nth-child(1) img { aspect-ratio: 1 / 1; } }
.shot:hover img { transform: scale(1.035); }
.shot figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.75rem 1rem 0.85rem;
  background: linear-gradient(to top, rgba(7, 27, 49, 0.85), transparent);
  color: var(--paper); font-size: var(--step--1); letter-spacing: 0.02em;
}

/* --- Before and after --------------------------------------------------- */
/* Pairs, not a gallery. The two images live inside one figure so a reflow can
   never separate a "before" from its "after", which would be worse than not
   showing them at all. Square, because the source photos are square and
   cropping a before and an after differently would be quietly dishonest. */
.ba-grid { display: grid; gap: clamp(1.75rem, 3.5vw, 3rem); }
@media (min-width: 820px) { .ba-grid { grid-template-columns: repeat(2, 1fr); } }

/* The pairs sit under the Recent work grid as part of the same proof, so the
   spacing between them reads as one gallery continuing rather than a new
   block starting. */
.figure-grid + .ba-grid { margin-top: clamp(1.5rem, 3vw, 2.25rem); }

.ba { margin: 0; }
.ba__pair { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(0.5rem, 1vw, 0.8rem); }
.ba__shot { position: relative; margin: 0; overflow: hidden; background: var(--paper-warm); }
.ba__shot img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; aspect-ratio: 1 / 1;
}
.ba__label {
  position: absolute; top: 0.55rem; left: 0.55rem;
  background: rgba(7, 27, 49, 0.82);
  color: var(--paper);
  font-family: var(--ui); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.28rem 0.5rem; border-radius: 2px;
}
.ba figcaption {
  margin-top: 0.9rem;
  font-size: var(--step--1); line-height: 1.5;
  color: var(--ink-faint);
}

/* --- Statement band ----------------------------------------------------- */
.statement { display: grid; justify-items: center; text-align: center; gap: 1.6rem; }
.statement__quote {
  font-family: var(--display); font-size: var(--step-3); line-height: 1.26;
  color: var(--on-navy); max-width: 20ch; letter-spacing: -0.012em;
}
.statement__sub { max-width: 56ch; color: var(--on-navy-soft); }

/* --- Trust points ------------------------------------------------------- */
.points { display: grid; gap: clamp(1.75rem, 3.5vw, 2.75rem); }
@media (min-width: 700px) { .points { grid-template-columns: repeat(3, 1fr); } }
.point { display: grid; gap: 0.65rem; align-content: start; }
.point h3 { font-size: var(--step-1); }
.point p { font-size: var(--step--1); line-height: 1.62; }
.point__rule { width: 34px; height: 2px; background: var(--navy); opacity: 0.45; }
.band--navy .point__rule { background: var(--paper); opacity: 0.5; }

/* --- Testimonials (auto-hide while empty) ------------------------------- */
.quote-grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
@media (min-width: 800px) { .quote-grid { grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); } }
.quote { display: grid; gap: 1rem; align-content: start; padding-top: 1.5rem; border-top: 1px solid var(--rule); margin: 0; }
.quote blockquote { margin: 0; font-family: var(--display); font-size: var(--step-1); line-height: 1.42; color: var(--ink); }
.quote figcaption { font-size: var(--step--1); color: var(--ink-faint); letter-spacing: 0.04em; }

/* --- CTA band ----------------------------------------------------------- */
.cta { display: grid; gap: 1.75rem; justify-items: start; }
.cta__text { display: grid; gap: 1.1rem; }
.cta h2 { max-width: 17ch; }
.cta p { max-width: 50ch; }
@media (min-width: 900px) { .cta { grid-template-columns: 1fr auto; align-items: end; gap: 3rem; } }

/* --- Footer ------------------------------------------------------------- */
.site-footer { background: var(--navy-deep); color: var(--on-navy-soft); padding-block: var(--band-tight) 2rem; }
.site-footer h3 {
  font-family: var(--ui); font-size: var(--step--1); letter-spacing: 0.1em;
  text-transform: uppercase; font-weight: 600;
  color: rgba(243, 237, 235, 0.62); margin: 0 0 1rem;
}
.footer-grid { display: grid; gap: clamp(2rem, 4vw, 3rem); }
@media (min-width: 700px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr; } }
.footer-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.2rem; font-size: var(--step--1); }
.footer-list li { padding-block: 0.25rem; }
/* Inline-block + padding so each link clears the 24px WCAG 2.5.8 target
   minimum; bare inline links here measured 18px. */
.footer-list a { text-decoration: none; display: inline-block; padding-block: 0.3rem; }
.footer-list a:hover { text-decoration: underline; text-underline-offset: 3px; }
.site-footer .logo { margin-bottom: 1.25rem; }
.site-footer .logo__mark { width: 134px; }
.footer-note { font-size: var(--step--1); max-width: 34ch; color: rgba(243, 237, 235, 0.66); }
.footer-bottom {
  margin-top: clamp(2.5rem, 5vw, 4rem); padding-top: 1.5rem;
  border-top: 1px solid var(--rule-navy);
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; justify-content: space-between;
  font-size: var(--step--1); color: rgba(243, 237, 235, 0.58);
}

/* --- Motion: entrances -------------------------------------------------- */
/* Content is visible by default. JS adds .reveal-ready to <html>, then .is-in
   per element. If JS never runs, everything still renders. */
.reveal-ready [data-reveal] { opacity: 0; transform: translateY(14px); }
.reveal-ready [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity 540ms var(--ease-out-quart), transform 540ms var(--ease-out-quart);
  transition-delay: var(--reveal-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .reveal-ready [data-reveal] { opacity: 1 !important; transform: none !important; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  .shot:hover img { transform: none; }
}

/* --- Page head (content pages, no photo hero) --------------------------- */
.page-head { padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(1rem, 2vw, 1.75rem); }
.page-head h1 { max-width: 17ch; }
.page-head__lede { margin-top: clamp(1.25rem, 2.5vw, 2rem); font-size: var(--step-1); line-height: 1.5; }

/* --- Accordion (native details, enhanced) -------------------------------- */
/* <details> is used so the list works with JS disabled and is keyboard
   accessible for free. Modern browsers animate it via ::details-content;
   everywhere else it opens instantly, which is a fine degradation. */
:root { interpolate-size: allow-keywords; }

.acc { margin-top: 1.75rem; border-top: 1px solid var(--rule); }
.acc__summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1rem 0;
  min-height: 48px;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.02em;
}
.acc__summary::-webkit-details-marker { display: none; }
.acc__summary:hover { color: var(--navy); }
.acc__summary:focus-visible { outline: 2.5px solid var(--navy); outline-offset: 2px; }

/* Plus that becomes a minus */
.acc__icon { position: relative; width: 14px; height: 14px; flex: none; }
.acc__icon::before, .acc__icon::after {
  content: ""; position: absolute; inset: 50% 0 auto 0;
  height: 1.5px; background: currentColor;
  transition: transform var(--dur) var(--ease-out-quart);
}
.acc__icon::after { transform: rotate(90deg); }
.acc[open] .acc__icon::after { transform: rotate(0deg); }

.acc__content { padding-bottom: 1.5rem; }
.acc__note { font-size: var(--step--1); color: var(--ink-faint); margin-bottom: 1.25rem; max-width: 60ch; }

details::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 320ms var(--ease-out-quart), content-visibility 320ms allow-discrete;
}
details[open]::details-content { block-size: auto; }

.acc__grid { display: grid; gap: clamp(1.5rem, 3vw, 2.25rem); }
@media (min-width: 620px) { .acc__grid { grid-template-columns: repeat(2, 1fr); } }
.acc__group h4 {
  font-family: var(--ui);
  font-size: 0.78rem; letter-spacing: 0.09em; text-transform: uppercase; font-weight: 600;
  color: var(--ink-faint);
  margin-bottom: 0.75rem;
}
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; font-size: var(--step--1); line-height: 1.5; }
.ticks li { position: relative; padding-left: 1.4rem; }
.ticks li::before {
  content: "";
  position: absolute; left: 0; top: 0.52em;
  width: 7px; height: 7px;
  border-left: 1.5px solid var(--navy);
  border-bottom: 1.5px solid var(--navy);
  transform: rotate(-45deg);
  opacity: 0.7;
}

@media (prefers-reduced-motion: reduce) {
  details::details-content { transition: none; }
  .acc__icon::before, .acc__icon::after { transition: none; }
}

/* --- Page hero (content pages) ------------------------------------------ */
.page-hero {
  position: relative;
  margin-top: calc(var(--header-h) * -1);
  padding-top: var(--header-h);
  min-height: clamp(320px, 42vw, 460px);
  display: grid; align-items: end;
  isolation: isolate;
  background: var(--navy);
  overflow: hidden;
}
.page-hero__media { position: absolute; inset: 0; z-index: -2; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 58%; }
.page-hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    rgba(7, 27, 49, 0.92) 0%,
    rgba(7, 27, 49, 0.66) 42%,
    rgba(7, 27, 49, 0.34) 75%,
    rgba(7, 27, 49, 0.48) 100%);
}
.page-hero__inner { padding-block: clamp(2rem, 5vw, 3.5rem); }
.page-hero h1 { color: var(--paper); max-width: 16ch; font-size: var(--step-4); }
.page-hero__lede { color: var(--on-navy-soft); max-width: 52ch; margin-top: 1.1rem; }

/* --- Centred section heading -------------------------------------------- */
.section-head--centred { justify-items: center; text-align: center; }
.section-head--centred h2, .section-head--centred p { margin-inline: auto; }

/* --- Feature band (full-bleed image beside text) ------------------------- */
.feature { display: grid; }
@media (min-width: 900px) { .feature { grid-template-columns: 1fr 1fr; } }
.feature__media { background: var(--paper-warm); }
.feature__media img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }
@media (min-width: 900px) { .feature__media img { aspect-ratio: auto; min-height: 100%; } }
.feature__text { background: var(--navy); color: var(--on-navy-soft); display: grid; align-items: center; }
.feature__text h2 { color: var(--on-navy); max-width: 16ch; }
.feature__inner {
  padding: clamp(2.5rem, 6vw, 5rem) var(--gutter);
  max-width: 34rem;
}
@media (min-width: 900px) { .feature__inner { padding-inline: clamp(2.5rem, 5vw, 4.5rem); } }
.feature__inner p { max-width: 46ch; }
.feature__inner p + p { margin-top: 1rem; }
.feature__text .btn--ghost { color: var(--paper); border-color: rgba(243, 237, 235, 0.42); }
.feature__text .btn--ghost:hover { border-color: var(--paper); background: rgba(243, 237, 235, 0.09); }
.feature__text :focus-visible { outline-color: var(--paper); }


/* --- Service block ------------------------------------------------------ */
/* One block per service: image, description and checklist together. An earlier
   version split these into a card grid up top and detail sections below, which
   meant every service appeared twice on the page. */
.svc {
  border-top: 1px solid var(--rule);
  padding-block: clamp(2.25rem, 5vw, 4rem);
  scroll-margin-top: calc(var(--header-h) + 1rem);
  display: grid;
  gap: clamp(1.5rem, 3.5vw, 3rem);
}
.svc:last-of-type { border-bottom: 1px solid var(--rule); }

@media (min-width: 900px) {
  .svc { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start; }
  /* Alternate which side the photograph sits on so four blocks in a row read as
     a rhythm rather than a list of identical rows. nth-of-type, not nth-child:
     the section heading is also a child of the wrapper and would offset the
     count by one, starting the sequence on the wrong side. */
  .svc:nth-of-type(even) .svc__media { order: 2; }
}

.svc__media {
  margin: 0;
  overflow: hidden;
  background: var(--paper-warm);
  border-radius: 2px;
}
.svc__media img {
  width: 100%; height: 100%; object-fit: cover;
  aspect-ratio: 4 / 3;
  transition: transform 700ms var(--ease-out-quart);
}
.svc:hover .svc__media img { transform: scale(1.03); }
@media (min-width: 900px) {
  .svc__media img { aspect-ratio: 5 / 4; }
}

.svc__body { display: flex; flex-direction: column; }
.svc__name { font-size: var(--step-3); }
.svc__for {
  margin-top: 0.7rem;
  color: var(--ink-faint);
  font-family: var(--display);
  font-size: var(--step-1);
  font-style: italic;
  line-height: 1.35;
  max-width: 34ch;
}
.svc__facts { display: flex; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin-top: 1.1rem; }
.svc__facts span {
  font-size: 0.72rem; letter-spacing: 0.07em; text-transform: uppercase; font-weight: 600;
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: 100px;
  padding: 0.32rem 0.8rem;
}
.svc__text { margin-top: 1.35rem; max-width: 58ch; }

@media (prefers-reduced-motion: reduce) {
  .svc:hover .svc__media img { transform: none; }
}

/* --- New client offer --------------------------------------------------- */
.offer {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 2px;
  display: grid;
  gap: 0.6rem;
}
.offer__lead {
  font-size: var(--step--1); letter-spacing: 0.09em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
}
.offer__text { max-width: 62ch; }
.offer__text strong { color: var(--ink); font-weight: 600; }

/* --- Price list --------------------------------------------------------- */
/* A menu, not a comparison grid: item on the left, price on the right, a
   hairline between each. */
/* Three groups, one row. This was briefly a four-column auto-fit grid, which
   stranded Organising alone on a row of its own, and briefly multi-column,
   which fixed the orphan but left one column running 800px past the others.
   The real problem was that Organising had no fixed prices to list, so it
   now sits below as a note and the columns hold only priced items. */
.price-groups {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  align-items: start;
}

/* Closing note under the columns, for work that is quoted rather than listed.
   Two columns so it reads as a deliberate block rather than a stray paragraph
   left over at the bottom of the page. */
.price-aside {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(1.75rem, 3vw, 2.25rem);
  border-top: 1.5px solid var(--navy);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
}
@media (min-width: 760px) {
  .price-aside { grid-template-columns: minmax(0, 300px) 1fr; }
}
.price-aside__media { margin: 0; overflow: hidden; border-radius: 2px; background: var(--white); }
.price-aside__media img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; aspect-ratio: 4 / 3;
}
.price-aside h3 {
  font-family: var(--ui);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-faint);
  margin: 0 0 0.75rem;
}
.price-aside p { max-width: 62ch; }
.price-group__name {
  font-family: var(--ui);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-faint);
  margin: 0 0 0.5rem;
  padding-bottom: 0.75rem;
  border-bottom: 1.5px solid var(--navy);
}
.price-list { list-style: none; margin: 0; padding: 0; }
.price-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.25rem;
  padding-block: 0.85rem;
  border-bottom: 1px solid var(--rule);
}
.price-item { flex: 1; }
.price-item em {
  display: block;
  font-style: normal;
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--ink-faint);
  margin-top: 0.2rem;
}
.price-value {
  font-family: var(--display);
  font-size: var(--step-1);
  color: var(--ink);
  white-space: nowrap;
  /* Tabular figures so the column of prices lines up. */
  font-variant-numeric: tabular-nums;
}
.price-value small {
  font-family: var(--ui);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  margin-left: 0.15rem;
}
.price-note {
  margin-top: 1rem;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-faint);
  max-width: 42ch;
}

/* On the feature band the light button needs its own hover on navy */
.feature__text .btn--light:hover { background: var(--white); border-color: var(--white); }

/* --- Price group image -------------------------------------------------- */
.price-group__media {
  margin: 0 0 1.25rem;
  overflow: hidden;
  border-radius: 2px;
  background: var(--white);
}
.price-group__media img {
  width: 100%; height: 100%; object-fit: cover;
  aspect-ratio: 4 / 3;
  transition: transform 700ms var(--ease-out-quart);
}
.price-group:hover .price-group__media img { transform: scale(1.03); }

/* Eyebrow inside a feature band. Used once, on the new-client offer, not as
   section grammar. */
.feature__lead {
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: rgba(243, 237, 235, 0.66);
  margin-bottom: 0.75rem;
}

@media (prefers-reduced-motion: reduce) {
  .price-group:hover .price-group__media img { transform: none; }
}

/* --- Numbered steps ----------------------------------------------------- */
/* Numbers are used here because this genuinely is a sequence, not as decoration
   above every section. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(1.75rem, 3.5vw, 2.5rem); counter-reset: step; }
@media (min-width: 800px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.step { display: grid; gap: 0.65rem; align-content: start; }
.step__num {
  font-family: var(--display);
  font-size: var(--step-2);
  line-height: 1;
  color: var(--ink-faint);
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 0.35rem;
}
.step h3 { font-size: var(--step-1); }
.step p { font-size: var(--step--1); line-height: 1.6; }

/* --- Embedded form panel ------------------------------------------------ */
.form-panel {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: clamp(1.25rem, 3vw, 2.5rem);
  max-width: 820px;
  margin-inline: auto;
  /* Deliberately NOT a scroll container. `overflow-x: auto` here computes
     overflow-y to auto as well, which turned the panel into a 119px box with
     the form scrolling inside it instead of the panel growing to fit. */
}
/* Jobber injects an iframe here and drives its height by postMessage from the
   form inside. That handshake starts at 40px and only grows once the form has
   laid itself out, so any delay or mismeasurement leaves a 40px sliver where
   the most important control on the site should be. min-height is the floor:
   Jobber's inline height wins whenever it reports something taller, and this
   catches it when it does not. */
.form-panel iframe {
  width: 100%;
  max-width: 100%;
  border: 0;
  display: block;
  min-height: 560px;
}
/* Jobber pins an inline height on its own container div too, not just the
   iframe, so flooring the iframe alone left a 560px form overflowing a 40px
   box. The floor has to go on both. Excludes our fallback block. */
.form-panel > div:not([data-form-fallback]) { min-height: 560px; }

.form-fallback { padding: clamp(1rem, 2vw, 1.5rem) 0; }
.form-fallback p { max-width: 56ch; }

.form-aside {
  margin-top: 1.5rem;
  text-align: center;
  font-size: var(--step--1);
  color: var(--ink-faint);
}

/* --- Contact grid ------------------------------------------------------- */
.contact-grid { display: grid; gap: clamp(1.5rem, 3vw, 2.25rem); }
@media (min-width: 620px) { .contact-grid { grid-template-columns: repeat(2, 1fr); } }
.contact-item h3 {
  font-family: var(--ui);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: rgba(243, 237, 235, 0.66);
  margin-bottom: 0.5rem;
}
.contact-item p { font-size: var(--step-0); }
/* These links are the whole paragraph rather than words inside a sentence, so
   WCAG 2.5.8's inline exception does not cover them. Measured 23px; padded to
   clear the 24px minimum. They are also the fallback path on the page that
   matters most, so they should be comfortable to hit. */
.contact-item a {
  display: inline-block;
  padding-block: 0.3rem;
  overflow-wrap: anywhere;
}

/* --- Policies ----------------------------------------------------------- */
.toc { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; border-top: 1px solid var(--rule); }
.toc li { border-bottom: 1px solid var(--rule); }
.toc a {
  display: block;
  padding: 0.85rem 0;
  min-height: 44px;
  text-decoration: none;
  font-size: var(--step--1);
  transition: padding-inline-start var(--dur) var(--ease-out-quart);
}
.toc a:hover { padding-inline-start: 0.6rem; }
@media (min-width: 700px) { .toc { grid-template-columns: repeat(2, 1fr); column-gap: clamp(1.5rem, 3vw, 3rem); }
  .toc li:nth-last-child(-n+1) { border-bottom: 1px solid var(--rule); }
}

.policy-updated {
  margin-top: 1.5rem;
  font-size: var(--step--1);
  color: var(--ink-faint);
}

.policies { display: grid; gap: 0; }
.policy {
  padding-block: clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
  /* Anchored from the contents list, so clear the sticky header. */
  scroll-margin-top: calc(var(--header-h) + 1rem);
}
.policy:first-child { border-top: 1px solid var(--rule); }
.policy h2 { font-size: var(--step-2); max-width: 24ch; }
.policy > * + * { margin-top: 1rem; }
.policy p, .policy ul { max-width: 68ch; }
.policy strong { color: var(--ink); font-weight: 600; }

/* --- FAQ ---------------------------------------------------------------- */
/* Same visual treatment as .policy, kept as its own block rather than reusing
   those classes: an element marked class="policy" on the services page would
   mislead whoever edits it next. Questions are h3, because the section already
   owns the h2. */
.faq { display: grid; gap: 0; }
.faq__item {
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-bottom: 1px solid var(--rule);
}
.faq__item:first-child { border-top: 1px solid var(--rule); }
.faq__item h3 { font-size: var(--step-1); max-width: 34ch; }
.faq__item p { margin-top: 0.75rem; max-width: 68ch; }

/* Plain bullets for policy lists: the brand tick reads as "included", which is
   the wrong signal on a list of things we will not do. */
.ticks--plain li::before {
  border: 0;
  transform: none;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--ink-faint);
  top: 0.62em;
  opacity: 1;
}

/* Contact grid on a light surface. The default variant is written for navy,
   where the label colour is a translucent paper. On a light background that is
   effectively invisible, so the light variant re-colours it. */
.contact-grid--light .contact-item h3 { color: var(--ink-faint); }
.contact-grid--light .contact-item p { color: var(--ink-soft); }

/* --- Hero brand lockup --------------------------------------------------- */
/* The mark was getting lost at header size, so it earns its space here instead,
   where it is large enough for its own lettering to read. */
.hero__brand {
  display: flex;
  align-items: flex-start;
  gap: clamp(1.25rem, 3vw, 2.75rem);
  flex-wrap: wrap;
}
.hero__logo {
  background: var(--logo-cream);
  padding: 6px;
  border-radius: 2px;
  line-height: 0;
  flex: none;
}
.hero__logo img {
  width: clamp(140px, 21vw, 270px);
  height: auto;
  display: block;
}

/* Mark and tagline travel together as one unit. */
.hero__mark { display: grid; justify-items: center; gap: 0.85rem; flex: none; }

/* The headline is a deliberate word stack, one word per line, set against the
   square logo beside it. Every break is explicit, so the column must not also
   impose a width or a stray word could wrap again and break the rhythm.
   Balancing is off for the same reason. Tighter leading because stacked single
   words want to read as a block, not as a paragraph. */
.hero .hero__content { max-width: none; }
.hero h1 {
  text-wrap: normal;
  line-height: 1.0;
  /* Aligning the boxes is not the same as aligning what you see. EB Garamond
     starts drawing the W about 0.153em below the top of its line box, so
     flex-start left the headline visibly sitting low against the logo tile.
     Measured, not guessed. In em so it holds as the heading scales. */
  margin-top: -0.153em;
}

@media (max-width: 560px) {
  .hero__brand { gap: 1.1rem; }
}
