/* ==========================================================================
   The Radiant Room
   Single stylesheet. All design tokens live in the :root block below, so the
   palette is one edit. Derivation of every color is in recon/PALETTE.md.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand — extracted from the live site's Flatsome customizer.
     These are also the two colors in the logo mark. */
  --ink:    #0E123F;   /* deep navy   — dark bands, headings, buttons, links   */
  --bronze: #735802;   /* deep gold   — the accent, on light surfaces          */
  --gold:   #D2AD38;   /* bright gold — the accent, on dark surfaces           */

  /* Ground — sampled from the photography's warm light neutral (#ECDCD5) */
  --shell:  #FAF6F3;
  --sand:   #EFE6E0;

  /* Text */
  --body:   #4A4A4A;

  /* Derived. --gold never sits on a light surface (2.15:1) and --bronze never
     sits on a dark one (2.66:1). They are one accent with a light form and a
     dark form. Full contrast matrix in recon/PALETTE.md. */
  --rule:        rgba(115, 88, 2, .32);   /* --bronze hairline, the only divider */
  --rule-strong: rgba(115, 88, 2, .6);
  --rule-dark:   rgba(210, 173, 56, .34); /* --gold hairline, on --ink           */
  --body-on-ink: rgba(250, 246, 243, .78);

  /* Type scale — fluid between 360px and 1440px. Tightened: the jumps are smaller and
     the contrast is carried by the width axis instead of by size alone. */
  --t-display-xl: clamp(2.75rem, 1.95rem + 3.6vw, 4.25rem);
  --t-display-l:  clamp(2.125rem, 1.65rem + 2.1vw, 3rem);
  --t-h2:         clamp(1.5rem, 1.32rem + .8vw, 1.875rem);
  --t-h3:         1.1875rem;
  --t-eyebrow:    .78125rem;
  --t-lede:       clamp(1.125rem, 1.06rem + .34vw, 1.25rem);
  --t-body:       1.0625rem;
  --t-small:      .875rem;
  --t-micro:      .75rem;

  /* Width axis — the weight contrast lever. */
  --w-display: 118%;
  --w-h2:      108%;
  --w-body:    100%;

  /* Space. Deliberately generous; whitespace is most of the premium signal. */
  --gutter:    clamp(1.25rem, .8rem + 2vw, 2.75rem);
  --section:   clamp(3.25rem, 2.1rem + 4.2vw, 6.25rem);
  --section-sm: clamp(2.25rem, 1.6rem + 2.6vw, 4rem);
  --measure:   66ch;
  --measure-narrow: 54ch;

  --wrap: 1140px;
  --wrap-tight: 900px;
  --header-h: 72px;

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   2. Font — one variable file, both axes, self-hosted
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-stretch: 100% 125%;
  font-style: normal;
  font-display: swap;
}

/* Metric-matched fallback. Without this, the swap from the system font to Archivo
   reflows text and pushes tall images down the page — it measured CLS 0.155 on
   /weight-loss, whose hero is 800x1199. Metrics below are read from the font file:
   1000 upm, ascent 878, descent 210, lineGap 0; Arial's average lowercase advance is
   0.556em against Archivo's 0.598em, hence size-adjust 107.5% and overrides divided
   by 1.075. */
@font-face {
  font-family: 'Archivo Fallback';
  src: local('Arial'), local('Helvetica Neue'), local('Roboto');
  size-adjust: 107.5%;
  ascent-override: 81.7%;
  descent-override: 19.5%;
  line-gap-override: 0%;
}

/* --------------------------------------------------------------------------
   3. Reset and base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--shell);
  color: var(--body);
  font-family: 'Archivo', 'Archivo Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.7;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, picture, svg { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 {
  color: var(--ink);
  font-weight: 600;
  margin: 0 0 .6em;
  text-wrap: balance;
}

h1 { font-size: var(--t-display-l); line-height: 1.06; letter-spacing: -.018em; font-stretch: var(--w-display); }
h2 { font-size: var(--t-h2);        line-height: 1.16; letter-spacing: -.012em; font-stretch: var(--w-h2); }
h3 { font-size: var(--t-h3);        line-height: 1.32; letter-spacing: -.005em; font-stretch: var(--w-body); }

p { margin: 0 0 1.1em; max-width: var(--measure); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--ink); text-decoration-color: var(--rule-strong); text-underline-offset: .18em; }
a:hover { text-decoration-color: var(--bronze); }

/* Reading measure applies to prose lists only. Layout grids (.cards, .quotes,
   .trust, .steps, .locations, .venues) set their own width. */
.legal ul, .legal ol, .faq ul, .faq ol, main p + ul, main p + ol {
  max-width: var(--measure);
}

:focus-visible {
  outline: 3px solid var(--bronze);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--shell);
  padding: .75rem 1.25rem; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

.vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */

/* The gutter absorbs the display cutout. viewport-fit=cover means the page now paints
   edge to edge, so in landscape on a notched phone the inset is the difference between
   a readable line and one running under the camera housing. Every inset resolves to 0px
   where there is no cutout, so nothing moves on any other device. */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: calc(var(--gutter) + env(safe-area-inset-left, 0px))
                  calc(var(--gutter) + env(safe-area-inset-right, 0px));
}

/* Anchor targets must clear the sticky header, or "See pricing" lands with the
   heading hidden behind it. */
[id] { scroll-margin-top: calc(var(--header-h) + 1.5rem); }

.band { padding-block: var(--section); }

/* Centred section headers. Body prose and the fee schedule stay left-aligned —
   centred running text is harder to read and centred numbers cannot align. */
.section-head { text-align: center; margin-inline: auto; max-width: 46rem; }
.section-head .eyebrow { margin-inline: auto; }
.section-head p { margin-inline: auto; }
.centred { text-align: center; }
/* When .centred is on the <p> itself it still carries the base max-width, so it needs
   the auto margin too — otherwise the text centres inside a box that is pinned left. */
p.centred { margin-inline: auto; }

/* Centred block, left-aligned running text — centred multi-line prose is measurably
   harder to read, so the container centres and the text does not. */
.prose-centred { max-width: 62ch; margin-inline: auto; }

/* The schedule centres as a block; its rows stay left/right aligned so the numbers
   line up, which is the whole point of the fee schedule. */
.schedule--centred { margin-inline: auto; }
.centred .eyebrow, .centred p { margin-inline: auto; }
.band--sand  { background: var(--sand); }
.band--ink   { background: var(--ink); color: var(--body-on-ink); }
.band--tight { padding-block: var(--section-sm); }

/* The default divider. A hairline costs nothing and reads as typeset; swapping the
   background on every section reads as a template. Sand is now used sparingly, to mark
   the fee schedule and one or two genuine changes of register. */
.band--rule { border-top: 1px solid var(--rule); }
.band--ink + .band--rule, .band--sand + .band--rule { border-top: 0; }

/* Prose columns stop at a readable measure rather than running the full 1140px.
   Applied to the element inside .wrap, not to .wrap itself — .wrap centres its own box,
   so combining them narrowed the column and pulled it off the shared left edge. */
.measure > * { max-width: var(--wrap-tight); }
.measure--narrow { max-width: var(--measure-narrow); }

.band--ink h1, .band--ink h2, .band--ink h3 { color: var(--shell); }
.band--ink a { color: var(--gold); text-decoration-color: var(--rule-dark); }
.band--ink a:hover { text-decoration-color: var(--gold); }

.eyebrow {
  display: block;
  font-size: var(--t-eyebrow);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--bronze);
  margin: 0 0 .9rem;
  font-stretch: 100%;
}
.band--ink .eyebrow { color: var(--gold); }

.lede { font-size: var(--t-lede); line-height: 1.6; max-width: 56ch; }

.rule { border: 0; border-top: 1px solid var(--rule); margin: 0; }
.band--ink .rule { border-top-color: var(--rule-dark); }


/* --------------------------------------------------------------------------
   Icons — Lucide (ISC), inlined as a <symbol> sprite.
   An icon font would add a render-blocking request and a FOIT window; this
   costs zero requests, inherits currentColor and scales with font-size.
   -------------------------------------------------------------------------- */

.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 1em; height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
  vertical-align: -.125em;
}

/* Uppercase label rows: pin the icon to the cap height and give it breathing room. */
.icon--label { width: .95em; height: .95em; margin-right: .5em; stroke-width: 2.25; }

/* Service cards: sits above the heading, in bronze, at a larger size. */
.icon--card {
  display: block;
  width: 1.5rem; height: 1.5rem;
  margin-bottom: .7rem;
  color: var(--bronze);
  stroke-width: 1.75;
}
.band--ink .icon--card { color: var(--gold); }

.icon--inline { margin-right: .4em; }

.deflist dt, .venue dt { display: flex; align-items: baseline; }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .8rem 1.5rem;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--shell);
  transition: background .12s var(--ease), color .12s var(--ease),
              border-color .12s var(--ease);
}
.btn:hover { background: #1b2160; border-color: #1b2160; }

.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--shell); }

.band--ink .btn {
  background: var(--gold); border-color: var(--gold); color: var(--ink);
}
.band--ink .btn:hover { background: #e0bd4d; border-color: #e0bd4d; }
.band--ink .btn--ghost {
  background: transparent; color: var(--gold); border-color: var(--rule-dark);
}
.band--ink .btn--ghost:hover { background: var(--gold); color: var(--ink); }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.75rem; }

.arrow-link {
  display: inline-block;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 2px;
  transition: border-color .12s var(--ease);
}
.arrow-link:hover { border-bottom-color: var(--bronze); }
.arrow-link::after { content: ' \2192'; }

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: #FFFFFF;
  border-bottom: 1px solid var(--rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: var(--header-h);
}

.site-header__logo { flex: 0 0 auto; margin-right: auto; }
.site-header__logo img { width: 156px; height: 67px; }

.nav { display: flex; align-items: center; gap: clamp(.75rem, 1.6vw, 1.6rem); }
.nav a {
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
  padding: .35rem 0;
  border-bottom: 2px solid transparent;
  transition: border-color .12s var(--ease);
  white-space: nowrap;
}
.nav a:hover, .nav a[aria-current='page'] { border-bottom-color: var(--bronze); }

.nav-toggle {
  display: none;
  align-items: center;
  gap: .5rem;
  background: none;
  border: 1px solid var(--rule);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  font-size: .9375rem;
  padding: .5rem .85rem;
  cursor: pointer;
}

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: none;
    position: absolute;
    inset: 100% 0 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--shell);
    border-bottom: 1px solid var(--rule);
    padding: .5rem var(--gutter) 1.25rem;
  }
  .nav[data-open='true'] { display: flex; }
  .nav a { padding: .85rem 0; border-bottom: 1px solid var(--rule); }
  .nav a:hover, .nav a[aria-current='page'] { border-bottom-color: var(--bronze); }
  .nav .btn { margin-top: 1rem; }
}

@media (max-width: 400px) {
  .site-header__logo img { width: 124px; height: 53px; }
}

/* Mobile call/book bar. The live site's only CTA is a tel: link, which loses
   every after-hours visitor; this is the cheapest possible fix. */
.callbar { display: none; }

/* The bar's own height, declared once. The page reserves exactly this much at the
   foot of <body> so the bar never sits on top of the last line of content — the old
   3.4rem guess was 4px short of the rendered bar and clipped it. */
@media (max-width: 720px) {
  .callbar {
    --callbar-h: 3.25rem;
    display: grid;
    grid-template-columns: 1fr 1fr;
    position: fixed;
    inset: auto 0 0;
    z-index: 45;
    border-top: 1px solid var(--rule-dark);
    /* A background of its own, so nothing ever shows through the bar on a device
       with a bottom inset. */
    background: var(--ink);
    padding-left: env(safe-area-inset-left, 0px);
    padding-right: env(safe-area-inset-right, 0px);
  }
  /* The home-indicator inset belongs on the two links, not on the bar. On the bar it
     was a strip of untinted padding below the buttons that the page scrolled behind,
     which read as the bar floating clear of the bottom edge. On the links, each half
     carries its own colour all the way down to the physical edge of the screen and the
     tappable area still starts above the indicator. */
  .callbar a {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--callbar-h);
    padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom, 0px));
    line-height: 1.3;
    text-align: center;
    font-weight: 600;
    text-decoration: none;
    background: var(--ink);
    color: var(--shell);
  }
  .callbar a + a { background: var(--gold); color: var(--ink); }
}


/* Mini trust badge in the sticky header. Stays visible while scrolling; the score is
   always shown, the qualifier drops on narrow screens where the header is tight. */
.header-trust {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  flex: 0 0 auto;
  margin-right: clamp(.5rem, 1.5vw, 1.25rem);
  padding: .4rem .1rem;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
}
.header-trust svg { fill: var(--bronze); flex: 0 0 auto; }
.header-trust__score { font-variant-numeric: tabular-nums; }
.header-trust__label {
  color: var(--bronze);
  font-size: var(--t-micro);
  letter-spacing: .09em;
  text-transform: uppercase;
  padding-left: .45rem;
  border-left: 1px solid var(--rule);
}
.header-trust:hover .header-trust__score { text-decoration: underline; text-underline-offset: .18em; }
@media (max-width: 560px) { .header-trust__label { display: none; } }
@media (max-width: 400px) { .header-trust { margin-right: .4rem; } }

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

.hero { padding-block: clamp(2.75rem, 1.6rem + 4.4vw, 5.5rem) var(--section); }

.hero__grid {
  display: grid;
  gap: clamp(2.25rem, 4vw, 4rem);
  align-items: center;
}

@media (min-width: 880px) {
  .hero__grid { grid-template-columns: 1.08fr .92fr; }
}

.hero h1 {
  font-size: var(--t-display-xl);
  line-height: 1.02;
  letter-spacing: -.025em;
  font-stretch: var(--w-display);
}

/* ---- Ink hero -------------------------------------------------------------
   Gold on ink is the one pairing in the locked palette that reads unmistakably
   premium (8.31:1, AAA), and it solves the image ceiling by making type the hero
   rather than photography. The photo is capped at its native 750px so it never
   upscales. */

.hero--ink {
  background: var(--ink);
  color: var(--body-on-ink);
  padding-block: clamp(3rem, 1.8rem + 5vw, 6.5rem) clamp(2.5rem, 1.6rem + 4vw, 5rem);
}
.hero--ink h1 { color: var(--shell); }
.hero--ink .eyebrow { color: var(--gold); }
.hero--ink .lede { color: var(--body-on-ink); }
.hero--ink .hero__figure img { border-color: var(--rule-dark); }
.hero--ink a { color: var(--gold); }

.hero--ink .btn { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.hero--ink .btn:hover { background: #e0bd4d; border-color: #e0bd4d; }
.hero--ink .btn--ghost {
  background: transparent; color: var(--gold); border-color: var(--rule-dark);
}
.hero--ink .btn--ghost:hover { background: var(--gold); color: var(--ink); }

/* Capped at the source's native width so it is never upscaled. */
.hero__figure--capped { max-width: 750px; margin-inline: auto; }

/* ---- Rating ---------------------------------------------------------------
   Visual only. No AggregateRating or Review markup: Google requires a review
   count in AggregateRating, and self-serving review markup on LocalBusiness has
   been ineligible for rich results since 2019. */

.rating {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  white-space: nowrap;
  gap: .55rem;
  text-decoration: none;
  padding: .4rem 0;
  font-size: var(--t-small);
  line-height: 1;
}
/* The five stars are one 89x16 SVG. At a fixed pixel size it read as a display
   graphic at 360px — wide enough to push "5.0 on Google" onto a second line. Sizing
   by height with the aspect ratio pinned keeps it a compact inline element at every
   width, and pinning the ratio means no layout shift while the sheet loads. */
.rating__stars {
  display: block;
  flex: 0 0 auto;
  height: clamp(11px, 3.1vw, 16px);
  width: auto;
  aspect-ratio: 89 / 16;
}
.rating__stars path { fill: var(--bronze); }
.hero--ink .rating__stars path, .band--ink .rating__stars path { fill: var(--gold); }
.rating__value {
  font-weight: 700;
  font-size: clamp(.875rem, 2.7vw, 1rem);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.hero--ink .rating__value, .band--ink .rating__value { color: var(--shell); }
.rating__label {
  color: var(--body);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  transition: border-color .12s var(--ease);
}
.hero--ink .rating__label, .band--ink .rating__label {
  color: var(--body-on-ink); border-bottom-color: var(--rule-dark);
}
.rating:hover .rating__label { border-bottom-color: var(--bronze); }
.hero--ink .rating:hover .rating__label { border-bottom-color: var(--gold); }

/* ---- Trust strip ----------------------------------------------------------
   Verifiable facts only, set as type. No badges, no seals, no icons in circles —
   a badge implying a credential she does not hold would be an FTC exposure, and
   they read as discount ecommerce besides. */

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem clamp(1rem, 2.4vw, 2rem);
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
}
.trust li {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--bronze);
  line-height: 1.5;
  position: relative;
}
.trust li + li::before {
  content: "";
  position: absolute;
  left: calc(clamp(1rem, 2.4vw, 2rem) / -2);
  top: .2em;
  bottom: .2em;
  border-left: 1px solid var(--rule);
}
.hero--ink .trust li, .band--ink .trust li { color: var(--gold); }
.hero--ink .trust li + li::before, .band--ink .trust li + li::before {
  border-left-color: var(--rule-dark);
}

.trust--strip {
  padding-block: clamp(1.25rem, .9rem + 1.2vw, 1.9rem);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.hero--ink .trust--strip {
  border-top-color: var(--rule-dark);
  border-bottom-color: var(--rule-dark);
}

/* Trust list layout.
   Mobile: a two-column grid, no dividers — a wrapped flex row leaves orphan separators
   hanging at the start of a line.
   Desktop: a single full-width row below the hero grid, where it never wraps. */
.trust { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem 1rem; }
.trust li::before { display: none; }

@media (min-width: 700px) {
  .trust { display: flex; flex-wrap: wrap; gap: .55rem clamp(1rem, 2.4vw, 2rem); }
  .trust li + li::before { display: block; }
}

/* Three signals sit with the CTAs in the hero column; the full strip is its own band. */

/* Each item carries its own hairline above it. A wrapped flex row leaves separators
   orphaned at the start of a line; a grid with per-item rules stays aligned at every
   width and reads as a spec sheet rather than a badge row. */
.trust--strip { display: grid; gap: 0 clamp(1.25rem, 2.4vw, 2.5rem); grid-template-columns: 1fr 1fr; }
@media (min-width: 620px) { .trust--strip { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { .trust--strip { grid-template-columns: repeat(6, 1fr); } }
.trust--strip li {
  border-top: 1px solid var(--rule);
  padding: .7rem 0 .1rem;
  line-height: 1.45;
}
.trust--strip li::before { display: none; }

.hero__trust {
  margin-top: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  padding-top: clamp(1.1rem, .9rem + .8vw, 1.5rem);
  border-top: 1px solid var(--rule);
  grid-template-columns: 1fr;
}
@media (min-width: 460px) { .hero__trust { grid-template-columns: repeat(3, auto); } }
.hero--ink .hero__trust { border-top-color: var(--rule-dark); }

.hero__figure { margin: 0; }
.hero__figure img { width: 100%; border: 1px solid var(--rule); }


/* --------------------------------------------------------------------------
   7b. Stage hero
   Adapted from the supplied reference: rounded inset frame, oversized three-line
   display type with the middle line de-emphasised, a copy + rating cluster bottom
   left, and a floating card bottom right.

   The reference runs a full-bleed photograph. The largest asset here is 750x499,
   which would need a 2x upscale to fill a hero — forbidden — so ink is the ground
   instead. Gold on ink is the one AAA pairing in the locked palette, and the photo
   moves to the section below where it renders under its native size.
   -------------------------------------------------------------------------- */

.stage {
  padding: clamp(.5rem, .3rem + .8vw, 1.25rem);
  padding-left: calc(clamp(.5rem, .3rem + .8vw, 1.25rem) + env(safe-area-inset-left, 0px));
  padding-right: calc(clamp(.5rem, .3rem + .8vw, 1.25rem) + env(safe-area-inset-right, 0px));
  padding-bottom: 0;
}

/* The frame's own padding is a token because the photograph bleeds through it to the
   frame edge — the figure cancels it with a negative margin of exactly the same value. */
.stage__inner {
  --stage-pt: clamp(2.25rem, 1.4rem + 3.6vw, 5rem);
  --stage-px: clamp(1.5rem, .9rem + 2.6vw, 4rem);
  --stage-pb: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);

  position: relative;
  background: var(--ink);
  border-radius: clamp(14px, 1.4vw, 26px);
  overflow: hidden;
  padding: var(--stage-pt) var(--stage-px) var(--stage-pb);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: clamp(1.75rem, 1.2rem + 2vw, 3rem);
  isolation: isolate;
}

/* A single soft radial lift stops the flat ink reading as a plain block. No new
   hue — it is the same ink and gold already in the palette. */
.stage__inner::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 80% at 12% 0%, rgba(210, 173, 56, .13), transparent 58%),
    radial-gradient(90% 70% at 100% 100%, rgba(210, 173, 56, .09), transparent 60%);
  z-index: -1;
}

.stage__head { max-width: none; }

.stage h1 {
  color: var(--shell);
  font-size: clamp(2.5rem, 1.45rem + 4.6vw, 5.25rem);
  line-height: 1.0;
  letter-spacing: -.035em;
  font-stretch: 118%;
  margin: 0;
  text-wrap: initial;
}
/* The reference mutes its middle line; same technique, same palette. */
.stage h1 .muted { color: rgba(250, 246, 243, .42); }

/* Split composition. The hero previously carried a "Visit us" card holding both full
   addresses and the hours — all already in the nav, the footer and on /find-us — plus
   six badges. Dropping the card and two of the badges frees a whole column, and the
   photograph takes it rather than more type. A single quiet line carries the one fact
   the card contributed that nothing else in the hero did.

   Below 940px everything stacks: copy, photograph, proof panel. */
.stage__lead { display: flex; flex-direction: column; }
.stage__head { margin-bottom: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem); }

@media (min-width: 940px) {
  .stage__inner {
    /* The display type sets the floor for the copy column: "done carefully" cannot
       rewrap, so the photograph takes a percentage and yields as the h1 grows. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 32%);
    grid-template-areas: "lead figure" "proof proof";
    column-gap: clamp(2rem, .8rem + 3.2vw, 4.5rem);
    row-gap: clamp(2.25rem, 1.5rem + 2.6vw, 3.75rem);
  }
  .stage__lead   { grid-area: lead; }
  .stage__figure { grid-area: figure; }
  .proof         { grid-area: proof; }
  /* The copy sits at the foot of its column, under the display type. */
  .stage__head  { margin-bottom: 0; }
  .stage__pitch { margin-top: auto; padding-top: clamp(2rem, 1.4rem + 2.4vw, 3.5rem); }
}

/* The measure caps the prose, not the block: the action row underneath needs the full
   column or the button and the hours are squeezed onto three lines. */
.stage__pitch { color: var(--body-on-ink); font-size: var(--t-body); }
.stage__pitch > p { max-width: 38ch; margin-bottom: 1.1rem; }
.stage__rating { display: flex; align-items: center; gap: .6rem; }

/* The quiet line that replaced the address card. Not a heading, not a badge — one
   line of small caps that answers "are they open" and nothing else. */
.stage__when {
  margin: 0;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--gold);
  white-space: nowrap;
}
.stage__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  margin-top: 1.4rem;
}
.stage__pitch .btn { width: 100%; max-width: 20rem; }

/* Side by side once there is room: the button and the hours are one line rather than
   two stacked blocks, which is what keeps the copy column close to the height of the
   photograph beside it. */
@media (min-width: 620px) {
  .stage__actions { flex-direction: row; align-items: center; gap: 1.5rem; }
  .stage__pitch .btn { width: auto; }
}

/* ---- Hero photograph -------------------------------------------------------
   Bleeds through the frame padding to the frame edge, the way the reference runs a
   full-bleed photograph. object-fit keeps it filling the column at any height; the
   source is 750x499 and the column is never wider than that, so the rendered scale
   stays at or below 1x and the picture is never stretched. object-position holds the
   left of the frame, where the nurse, the syringe and the client all sit. */
.stage__figure {
  /* Stacked: bleeds to the side edges only, so the row gap above it survives. */
  margin: 0 calc(var(--stage-px) * -1);
  min-width: 0;
  overflow: hidden;
}
.stage__figure picture { display: block; height: 100%; }
.stage__figure img {
  display: block;
  width: 100%;
  /* The source is 750px wide. Stacked, the bleeding figure is wider than that from
     roughly 770px up, so the box is capped at the native width and centred rather than
     letting the picture upscale. */
  max-width: 750px;
  margin-inline: auto;
  height: 100%;
  min-height: clamp(13rem, 8rem + 20vw, 20rem);
  object-fit: cover;
  object-position: 34% 50%;
}

@media (min-width: 940px) {
  .stage__figure {
    margin: calc(var(--stage-pt) * -1) calc(var(--stage-px) * -1) 0 0;
    align-self: stretch;
  }
  /* The source is 750x499 and there is no larger original. object-fit: cover would
     happily scale it to fill a 680px-tall column — a 1.37x upscale — so the box is
     capped at the native height. Below that cap the cover scale is always <= 1x. */
  .stage__figure img { min-height: 0; max-width: none; max-height: 499px; }
}


/* Everything inside the stage sits on ink, so it takes the dark-surface forms of the
   accent: gold buttons and gold stars, never bronze or ink-on-ink. */
.stage .btn { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.stage .btn:hover { background: #e0bd4d; border-color: #e0bd4d; }
.stage .rating__stars path { fill: var(--gold); }
.stage .rating__value { color: var(--shell); }
.stage .rating__label { color: var(--body-on-ink); border-bottom-color: var(--rule-dark); }
.stage .rating:hover .rating__label { border-bottom-color: var(--gold); }
.stage .eyebrow { color: var(--gold); }






/* ---- Hero proof panel ------------------------------------------------------
   Four verifiable facts, set as type. This was six pill-shaped badges with icons:
   six items forced each one small, and small is what read as cheap. Four items at
   real size fill the same column and can be read at a glance.

   Hairline gold rules between the cells, no boxes, no pills, no icons in circles.
   The restraint is the premium signal — but restraint is about ornament, not scale,
   so the type is set as large as the column allows. */
.proof {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  list-style: none;
  margin: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem) 0 0;
  padding: 0;
  max-width: none;
  border-top: 1px solid var(--rule-dark);
}
.proof__item {
  display: flex;
  align-items: center;
  padding: clamp(.9rem, .7rem + .9vw, 1.6rem) 0;
  border-bottom: 1px solid var(--rule-dark);
  color: var(--shell);
  font-size: clamp(1.0625rem, .98rem + .38vw, 1.375rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -.012em;
  line-height: 1.2;
}

/* 2x2 from the point the cells can hold their phrase on one or two lines. Odd cells
   carry the vertical rule, so the divider never doubles up at the column seam. */
@media (min-width: 620px) {
  .proof { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .proof__item { padding-inline: clamp(1rem, .5rem + 1.6vw, 1.9rem); }
  .proof__item:nth-child(odd) {
    padding-left: 0;
    border-right: 1px solid var(--rule-dark);
  }
  .proof__item:nth-child(even) { padding-right: 0; }
}

@media (min-width: 940px) {
  .proof { margin-top: 0; }
}

.stage__trust {
  margin-top: clamp(2rem, 1.5rem + 2vw, 3rem);
  border-bottom: 0;
  border-top-color: var(--rule-dark);
}
.stage__trust li { border-top-color: var(--rule-dark); }


/* --------------------------------------------------------------------------
   8. The fee schedule — signature element
   -------------------------------------------------------------------------- */

.schedule {
  margin: 0;
  max-width: 44rem;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

.schedule dl { margin: 0; }
.schedule__group + .schedule__group { margin-top: clamp(2.75rem, 2rem + 2vw, 4rem); }

/* An <h3> rather than a <p>: the caption genuinely heads its section, and a <p> was not
   a valid child of <dl> before the list was restructured. Styled as an eyebrow. */
.schedule__caption {
  font-size: var(--t-eyebrow);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--bronze);
  padding-bottom: .6rem;
  border-bottom: 1px solid var(--rule-strong);
  margin: 0 0 .25rem;
  font-stretch: 100%;
}
.band--ink .schedule__caption { color: var(--gold); border-bottom-color: var(--rule-dark); }

.fee {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  padding: .95rem 0;
  border-bottom: 1px solid var(--rule);
}
.band--ink .fee { border-bottom-color: var(--rule-dark); }

.fee__name {
  display: flex;
  align-items: baseline;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-weight: 400;
  color: var(--ink);
}
.band--ink .fee__name { color: var(--shell); }

/* Dotted leader. Presentational, hidden from assistive tech — the dt/dd
   pairing already conveys the relationship. */
.fee__dots {
  flex: 1 1 auto;
  min-width: 1.25rem;
  align-self: flex-end;
  margin: 0 .5rem .34em;
  border-bottom: 1px dotted var(--rule-strong);
}
.band--ink .fee__dots { border-bottom-color: var(--rule-dark); }

.fee__price {
  margin: 0;
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.band--ink .fee__price { color: var(--gold); }

/* Rows where the price genuinely depends on the patient. The row stays in the
   list and says why, rather than being omitted and forcing a phone call. */
.fee__price--quoted {
  font-weight: 400;
  font-size: var(--t-small);
  color: var(--body);
  white-space: normal;
  text-align: right;
}
.band--ink .fee__price--quoted { color: var(--body-on-ink); }

/* Two-line rows: anatomical name, then plain English underneath. */
.fee--area { align-items: start; padding: 1.3rem 0; }
.fee--area .fee__name { flex-direction: column; gap: .15rem; }
.fee--area .fee__term { font-weight: 600; }
.fee--area .fee__gloss { font-size: var(--t-small); color: var(--body); line-height: 1.45; }
.band--ink .fee--area .fee__gloss { color: var(--body-on-ink); }
.fee--area .fee__dots { display: none; }
.fee--area .fee__price { max-width: 15rem; }

.schedule__note {
  margin-top: 1.6rem;
  font-size: var(--t-small);
  line-height: 1.6;
  max-width: 46ch;
  color: var(--body);
}

/* The dotted leader survives to 360px on plain name/price rows. It is the signature
   element of the page and it still fits: "Bunny lines … $100" leaves roughly 180px of
   leader inside a 320px content column. Only .fee--area rows stack — those carry a
   gloss under the name and a sentence where the price goes, and they have never had
   a leader at any width. */
@media (max-width: 560px) {
  .fee--area { flex-direction: column; align-items: stretch; gap: .2rem; }
  .fee--area .fee__price, .fee__price--quoted {
    text-align: left; max-width: none;
  }
  .fee__price { font-size: 1.0625rem; }
}

/* --------------------------------------------------------------------------
   9. Service cards
   -------------------------------------------------------------------------- */

.cards {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.card { display: flex; flex-direction: column; }

/* Typographic cards — no image. The stock photography here was small, generic and
   added noise; a hairline rule and the type do the work. Also removes four image
   requests from the homepage. */
.cards--plain .card { border-top: 1px solid var(--rule); padding-top: 1.15rem; }
.cards--plain .card h3 { margin-top: 0; }
.card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border: 1px solid var(--rule); }
.card h3 { margin: 1rem 0 .5rem; }

/* The /services grid. Twelve cards rather than four, so they run three-up on a wide
   screen and the starting price sits directly under the name — that is the number
   people are scanning for, and it is the reason the grid exists rather than a list. */
.services-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
.service-card__price {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--bronze);
  margin: 0 0 .55rem;
}
.service-card__more { margin-top: auto; padding-top: .9rem; }
.service-card p { max-width: none; }
.card p { font-size: var(--t-small); line-height: 1.6; flex: 1 1 auto; margin-bottom: 1rem; }

/* --------------------------------------------------------------------------
   10. Prose blocks, split columns, founder
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
}
@media (min-width: 780px) { .split { grid-template-columns: 1fr 1fr; } }

.split--portrait { align-items: start; }
@media (min-width: 780px) {
  .split--portrait { grid-template-columns: minmax(0, 300px) 1fr; }
}
.split--portrait img { width: 100%; border: 1px solid var(--rule); }

.steps { display: grid; gap: 1.75rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); padding: 0; margin: 0; list-style: none; }
.steps li { border-top: 1px solid var(--rule); padding-top: 1rem; }
.steps h3 { font-size: 1.0625rem; margin-bottom: .4rem; }
.steps p { font-size: var(--t-small); line-height: 1.6; }

.quotes {
  display: grid;
  gap: clamp(2rem, 1.4rem + 2vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  padding: 0; margin: 0; list-style: none;
}
.quotes blockquote { margin: 0; border-top: 1px solid var(--rule); padding-top: 1.15rem; }
.quotes p { font-size: 1rem; line-height: 1.65; max-width: 42ch; }
.quotes cite {
  display: block; margin-top: 1rem;
  font-size: var(--t-micro); font-style: normal; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--bronze);
}

/* --------------------------------------------------------------------------
   11. FAQ
   -------------------------------------------------------------------------- */

.faq { max-width: 46rem; }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  cursor: pointer;
  padding: 1.05rem 2rem 1.05rem 0;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '';
  position: absolute;
  right: .35rem;
  top: 1.5rem;
  width: .55rem; height: .55rem;
  border-right: 2px solid var(--bronze);
  border-bottom: 2px solid var(--bronze);
  transform: rotate(45deg);
  transition: transform .18s var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 1.7rem; }
.faq details > div { padding-bottom: 1.15rem; }
.faq p { font-size: var(--t-body); }


/* --------------------------------------------------------------------------
   11b. Reviews carousel
   Manual scroll-snap, no autoplay. Auto-advancing text would need a visible
   pause control under WCAG 2.2.2 and would fight the restrained-motion rule;
   a snap track reads as "scrolling" and stays keyboard- and swipe-native.
   -------------------------------------------------------------------------- */

.reviews { position: relative; }

.reviews__track {
  /* Flex, not grid: grid-auto-columns with a minmax floor of 0 lets the tracks
     collapse instead of overflowing, which squashed six cards into the container
     rather than scrolling them. flex: 0 0 <basis> cannot shrink. */
  display: flex;
  gap: clamp(1rem, 2vw, 1.5rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-block: .35rem;
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
}
.reviews__track::-webkit-scrollbar { display: none; }
.reviews__track:focus-visible { outline: 3px solid var(--bronze); outline-offset: 4px; }

.review {
  flex: 0 0 min(275px, 82%);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  background: var(--shell);
  border: 1px solid var(--rule);
  padding: clamp(1.4rem, 1.1rem + 1vw, 2rem);
}
.band--sand .review { background: #FFFFFF; }

@media (min-width: 780px)  { .review { flex-basis: calc((100% - 1.5rem) / 2); } }
@media (min-width: 1080px) { .review { flex-basis: calc((100% - 3rem) / 3); } }

.review__stars { display: flex; gap: .15rem; }
/* Relative, so the star row stays a compact inline element at 360px instead of a
   display graphic. The width/height attributes on the tag hold the ratio, so this
   cannot shift layout while the sheet is loading. */
.review__stars svg { width: clamp(12px, 3.4vw, 15px); height: auto; aspect-ratio: 1; fill: var(--gold); }

.review blockquote { margin: 0; flex: 1 1 auto; }
.review blockquote p {
  margin: 0;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ink);
  max-width: none;
  text-wrap: pretty;
}

.review__by {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding-top: .9rem;
  border-top: 1px solid var(--rule);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--bronze);
}
.review__by svg { width: 14px; height: 14px; flex: 0 0 auto; }
.review__src { margin-left: auto; color: var(--body); letter-spacing: .06em; }

.reviews__nav { display: flex; gap: .6rem; justify-content: center; margin-top: 1.75rem; }
.reviews__nav button {
  width: 44px; height: 44px;
  display: inline-grid; place-items: center;
  background: none;
  border: 1px solid var(--rule-strong);
  color: var(--ink);
  cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.reviews__nav button:hover:not(:disabled) { background: var(--ink); color: var(--shell); border-color: var(--ink); }
.reviews__nav button:disabled { opacity: .3; cursor: default; }
.reviews__nav svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* --------------------------------------------------------------------------
   12. Locations
   -------------------------------------------------------------------------- */

.locations { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.location { border-top: 2px solid var(--bronze); padding-top: 1.1rem; }
.location h2, .location h3 { font-size: var(--t-h3); margin-bottom: .5rem; }
.location address { font-style: normal; line-height: 1.65; }
.location .arrow-link { margin-top: .9rem; }


/* Locations hub — both locations get identical treatment, no visual hierarchy. */
.venues { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 820px) { .venues { grid-template-columns: 1fr 1fr; } }

.venue { border-top: 2px solid var(--bronze); padding-top: 1.25rem; }
.venue h2 { font-size: var(--t-h3); margin-bottom: .75rem; }
.venue address { font-style: normal; line-height: 1.65; margin-bottom: 1rem; }
.venue figure { margin: 0 0 1rem; }

/* The map is a picture, not an embed. It is composited from OpenStreetMap tiles when the
   site is built and rendered at 2x, so it needs no runtime request to anyone — which is
   what lets the privacy policy say nothing loads from another company. It replaced a
   click-to-load facade over a Google Maps iframe; that iframe pulled 38 requests across
   seven Google hosts, and the button was a step between the visitor and a map they had
   already decided they wanted. The whole picture links to driving directions. */
.venue__map > a {
  display: block;
  border: 1px solid var(--rule);
  transition: border-color .12s var(--ease);
}
.venue__map > a:hover { border-color: var(--bronze); }
.venue__map > a:focus-visible { outline: 3px solid var(--bronze); outline-offset: 3px; }
.venue__map img { width: 100%; border: 0; }
.venue img { width: 100%; border: 1px solid var(--rule); }
.venue figcaption { font-size: .75rem; color: var(--body); margin-top: .4rem; }
.venue figcaption a { color: inherit; }
.venue dl { display: grid; grid-template-columns: auto 1fr; gap: .4rem 1rem; margin: 0 0 1.15rem; }
.venue dt { font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--bronze); padding-top: .15rem; }
.venue dd { margin: 0; }

.deflist { display: grid; gap: .85rem 2rem; margin: 0; }
@media (min-width: 620px) { .deflist { grid-template-columns: auto 1fr; } }
.deflist dt { font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--bronze); padding-top: .18rem; }
.deflist dd { margin: 0; }

/* --------------------------------------------------------------------------
   13. Footer
   -------------------------------------------------------------------------- */

.site-footer { background: var(--ink); color: var(--body-on-ink); padding-block: var(--section) 2.5rem; font-size: var(--t-small); }
.site-footer h2, .site-footer h3 { color: var(--shell); font-size: 1rem; margin-bottom: .75rem; }
.site-footer a { color: var(--gold); text-decoration-color: var(--rule-dark); }
.site-footer a:hover { text-decoration-color: var(--gold); }
.site-footer address { font-style: normal; line-height: 1.7; }

.site-footer__grid { display: grid; gap: 2.25rem; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.site-footer ul { list-style: none; padding: 0; margin: 0; line-height: 2; }

/* The services column carries all ten service links, because a link from every page to
   every service page is worth having and the hub alone would not give that. Stacked one
   per line at a 44px tap height it ran to 523px on a phone and pushed the whole footer
   to a quarter of the document; two columns halve it without dropping a link. */
.footer-services { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
@media (min-width: 560px) and (max-width: 900px) {
  .footer-services { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 901px) { .footer-services { display: block; } }

/* Not a link, so it should not sit in the list looking like one that failed to render. */
.footer-note {
  color: var(--body-on-ink);
  line-height: 1.5;
  padding-top: .35rem;
  font-size: var(--t-micro);
  letter-spacing: .01em;
}

.site-footer__base {
  margin-top: 2.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule-dark);
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.5rem;
  justify-content: space-between;
}

/* Clearance for the fixed Call/Book bar. It goes on the footer, not on <body>: padding
   on the body reserves the space in the page background, which reads as a cream strip
   between the ink footer and the ink bar. Padding on the last element reserves the same
   space in the footer's own colour. The figure is the bar (3.25rem + its 1px border)
   plus breathing room, and it must stay in step with --callbar-h above. */
@media (max-width: 720px) {
  .site-footer {
    padding-bottom: calc(3.25rem + 1px + 1.5rem + env(safe-area-inset-bottom, 0px));
  }
  /* Once the email address wraps below it at 360px, the separator is left stranded at
     the end of the line above. */
  .site-footer__base .sep { display: none; }
}

/* --------------------------------------------------------------------------
   12b. Legal pages
   -------------------------------------------------------------------------- */

.legal { max-width: 68ch; }
/* Bare URLs sometimes appear as link text here; without this they overflow at 360px. */
.legal a { overflow-wrap: anywhere; }

/* Draft notice. Deliberately loud — these documents are not approved. */
.notice {
  border: 2px solid var(--bronze);
  background: var(--sand);
  padding: 1.1rem clamp(1rem, 2vw, 1.4rem);
  margin: 0 0 2.5rem;
  max-width: 68ch;
}
.notice p { font-size: var(--t-small); line-height: 1.6; }
.notice p:last-child { margin-bottom: 0; }
.notice strong { color: var(--ink); }
.legal h2 { font-size: 1.375rem; margin-top: 2.5rem; }
.legal h2:first-of-type { margin-top: 1.5rem; }
.legal ul { padding-left: 1.25rem; }
.legal li { margin-bottom: .4rem; }
.legal__meta {
  font-size: var(--t-small);
  border-left: 2px solid var(--bronze);
  padding: .1rem 0 .1rem 1rem;
  margin-bottom: 2.5rem;
}

/* --------------------------------------------------------------------------
   13b. Touch targets
   WCAG 2.5.8 exempts links inline in a sentence, but links that stand alone on
   their own line — phone numbers in an address, footer nav, definition lists —
   get a real hit area on touch devices. The floor here is 44px, not the 24px the
   AA criterion asks for: 24 passes an audit, 44 is what a thumb actually needs.
   -------------------------------------------------------------------------- */

@media (pointer: coarse), (max-width: 720px) {
  .site-footer address a,
  .site-footer ul a,
  .location address a,
  .deflist dd a,
  .venue dd a,
  .venue address a,
  .card h2 a,
  .card h3 a,
  main p > a:only-child:not(.rating):not(.arrow-link) {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
  /* .arrow-link draws its underline with a border and its arrow with ::after, so it
     must not become a flex box: the rule would run the full width of the card and the
     space before the arrow would collapse. It takes its 44px band from padding above
     the text instead, which keeps the underline sitting 2px under the words. */
  .arrow-link {
    display: inline-block;
    /* Computed from the line box rather than fixed, because .arrow-link appears at more
       than one font size — a flat .9rem cleared 44px in body copy and came up 4px short
       inside the smaller type of a card on /services. */
    padding-top: max(.9rem, calc(46px - 1.75em));
  }
  /* These two can sit inside a sentence, so they stay inline and take the height
     band only — going full-width would force a line break mid-paragraph. */
  .site-footer p a,
  .site-footer__base a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* .rating is an inline-flex cluster of its own; forcing it to inline-block above
     broke it onto two lines. It only needs the hit area. */
  .rating { min-height: 44px; }
  .header-trust { min-height: 44px; }
  .nav a { min-height: 44px; display: flex; align-items: center; }
  .reviews__nav button { min-width: 44px; min-height: 44px; }
  .site-footer ul { line-height: 1.6; }
  .site-footer ul li + li { margin-top: .35rem; }
}

/* --------------------------------------------------------------------------
   14. Motion — restrained. Scroll reveal and hover only.
   -------------------------------------------------------------------------- */

/* Content is visible by default and only hidden once JS confirms it can
   reveal it, so nothing is lost if the script never runs. */
.js [data-reveal] { opacity: 0; transform: translateY(12px); }
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity .38s var(--ease), transform .38s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* --------------------------------------------------------------------------
   15. Print
   -------------------------------------------------------------------------- */

@media print {
  .site-header, .callbar, .site-footer, .btn-row { display: none; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .band { padding-block: 1rem; }
  .fee { break-inside: avoid; }
}
