/* ==========================================================================
   PRAIRIE HAVEN NP CLINIC
   Shared stylesheet — YQR Design
   --------------------------------------------------------------------------
   Load order:  fonts → tokens → base → components → sections → utilities
   Fonts are self-hosted. No third-party CDN, no external requests, no pixels.
   Required by the discovery form: no third-party pixels on any page that
   links to booking.
   ========================================================================== */

/* ==========================================================================
   01 · FONTS — self-hosted, subset to Latin, variable weight
   ========================================================================== */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/CormorantGaramond.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/CormorantGaramond-Italic.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Roboto";
  src: url("../fonts/Roboto.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Metric-matched fallback for the body face.

   Every page's running text is Roboto. With `font-display: swap` the browser
   paints Arial first and re-paints when the real file lands — and Arial sets
   noticeably shorter, so every paragraph on the page reflowed on load. That
   is the layout shift a visitor sees as the page "jumping" while they are
   already reading.

   The overrides below force the fallback to occupy Roboto's exact vertical
   box, so the swap changes the letterforms and nothing else. The numbers are
   Roboto's own metrics: 2048 units/em, ascender 1900, descender -500, no
   line gap. Nothing is guessed.

   Only the body face gets this. Cormorant and Jost carry short headings and
   nav labels where a few pixels of drift is invisible, and inventing metrics
   for them would risk making the fit worse, not better.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Roboto Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  ascent-override: 92.77%;      /* 1900 / 2048 */
  descent-override: 24.41%;     /*  500 / 2048 */
  line-gap-override: 0%;
  size-adjust: 100%;
}

/* ==========================================================================
   02 · TOKENS
   ========================================================================== */

:root {
  /* ---- Brand palette — from the approved brand board ---- */
  --sage:       #A7B89A;
  --soft-sage:  #C8D5C1;
  --wheat:      #E6D6B5;
  --sky:        #A7C1C6;
  --earth:      #5E6B5B;

  /* ---- Soft white — the board's background tone, now a named brand colour.
         This is the default page ground. Everything else sits on it.

         Warmed from #FAF8F3 to sit on the wheat side of neutral rather than
         the grey side. The old value was only two points warm and read as
         plain white next to the sage and wheat it has to share a page with;
         this one reads as cream and lets the logo's greens sit on it without
         looking pasted on. Measured, not eyeballed — see the ladder below. ---- */
  --soft-white: #FBF8F0;

  /* ---- Logo ink — sampled from the supplied logo SVG.
         Slightly warmer/deeper than --earth. Used for the mark only, so the
         header lockup matches the print files exactly. ---- */
  --logo-green: #5F7359;
  --logo-gold:  #C49046;

  /* ---- Derived surfaces.
         A four-step warm ladder, each step a visible tone apart so alternating
         sections separate without a single border. Contrast checked against
         --ink and --ink-soft; the worst case in the set is --ink-soft on
         --paper-2 at 5.1:1, comfortably past the 4.5:1 AA floor for body
         copy. Re-check these two if any value here is ever changed. ---- */
  --paper:    #F6F2E9;              /* alternating section ground           */
  --paper-2:  #EFE9DC;              /* recessed band                        */
  --white:    #FFFDF8;              /* cards, raised surfaces               */

  /* ---- Ink ---- */
  --ink:       #2E3830;             /* body copy — AA on soft white         */
  --ink-soft:  #5A6459;             /* secondary copy — AA at 16px+         */
  --ink-faint: #7C8579;             /* meta, captions — large/decorative    */

  /* ---- Accent ---- */
  --gold:      #B98F4E;             /* wheat darkened to pass AA on light   */
  --gold-soft: #C9A96A;             /* rules, dividers, decorative          */

  /* ---- Sage darkened until it carries meaning on a light ground.
         --sage itself is 1.9:1 on --paper: fine for a wash, far too faint for
         anything a visitor is meant to read as a signal. This is the value
         used for the "taking new patients" dot. 3.8:1, past the 3:1 floor
         for non-text. ---- */
  --sage-deep: #6F8566;

  /* ---- Lines ---- */
  --line:        rgba(94,107,91,.18);
  --line-strong: rgba(94,107,91,.32);
  --line-light:  rgba(255,255,255,.16);

  /* ---- Type.
         Three faces, all from the supplied brand package:

         --display  Cormorant Garamond. The logo wordmark is a high-contrast
                    old-style serif; this is its closest living relative and
                    the reason every heading, pull quote and numeral on the
                    site is set in it. Headings are the type that has to look
                    like it came from the same studio as the mark.
         --ui       Jost. Wide-tracked geometric caps — the same treatment as
                    the "NP CLINIC" rule under the wordmark. Used only for
                    labels, nav, buttons and eyebrows, never for reading.
         --body     Roboto. Deliberately quiet: running text on a clinic site
                    is there to be read, not to perform, and a second serif
                    would compete with the mark.

         "Roboto Fallback" is the metric-matched stand-in declared in §01. It
         must stay immediately after "Roboto" — after the generic families it
         would never be reached. ---- */
  --display: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --ui:      "Jost", system-ui, -apple-system, "Segoe UI", sans-serif;
  --body:    "Roboto", "Roboto Fallback", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* ---- Layout ---- */
  --w:    1140px;
  --w-nr: 780px;                    /* narrow measure — prose pages         */
  --gut:  clamp(20px, 5vw, 40px);
  --r:    14px;
  --r-sm: 10px;

  /* ---- Motion ---- */
  --ease: cubic-bezier(.4, 0, .2, 1);
}

/* ==========================================================================
   03 · BASE
   ========================================================================== */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;         /* sticky header + safety strip         */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--soft-white);
  color: var(--ink);
  font-family: var(--body);
  font-weight: 400;
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg, video { max-width: 100%; display: block; }
a { color: inherit; }

.wrap {
  width: 100%;
  max-width: var(--w);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.wrap-nr { max-width: var(--w-nr); }

/* Skip link — first tab stop on every page */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--earth);
  color: var(--soft-white);
  padding: .8rem 1.3rem;
  font-family: var(--ui);
  font-size: .85rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

/* ==========================================================================
   04 · TYPE
   ========================================================================== */

/* Display type — headings, pull quotes, the step numerals and the answer
   band. Everything here is the logo's voice.

   `oldstyle-nums` is the detail that ties the numerals to the mark: Cormorant
   defaults to lining figures, which stand at cap height and read as tabular
   and clinical. Old-style figures sit on the baseline with ascenders and
   descenders like lowercase letters, which is what a Garamond-derived
   wordmark implies and what makes "01 02 03" on the booking steps look drawn
   rather than typed.

   `font-optical-sizing` lets the variable file thin its hairlines as the
   display sizes climb, so the 4.3rem h1 keeps the contrast the logo has
   instead of going blunt. */
h1, h2, h3, h4,
.quote, .tagline, .cell .a, .step::before, .faq summary, .portrait-name {
  font-optical-sizing: auto;
  font-variant-numeric: oldstyle-nums;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 500;
  color: var(--earth);
  margin: 0;
  letter-spacing: .005em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.6rem, 6.6vw, 4.3rem); line-height: 1.04; }
h2 { font-size: clamp(1.95rem, 4.4vw, 2.9rem); line-height: 1.1;  }
h3 { font-size: 1.42rem; line-height: 1.24; }
h4 { font-size: 1.12rem; line-height: 1.3; font-weight: 600; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(1.04rem, 1.9vw, 1.18rem);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 52ch;
}

/* Eyebrow — mirrors the "— NP CLINIC —" rule on the brand lockup */
.eyebrow {
  font-family: var(--ui);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--earth);
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 0 0 1.05rem;
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: var(--gold-soft);
  flex: none;
}

/* Pull quote — the practitioner's own voice */
.quote {
  font-family: var(--display);
  font-size: clamp(1.4rem, 3vw, 1.95rem);
  line-height: 1.35;
  color: var(--earth);
  font-style: italic;
  border-left: 2px solid var(--gold-soft);
  padding-left: clamp(1.1rem, 3vw, 2rem);
  margin: 0;
  max-width: 34ch;
}

/* --------------------------------------------------------------------------
   TBD — everything only Lorissa can confirm.
   Deliberately loud. Nothing wearing this class may go to production.
   `npm run check` equivalent: search the built site for "tbd" before launch.
   -------------------------------------------------------------------------- */
.tbd {
  border-bottom: 1.5px dotted #C08A4A;
  color: #8F6224;
  background: rgba(230, 214, 181, .38);
  padding: 0 .2em;
  border-radius: 2px;
  font-style: normal;
}
.tbd::before {
  content: "▲ ";
  font-size: .7em;
  vertical-align: .12em;
  opacity: .75;
}

/* ==========================================================================
   05 · BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  font-family: var(--ui);
  font-size: .83rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1;
  padding: 1rem 1.7rem;
  border-radius: 100px;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease),
              border-color .2s var(--ease), transform .2s var(--ease);
}
.btn svg { width: 15px; height: 15px; flex: none; }

.btn-primary { background: var(--earth); color: var(--soft-white); }
.btn-primary:hover { background: #4B564A; transform: translateY(-1px); }

.btn-ghost { border-color: var(--earth); color: var(--earth); }
.btn-ghost:hover { background: var(--soft-sage); transform: translateY(-1px); }

/* On dark grounds */
.btn-light { border-color: var(--wheat); color: var(--wheat); }
.btn-light:hover { background: var(--wheat); color: var(--earth); }

.btn-sm { padding: .65rem 1.2rem; font-size: .72rem; }

/* On a touch device every button clears 44px, regardless of size variant.
   .btn-sm is 34px tall by design and that is fine under a mouse, but it is a
   real miss rate under a thumb — and the small buttons are the ones that
   matter here ("Show the map", "Get directions", the header booking CTA). */
@media (pointer: coarse) {
  .btn { min-height: 44px; }
}

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2.5px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ==========================================================================
   06 · ICONS — line set drawn to match the brand board
   ========================================================================== */

/* --------------------------------------------------------------------------
   Every symbol is drawn in a 40×40 viewBox, so the stroke a visitor actually
   sees is  stroke-width × (rendered px / 40).  A single stroke-width across
   all sizes therefore does not hold its weight — it collapses as the icon
   shrinks:

       stroke-width: 1.4   at 62px → 2.17px   fine
                           at 46px → 1.61px   fine
                           at 34px → 1.19px   fine
                           at 17px → 0.60px   washed out
                           at 15px → 0.53px   effectively invisible

   The 15px case is every button icon on the site — the pin on "Open in Google
   Maps", the arrow on the marquee links — and a half-pixel stroke does not
   land on a device pixel. The browser antialiases it into pale grey, which is
   why those icons read as smudges rather than as line art. It is not a colour
   problem; the colour was always right.

   Fixed by tiering the width so the drawn stroke stays near 1–1.3 device px
   at every size the site actually uses. Sizes are grouped by their rendered
   px, not by which class happens to set them.
   -------------------------------------------------------------------------- */

/* Base is the SMALL case — a bare .icon renders at 1em (≈17px), and the
   button and toggle icons are smaller still. Everything at or above 26px
   sets its own stroke-width in the same rule that sets its size, a few
   sections down. Keeping the two together is deliberate: they are one
   decision, and split across sections they drift apart the first time
   someone resizes an icon. */
.icon {
  width: 1em; height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;                /* 15px → 0.98px · 17px → 1.11px        */
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Large display marks. Left at the original 1.4 — these were never the
   problem, and thinning them to match the small tier would be a redesign
   rather than a fix. */
.icon-lg { width: 46px; height: 46px; stroke-width: 1.4; }   /* → 1.61px    */
.icon-xl { width: 62px; height: 62px; stroke-width: 1.4; }   /* → 2.17px    */

/* Filled marks (the logo) opt out of the stroke treatment */
.icon-solid { fill: currentColor; stroke: none; }

/* --------------------------------------------------------------------------
   Icon colour.

   Line icons inherit currentColor, so they are only ever as visible as the
   text colour that happens to surround them — inside .muted copy that means
   --ink-soft, and inside a caption --ink-faint at 2.9:1. Pinning the
   decorative marks to --earth holds them at 5.6:1 on every light ground.
   -------------------------------------------------------------------------- */
.card .ic, .mq-card .ic, .svc .ic, .value .ring { color: var(--earth); }

/* On the dark ground they go to wheat instead: 3.9:1 on --earth, past the
   3:1 floor for non-text, and the same colour as the eyebrow rule above
   them. Buttons are excluded — .btn-light and .btn-primary already set a
   colour their icon correctly inherits. */
.ground-earth .ic { color: var(--wheat); }

/* ==========================================================================
   07 · SAFETY STRIP — always visible, every page. Non-negotiable.
   ========================================================================== */

.safety {
  background: var(--earth);
  color: #EDF0EA;
  font-family: var(--ui);
  font-size: .8rem;
  letter-spacing: .015em;
  padding: .62rem 0;
}
.safety .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.5rem;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.safety strong { font-weight: 600; color: #fff; }
.safety a { color: #fff; text-underline-offset: 3px; }

/* ==========================================================================
   08 · HEADER
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  /* Must track --soft-white. Hard-coded rather than a var() because it needs
     an alpha channel for the blur behind it to read. */
  background: rgba(251, 248, 240, .93);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .5rem 0;
}

/* Logo lockup.
   This is the supplied logo file, used unmodified — the mark, the wordmark and
   the "NP CLINIC" rule are all part of the artwork. Do not rebuild any part of
   it in HTML text, and do not recolour it. Size it with height only so the
   proportions stay exactly as drawn. */
.lockup { display: flex; align-items: center; text-decoration: none; }

/* The logo is a stacked lockup — mark above the wordmark — so it needs real
   height before "Prairie Haven" and the "NP CLINIC" rule become legible.
   Height only; never set width, or the proportions shift. */
.lockup .logo { height: 92px; width: auto; flex: none; }

@media (max-width: 940px) {
  .lockup .logo { height: 64px; }
}

.site-nav ul {
  display: flex;
  gap: 1.6rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav a {
  font-family: var(--ui);
  font-size: .79rem;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-soft);
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.site-nav a:hover { color: var(--earth); border-color: var(--gold-soft); }
.site-nav a[aria-current="page"] { color: var(--earth); border-color: var(--gold); }

/* Mobile toggle.
   44x44 minimum. This is the one control every mobile visitor has to hit, and
   the practice serves adults across the whole age range — a 38px target is a
   real miss rate, not a theoretical one. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  padding: .5rem;
  color: var(--earth);
  cursor: pointer;
}
.nav-toggle svg { width: 22px; height: 22px; }

@media (max-width: 940px) {
  .nav-toggle { display: inline-flex; }
  .site-nav {
    position: absolute;
    inset: 100% 0 auto;
    background: var(--soft-white);
    border-bottom: 1px solid var(--line);
    padding: .5rem var(--gut) 1.3rem;
    display: none;
  }
  .site-nav[data-open="true"] { display: block; }
  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav li { border-bottom: 1px solid var(--line); }
  .site-nav a { display: block; padding: .95rem 0; border-bottom: none; font-size: .88rem; }
  .header-cta { display: none; }
}

/* ==========================================================================
   09 · SECTIONS
   ========================================================================== */

section { padding: clamp(3.4rem, 7.5vw, 5.8rem) 0; }
.sec-head { max-width: 58ch; margin-bottom: clamp(1.9rem, 4vw, 2.9rem); }
.sec-head p { margin-top: .9rem; }

.ground-paper  { background: var(--paper); }
.ground-paper2 { background: var(--paper-2); }
.ground-sage   { background: var(--soft-sage); }

/* Dark ground — inverts type colours */
.ground-earth { background: var(--earth); color: #DDE3D9; }
.ground-earth h1, .ground-earth h2,
.ground-earth h3, .ground-earth h4 { color: #fff; }
.ground-earth .eyebrow { color: var(--wheat); }
.ground-earth .eyebrow::before { background: var(--wheat); }
.ground-earth .lede { color: #D3DACE; }
.ground-earth a { color: #fff; text-underline-offset: 4px; }

/* ==========================================================================
   10 · HERO
   ========================================================================== */

.hero { position: relative; overflow: hidden; padding: clamp(2.8rem, 6.5vw, 5rem) 0 0; }
.hero-grid {
  display: grid;
  /* The photograph carries more weight than the illustration it replaced, so
     it gets the wider column. Text still holds a comfortable measure. */
  grid-template-columns: .88fr 1.12fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.hero h1 span { display: block; }
.hero h1 .em { color: var(--gold); font-style: italic; font-weight: 400; }
.hero-cta { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }
/* The hero photograph is shown whole — no fixed aspect-ratio and no
   object-fit, so nothing is cropped out of frame. The image's own proportions
   set the height of the column.

   It carries no parallax. The previous illustration was over-sized 8% top and
   bottom so it had room to drift inside a clipping frame; a photo shown whole
   has no such overscan, and drifting it would either expose an edge or force a
   crop back in. Trading a subtle drift for an uncropped photograph. */
.hero-art {
  border-radius: var(--r);
  border: 1px solid var(--line);
  overflow: hidden;
  line-height: 0;              /* kills the inline-descender gap under the img */
}
/* Same 3:2 window as every other photograph on the site. height:auto for the
   same reason as .photo — see the note there. */
.hero-art > img {
  width: 100%;
  height: auto;
  display: block;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: center;
}
@media (max-width: 860px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-art { order: -1; }
}

/* ==========================================================================
   11 · ANSWER BAND — the three things every visitor arrives wanting
   ========================================================================== */

.band {
  margin-top: clamp(2.6rem, 5.5vw, 4.2rem);
  border-block: 1px solid var(--line);
  background: var(--paper);
}
.band-grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.cell { padding: 1.85rem clamp(1rem, 2.4vw, 2rem); position: relative; }
.cell + .cell::before {
  content: "";
  position: absolute;
  left: 0; top: 16%; bottom: 16%;
  width: 1px;
  background: var(--line);
}
.cell .q {
  font-family: var(--ui);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .5rem;
}
.cell .a {
  font-family: var(--display);
  font-size: 1.48rem;
  color: var(--earth);
  line-height: 1.18;
  margin-bottom: .35rem;
}
.cell .n { font-size: .88rem; color: var(--ink-soft); margin: 0; }

.status { display: inline-flex; align-items: center; gap: .5rem; }
/* The "taking new patients — Yes" indicator. The word carries the meaning, so
   the dot is not the only cue, but at --sage it was 1.9:1 on --paper and read
   as a smudge rather than as a live status light. The deeper green core hits
   3.8:1; the halo stays soft, since it is pure decoration. */
.dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--sage-deep);
  box-shadow: 0 0 0 4px rgba(167, 184, 154, .34);
  flex: none;
}

@media (max-width: 780px) {
  .band-grid { grid-template-columns: 1fr; }
  .cell + .cell::before {
    left: clamp(1rem, 2.4vw, 2rem);
    right: clamp(1rem, 2.4vw, 2rem);
    top: 0; bottom: auto;
    width: auto; height: 1px;
  }
}

/* ==========================================================================
   12 · VALUES — Rooted · Safe · Care (the brand board's icon trio)
   ========================================================================== */

.values {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.6rem, 4vw, 3rem);
  text-align: center;
}
.value .ring {
  width: 76px; height: 76px;
  margin: 0 auto 1.1rem;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--earth);
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.value:hover .ring { border-color: var(--gold-soft); background: var(--soft-white); }
.value .ring svg { width: 36px; height: 36px; stroke-width: 1.7; } /* → 1.53px */
.value h3 {
  font-family: var(--ui);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--earth);
  margin-bottom: .55rem;
}
.value p { font-size: .92rem; color: var(--ink-soft); margin: 0; max-width: 30ch; margin-inline: auto; }
@media (max-width: 720px) { .values { grid-template-columns: 1fr; } }

/* ==========================================================================
   13 · CARDS
   ========================================================================== */

.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem; }
.cards-2 { grid-template-columns: repeat(2, 1fr); }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 2rem 1.75rem;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: 0 14px 34px -22px rgba(46, 56, 48, .5); }
.card .ic { color: var(--earth); margin-bottom: 1.15rem; }
.card h3 { margin-bottom: .7rem; }
.card > p { font-size: .95rem; color: var(--ink-soft); }
.card ul { margin: 0; padding-left: 1.1rem; font-size: .93rem; color: var(--ink-soft); }
.card li { margin-bottom: .35rem; }
.card li::marker { color: var(--gold); }

@media (max-width: 880px) { .cards, .cards-2 { grid-template-columns: 1fr; } }

/* ==========================================================================
   14 · SERVICE ROWS — Services page
   ========================================================================== */

.svc { border-top: 1px solid var(--line); padding: clamp(1.7rem, 3.5vw, 2.5rem) 0; }
.svc:last-child { border-bottom: 1px solid var(--line); }
.svc-grid {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) 260px;
  gap: clamp(1.2rem, 3vw, 2.4rem);
  align-items: start;
}
.svc .ic { color: var(--earth); width: 44px; height: 44px; stroke-width: 1.5; } /* → 1.65px */
.svc h3 { margin-bottom: .6rem; }
.svc p { font-size: .96rem; color: var(--ink-soft); }

.meta { font-family: var(--ui); font-size: .8rem; }
.meta div { display: flex; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--line); }
.meta div:last-child { border-bottom: none; }
.meta dt, .meta .k {
  color: var(--earth);
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-size: .68rem;
  min-width: 5.6rem;
  flex: none;
  padding-top: .15rem;
}
.meta dd, .meta .v { margin: 0; color: var(--ink-soft); }

@media (max-width: 880px) {
  .svc-grid { grid-template-columns: 44px minmax(0, 1fr); }
  .svc .meta { grid-column: 1 / -1; }
}

/* ==========================================================================
   15 · PRACTITIONER
   ========================================================================== */

.who-grid {
  display: grid;
  grid-template-columns: .85fr 1.15fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.portrait {
  aspect-ratio: 4 / 5;
  border-radius: var(--r);
  background: linear-gradient(160deg, var(--paper-2), var(--wheat));
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  text-align: center;
  padding: 1.4rem;
  font-family: var(--ui);
  font-size: .74rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.creds { list-style: none; padding: 0; margin: 1.6rem 0 0; font-size: .91rem; }
.creds li {
  padding: .62rem 0;
  border-top: 1px solid var(--line-strong);
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.creds span:first-child {
  font-family: var(--ui);
  color: var(--earth);
  font-weight: 500;
  min-width: 8.5rem;
  flex: none;
  font-size: .7rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding-top: .2rem;
}
@media (max-width: 880px) { .who-grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   16 · STEPS
   ========================================================================== */

.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; counter-reset: s; }
.step { padding-top: 1.35rem; border-top: 2px solid var(--wheat); }
.step::before {
  counter-increment: s;
  content: "0" counter(s);
  font-family: var(--display);
  font-size: 2.4rem;
  color: var(--gold-soft);
  line-height: 1;
  display: block;
  margin-bottom: .55rem;
}
.step h3 { font-size: 1.18rem; margin-bottom: .5rem; }
.step p { font-size: .93rem; color: var(--ink-soft); margin: 0; }
@media (max-width: 880px) { .steps { grid-template-columns: 1fr; } }

/* ==========================================================================
   17 · FAQ
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hover-to-reveal.

   Requested behaviour: moving the mouse over a question shows its answer,
   without a click. Implemented as an enhancement on top of native <details>,
   never as a replacement for it — main.js opens the panel on pointer entry
   and closes it again on exit, and marks the element [data-hover-open] while
   it is doing so.

   Three things keep this from becoming an accessibility problem:

   · It is gated to (hover: hover) and (pointer: fine) in the script, so a
     touch device never gets it. On a phone, hover-open means the answer
     appears and vanishes on a tap with no way to keep it, which is worse
     than no enhancement at all.
   · Clicking still works and wins. A clicked-open question is pinned, and
     moving the mouse away does not close it — otherwise reading a long
     answer would be a test of mouse steadiness.
   · Keyboard focus opens it too, so the two input methods behave the same.

   With JavaScript off, all of this disappears and the plain click-to-open
   <details> remains. Nothing here is required to read an answer.
   -------------------------------------------------------------------------- */

.faq { max-width: 820px; }
.faq details {
  border-bottom: 1px solid var(--line);
  /* A wash on hover so the whole row, not just the text, reads as the
     hit target — the question is two lines wide on a phone and the
     difference between "this is a link" and "this is a paragraph" has to be
     legible before anything moves. */
  transition: background .2s var(--ease);
}
.faq details:hover,
.faq details[open] { background: rgba(255, 255, 255, .5); }
.faq details:hover { box-shadow: inset 3px 0 0 var(--gold-soft); }
.faq details[open] { box-shadow: inset 3px 0 0 var(--gold); }

.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 1.25rem 2.6rem 1.25rem 0;
  position: relative;
  font-family: var(--display);
  font-size: 1.22rem;
  color: var(--earth);
  line-height: 1.32;
  transition: color .2s var(--ease), padding-left .2s var(--ease);
}
.faq details:hover summary,
.faq details[open] summary { padding-left: .9rem; }
.faq summary::-webkit-details-marker { display: none; }
/* Hover/focus makes the question read as interactive before it's opened —
   colour shifts to the site's accent gold, same language as the chevron. */
.faq summary:hover,
.faq summary:focus-visible { color: var(--gold); }
.faq summary::after {
  content: "";
  position: absolute;
  right: .45rem; top: 1.6rem;
  width: 11px; height: 11px;
  border-right: 1.5px solid var(--gold);
  border-bottom: 1.5px solid var(--gold);
  transform: rotate(45deg);
  transition: transform .25s var(--ease), border-color .2s var(--ease);
}
.faq summary:hover::after,
.faq summary:focus-visible::after { border-color: var(--earth); }
.faq details[open] summary::after { transform: rotate(-135deg); }

.faq .answer {
  padding: 0 2.6rem 1.5rem .9rem;
  font-size: .96rem;
  color: var(--ink-soft);
}
.faq .answer p { margin-bottom: .8em; }

/* Let the panel ease open instead of snapping. `interpolate-size` is what
   makes height:auto animatable; where it is unsupported the answer simply
   appears instantly, which is the current behaviour and perfectly fine. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }

  .faq details::details-content {
    block-size: 0;
    overflow: clip;
    transition: block-size .28s var(--ease), content-visibility .28s allow-discrete;
  }
  .faq details[open]::details-content { block-size: auto; }
}

/* Hover-opened panels are transient — dim them very slightly so a pinned
   (clicked) answer is distinguishable from one that is about to vanish when
   the mouse moves on. */
.faq details[data-hover-open] .answer { opacity: .92; }
.faq .src {
  font-size: .78rem;
  color: var(--ink-faint);
  font-style: italic;
  display: block;
  margin-top: .6rem;
}

/* Grouped FAQ headings */
.faq-group {
  font-family: var(--ui);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 2.6rem 0 .4rem;
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--line-strong);
}
.faq-group:first-child { margin-top: 0; }

/* ==========================================================================
   18 · NOTICES
   ========================================================================== */

.notice {
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-sm);
  padding: 1.15rem 1.3rem;
  font-size: .92rem;
  background: var(--paper);
  color: var(--ink-soft);
}
.notice strong { color: var(--earth); font-weight: 600; }
.notice.on-dark {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(230, 214, 181, .4);
  border-left-color: var(--wheat);
  color: #E7EBE3;
}
.notice.on-dark strong { color: #fff; }

/* Crisis panel — end-of-life / MAiD pages */
.crisis {
  background: var(--paper-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  padding: clamp(1.4rem, 3vw, 2rem);
}
.crisis h3 { font-size: 1.2rem; margin-bottom: .8rem; }
.crisis ul { list-style: none; padding: 0; margin: 0; font-size: .93rem; }
.crisis li { padding: .55rem 0; border-bottom: 1px solid var(--line); display: flex; gap: 1rem; flex-wrap: wrap; }
.crisis li:last-child { border-bottom: none; }
.crisis li b { font-family: var(--ui); font-weight: 500; color: var(--earth); min-width: 9rem; flex: none; }

/* ==========================================================================
   19 · CONTACT
   ========================================================================== */

.contact-item { margin-bottom: 1.45rem; }
.contact-item .k {
  font-family: var(--ui);
  font-size: .7rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .28rem;
}
.ground-earth .contact-item .k { color: var(--wheat); }
.contact-item a { text-underline-offset: 4px; }

.hours { list-style: none; padding: 0; margin: 1.2rem 0 0; font-size: .93rem; }
.hours li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .55rem 0;
  border-bottom: 1px solid var(--line);
}
.ground-earth .hours li { border-color: var(--line-light); }
.ground-earth .hours span:last-child { color: #fff; }

/* --------------------------------------------------------------------------
   MAP — click-to-load, contact page only.

   The map was originally left out entirely: an embedded Google iframe loads
   third-party script and sets cookies, and the discovery form rules that out
   on any page that links to booking. That reasoning is sound and it still
   holds — but "no map at all" was never what it required. What it requires is
   that no third-party request happens without the visitor choosing it.

   So the embed is here, behind a click. On load this is a plain local panel:
   no iframe in the DOM, no request to Google, no cookie, nothing to consent
   to. The visitor sees the address and a button. If they press it, main.js
   builds the iframe and only then does anything leave the browser — and the
   button says so before they press it.

   That keeps the privacy page accurate as written (it claims no third-party
   requests, which remains true of every page as delivered) and still gives
   the "quick review" map the brief asked for.

   The static-map export in the photo list is no longer needed. Left in the
   shoot brief for now — it is Lorissa's call whether to keep a flat image as
   the no-JavaScript fallback.
   -------------------------------------------------------------------------- */

.map {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--r);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  overflow: hidden;
}

/* The map drawing sitting under the consent panel.

   Drawn in the brand palette rather than loaded from anywhere, so the section
   looks like a map the moment the page paints while still making no
   third-party request. It is schematic — a grid orientation, not a survey.

   TO SWAP IN A REAL STATIC EXPORT: drop the image at assets/img/map.png and
   replace the <svg class="map-art"> element in contact.html with
   <img class="map-art" src="assets/img/map.png" alt="">. Nothing else changes.
   Keep it a flat exported image, not an iframe, and carry Google's attribution
   ("Map data ©Google") in the caption if the export comes from Google Maps. */
.map-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* The pre-consent panel. Replaced wholesale by the iframe on activation.

   Only the faintest wash over the whole panel — an earlier version scrimmed it
   at 68-93% and the map underneath was invisible, which defeated the point of
   drawing one. Legibility is handled by the card instead, so the map stays
   fully readable around it. */
.map-consent {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: end;          /* bar sits along the bottom */
  padding: clamp(.7rem, 2.5vw, 1rem);
  background: rgba(94, 107, 91, .08);
}

/* A bottom bar, not a centred card. Centred, it sat squarely on top of the
   pin — the one thing the drawing exists to show. */
.map-card {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .55rem .9rem;
  padding: .85rem 1.05rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(250, 248, 243, .95);
  box-shadow: 0 18px 44px -30px rgba(46, 56, 48, .6);
}
@supports (backdrop-filter: blur(2px)) {
  .map-card { backdrop-filter: blur(4px); }
}
.map-card .icon { width: 26px; height: 26px; stroke-width: 1.7; color: var(--earth); flex: none; }

/* The consent explanation, moved out from under the pin to below the map. */
.map-why {
  font-size: .82rem;
  color: var(--ink-soft);
  margin: .8rem 0 0;
  max-width: 46ch;
}
.map-consent svg { width: 34px; height: 34px; stroke-width: 1.7; color: var(--earth); }
.map-consent .addr {
  font-family: var(--display);
  font-size: 1.3rem;
  line-height: 1.25;
  color: var(--earth);
}
.map-consent .why {
  font-size: .82rem;
  color: var(--ink-soft);
  max-width: 34ch;
  margin: 0;
}

.map iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* Sits under the map: the plain link out, which needs no consent and is the
   route anyone on a phone will actually use to get directions. */
.map-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin-top: 1rem;
}

@media (max-width: 620px) { .map { aspect-ratio: 1; } }

/* ==========================================================================
   20 · PROSE — Privacy / Terms
   ========================================================================== */

.prose { max-width: 72ch; }
.prose h2 { font-size: clamp(1.5rem, 3vw, 2rem); margin: 2.6rem 0 .9rem; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: 1.15rem; margin: 1.8rem 0 .6rem; }
.prose ul, .prose ol { padding-left: 1.3rem; margin: 0 0 1.15em; }
.prose li { margin-bottom: .45rem; }
.prose li::marker { color: var(--gold); }
.prose a { color: var(--earth); text-underline-offset: 3px; }
.prose dl { margin: 1.2rem 0 1.6rem; }
.prose dt {
  font-family: var(--ui);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold);
  font-weight: 500;
  margin-top: 1.1rem;
}
.prose dt:first-child { margin-top: 0; }
.prose dd { margin: .35rem 0 0; }
.updated {
  font-family: var(--ui);
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ==========================================================================
   21 · PAGE HEAD — inner pages
   ========================================================================== */

.page-head { padding: clamp(2.6rem, 6vw, 4.4rem) 0 clamp(2rem, 4vw, 3rem); background: var(--paper); border-bottom: 1px solid var(--line); }
.page-head .lede { margin-top: 1.1rem; }

/* On-page table of contents — long legal pages only (Privacy) */
.toc { margin-top: 1.8rem; padding: 1.3rem 1.5rem; background: var(--white); border: 1px solid var(--line); border-radius: var(--r-sm); font-size: .88rem; }
.toc .label { font-family: var(--ui); font-size: .66rem; letter-spacing: .18em; text-transform: uppercase; color: var(--gold); font-weight: 500; margin: 0 0 .7rem; }
.toc ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem 1.2rem; }
.toc a { text-decoration: none; color: var(--ink-soft); }
.toc a:hover { color: var(--earth); text-decoration: underline; }
@media (max-width: 620px) { .toc ul { grid-template-columns: 1fr; } }

.crumb { font-family: var(--ui); font-size: .74rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: .9rem; }
.crumb a { text-decoration: none; color: var(--ink-soft); }
.crumb a:hover { color: var(--earth); text-decoration: underline; }

/* ==========================================================================
   22 · CTA STRIP
   ========================================================================== */

.cta-strip { background: var(--soft-sage); text-align: center; }
.cta-strip h2 { margin-bottom: .8rem; }
.cta-strip p { max-width: 46ch; margin-inline: auto; color: var(--ink-soft); }
.cta-strip .btns { display: flex; gap: .75rem; justify-content: center; flex-wrap: wrap; margin-top: 1.8rem; }

/* ==========================================================================
   23 · FOOTER
   ========================================================================== */

.site-footer {
  background: #4B564A;
  color: rgba(255, 255, 255, .74);
  font-size: .85rem;
  padding: clamp(2.6rem, 5vw, 3.6rem) 0 2rem;
}
.foot-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 2rem;
  padding-bottom: 2.2rem;
  border-bottom: 1px solid var(--line-light);
}
.site-footer a { color: rgba(255, 255, 255, .9); text-underline-offset: 3px; }
.site-footer h4 {
  font-family: var(--ui);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--wheat);
  margin-bottom: .9rem;
}
.foot-links { list-style: none; padding: 0; margin: 0; }
.foot-links li { margin-bottom: .5rem; }
.foot-links a { text-decoration: none; }
.foot-links a:hover { text-decoration: underline; }

.tagline { font-family: var(--display); font-size: 1.08rem; color: var(--wheat); font-style: italic; }

.foot-base {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem 2rem;
  justify-content: space-between;
  align-items: center;
  padding-top: 1.5rem;
  font-size: .78rem;
  color: rgba(255, 255, 255, .6);
}
@media (max-width: 760px) { .foot-grid { grid-template-columns: 1fr; gap: 1.8rem; } }

/* ==========================================================================
   24 · UTILITIES
   ========================================================================== */

.mt-0  { margin-top: 0; }
.mt-1  { margin-top: .8rem; }
.mt-2  { margin-top: 1.6rem; }
.mt-3  { margin-top: 2.4rem; }
.mt-4  { margin-top: 3.2rem; }
.mb-0  { margin-bottom: 0; }
.mb-1  { margin-bottom: .8rem; }
.mb-2  { margin-bottom: 1.6rem; }
.mb-3  { margin-bottom: 2.4rem; }
.small { font-size: .87rem; }
.muted { color: var(--ink-soft); }
.center { text-align: center; }

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
}
@media (max-width: 880px) { .split { grid-template-columns: 1fr; } }

.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;
}

/* Reveal on scroll */
.rv { opacity: 0; transform: translateY(16px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.rv.in { opacity: 1; transform: none; }

/* ==========================================================================
   25 · PHOTO PLACEHOLDERS
   --------------------------------------------------------------------------
   Marks where commissioned photography goes. Each one names the shot so the
   photographer and Lorissa are working from the same list. Dashed border and
   the ▲ convention make them obviously unfinished — they must not survive to
   launch, and tools/check.mjs counts them.
   ========================================================================== */

.ph {
  border-radius: var(--r);
  border: 1.5px dashed var(--line-strong);
  background: linear-gradient(160deg, var(--paper-2), var(--wheat));
  display: grid;
  place-items: center;
  padding: 1.5rem;
  color: var(--ink-soft);
  font-family: var(--ui);
  /* Clips the inner parallax layer so it can drift without pushing the
     dashed border around or spilling into the next section. */
  overflow: hidden;
}
.ph-inner {
  display: grid;
  place-items: center;
  align-content: center;
  gap: .55rem;
  text-align: center;
}
.ph svg { width: 34px; height: 34px; stroke-width: 1.7; color: var(--earth); opacity: .45; }
.ph b {
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--earth);
}
.ph b::before { content: "▲ "; opacity: .75; }
.ph small {
  font-size: .78rem;
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 34ch;
}

.ph-wide   { aspect-ratio: 16 / 9; }
.ph-band   { aspect-ratio: 21 / 9; }
.ph-tall   { aspect-ratio: 4 / 5; }
.ph-square { aspect-ratio: 1; }

@media (max-width: 640px) {
  .ph-band, .ph-wide { aspect-ratio: 4 / 3; }
}

/* ==========================================================================
   26 · PHOTOS — finished, real imagery
   --------------------------------------------------------------------------
   Once a .ph placeholder is replaced by an actual photo, swap the <figure>
   for an <img class="photo …">. Same aspect-ratio vocabulary as .ph so a
   replacement never reflows the section around it.
   ========================================================================== */

/* ONE SHAPE FOR EVERY PHOTOGRAPH.
   --------------------------------------------------------------------------
   The source library is a mix of 3:2 landscapes and 2:3 portraits. Shown at
   their own proportions they stack into a ragged column — a tall portrait
   beside a short landscape reads as files dropped on a page rather than a
   designed one, and it makes some subjects look more important than others
   purely because their file was taller.

   So every photo is served in the same 3:2 window and centre-cropped to fit.
   3:2 because it is the native ratio of most of the library, so the majority
   of images lose nothing at all, and the portraits give up their empty top
   and bottom rather than their subject — which sits centred in all of them.

   Consequence to know: a photo whose subject is NOT centred will be cropped
   badly. Crop it to 3:2 in an editor first, choosing the framing deliberately,
   then drop it in. Do not add a per-image exception here. */
.photo {
  width: 100%;
  /* height:auto is load-bearing, not tidiness. Every <img> carries
     height="1000" so the browser can reserve space before the file loads, and
     that attribute lands as a presentational hint of `height: 1000px`. Since
     this rule sets width but not height, the hint wins, both dimensions end up
     fixed, and `aspect-ratio` is ignored entirely — the box renders ~688x1000
     portrait and object-fit:cover slices the sides off every photograph.
     Setting height:auto hands control back to aspect-ratio. */
  height: auto;
  display: block;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: center;
  border-radius: var(--r);
  background: var(--paper-2);   /* holds the shape before the file arrives */
}

/* The brand mark is not a photograph. It carries the business name, so it is
   never cropped and never forced into the 3:2 photo frame — it gets a small,
   centred frame at its own proportions. */
.brand-mark {
  display: block;
  width: 100%;
  max-width: 300px;
  height: auto;
  margin-inline: auto;
  object-fit: contain;
}

/* Two photographs side by side. Both are already the same shape, so they line
   up top and bottom without any further work. */
.photo-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1rem, 2.4vw, 1.6rem);
}
@media (max-width: 720px) { .photo-pair { grid-template-columns: 1fr; } }

/* ==========================================================================
   27 · MARQUEE — auto-scrolling banner, right to left
   --------------------------------------------------------------------------
   Used twice: the team on About, and the "good to know" band on Home.

   Structure matters. The track holds TWO identical groups; the animation
   translates it by exactly -50%, which lands the second group where the first
   started, so the loop is seamless. Each group carries its own trailing gap
   (padding-right) so both halves are exactly equal width — using a single
   flex `gap` across all items instead makes the halves differ by one gap and
   the loop visibly jumps.

   The duplicate group is aria-hidden so screen readers read the list once.

   Accessibility: content that moves automatically for more than five seconds
   needs a way to stop it (WCAG 2.1 SC 2.2.2 Pause, Stop, Hide). Hence the
   pause button, plus pause on hover and on keyboard focus. Under reduced
   motion it does not animate at all and becomes an ordinary scrollable row.
   ========================================================================== */

.marquee { --speed: 64s; position: relative; }

.marquee-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.7rem;
}

.marquee-viewport { overflow: hidden; }

/* Fade the edges so cards enter and leave rather than being chopped off */
@supports (mask-image: linear-gradient(90deg, #000, transparent)) {
  .marquee-viewport {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
  }
}

.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee var(--speed) linear infinite;
}
.marquee-group {
  display: flex;
  gap: 1.25rem;
  padding-right: 1.25rem;   /* keeps both halves identical in width */
  margin: 0;
  padding-left: 0;
  list-style: none;
}

@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* Stop on hover, on keyboard focus, and on explicit request */
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track,
.marquee[data-paused="true"] .marquee-track { animation-play-state: paused; }

.marquee-toggle {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: 100px;
  padding: .5rem 1rem;
  cursor: pointer;
  color: var(--earth);
  font-family: var(--ui);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.marquee-toggle:hover { background: var(--white); border-color: var(--gold-soft); }
.marquee-toggle svg { width: 13px; height: 13px; stroke-width: 3; } /* → 0.98px */
.ground-earth .marquee-toggle { color: var(--wheat); border-color: rgba(230, 214, 181, .45); }
.ground-earth .marquee-toggle:hover { background: rgba(255, 255, 255, .08); }

/* --- Cards inside a marquee --- */
.mq-card {
  flex: none;
  width: clamp(248px, 29vw, 310px);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.5rem 1.4rem;
}
.mq-card .ic { color: var(--earth); width: 34px; height: 34px; stroke-width: 1.7; margin-bottom: .9rem; } /* → 1.45px */
.mq-card h3 { font-size: 1.16rem; margin-bottom: .45rem; }
.mq-card p { font-size: .9rem; color: var(--ink-soft); margin: 0; }
.mq-card a.more {
  display: inline-block;
  margin-top: .8rem;
  font-family: var(--ui);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--earth);
  text-underline-offset: 4px;
}

/* Team variant — portrait placeholder above the name */
.mq-person { text-align: center; }
.mq-person .avatar {
  width: 92px;
  height: 92px;
  margin: 0 auto .95rem;
  border-radius: 50%;
  border: 1.5px dashed var(--line-strong);
  background: linear-gradient(160deg, var(--paper-2), var(--wheat));
  display: grid;
  place-items: center;
  color: var(--earth);
}
.mq-person .avatar svg { width: 26px; height: 26px; stroke-width: 1.9; opacity: .45; }
.mq-person h3 { font-size: 1.14rem; margin-bottom: .2rem; }
.mq-person .role {
  font-family: var(--ui);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .6rem;
}

.marquee-toggle { min-height: 44px; }

/* On a phone the banner runs faster than it needs to relative to the smaller
   viewport, and the edge fade eats too much of a narrow card. */
@media (max-width: 640px) {
  .marquee { --speed: 46s; }
  .marquee-viewport {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent);
            mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent);
  }
  .marquee-head { margin-bottom: 1.3rem; }
  .mq-card { width: min(78vw, 290px); }
}

@media (prefers-reduced-motion: reduce) {
  /* No motion. Becomes a plain horizontal scroller the visitor controls,
     with the duplicate removed so nothing reads twice. */
  .marquee-viewport {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .marquee-track { width: auto; animation: none; }
  .marquee-group[aria-hidden="true"] { display: none; }
  .marquee-toggle { display: none; }
  .mq-card { scroll-snap-align: start; }
}

/* ==========================================================================
   28 · TEAM GRID — "The people here", home page
   --------------------------------------------------------------------------
   A compact, static counterpart to the About page's team marquee. Home shows
   just enough to feel staffed and welcoming; "Meet the whole team" sends
   anyone who wants full bios to About.
   ========================================================================== */

.team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.4rem, 3vw, 2.2rem);
}
.member {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.6rem 1.5rem 1.9rem;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.member:hover { transform: translateY(-3px); box-shadow: 0 14px 34px -22px rgba(46, 56, 48, .5); }

/* Arch portrait — echoes the circular ring in the logo mark */
.member .ph-arch {
  aspect-ratio: 4 / 5;
  border-radius: 50% 50% var(--r-sm) var(--r-sm) / 32% 32% var(--r-sm) var(--r-sm);
  margin-bottom: 1.2rem;
}

.member .role {
  font-family: var(--ui);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold);
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin: 0 0 .5rem;
}
.member .tag {
  font-family: var(--ui);
  font-size: .62rem;
  letter-spacing: .1em;
  padding: .2rem .55rem;
  border-radius: 100px;
  background: var(--wheat);
  color: #7A6432;
  font-weight: 500;
}
.member h3 { font-size: 1.3rem; margin-bottom: .5rem; }
.member > p:last-child { font-size: .92rem; color: var(--ink-soft); margin: 0; }

@media (max-width: 880px) {
  .team-grid { grid-template-columns: 1fr; max-width: 420px; margin-inline: auto; }
}

/* ==========================================================================
   29 · MOTION / PRINT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .rv { opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
}

@media print {
  .safety, .site-header, .cta-strip, .nav-toggle, .btn { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .rv { opacity: 1; transform: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; color: #555; }
  section { padding: 1.2rem 0; }
}
