/* ==========================================================================
   Constanza Acevedo — Fisioterapia pediátrica
   Derived strictly from Branding/brand.md and Branding/tokens.css.
   No colours, sizes or timings that are not defined there.

   Built mobile-first: the base rules ARE the phone layout.
   Breakpoints widen it; they never rebuild it.
   ========================================================================== */

/* Fonts are self-hosted — see assets/fonts/fonts.css, linked from the page
   head. The site makes no third-party request of any kind. */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour */
  --c-eggshell:  #F8F6F0;
  --c-paper:     #FDFCF9;
  --c-forest:    #3D4A33;
  --c-sage:      #8F9878;
  --c-sage-tint: #E4E7DC;
  --c-taupe:     #C3B4A0;
  --c-clay:      #B87B5C;
  --c-ink:       #2B2B24;
  --c-ink-muted: #6B6B5E;
  --c-white:     #FFFFFF;

  /* Sage is legible on forest (5.16:1) but NOT on eggshell (2.80:1).
     brand.md §3 forbids the latter; tokens.css shipped it in .eyebrow.
     Light-surface eyebrows therefore use ink-muted (5.00:1). */
  --c-sage-on-dark: #B9C4A2;

  --bg-page:         var(--c-eggshell);
  --bg-surface:      var(--c-paper);
  --bg-inverse:      var(--c-forest);
  --text-body:       var(--c-ink);
  --text-muted:      var(--c-ink-muted);
  --text-on-dark:    var(--c-eggshell);
  --border-hairline: rgba(195, 180, 160, 0.4);

  --btn-primary-bg:    var(--c-forest);
  --btn-primary-text:  var(--c-white);
  --btn-primary-hover: #33402B;

  /* Typography */
  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-body:    'Figtree', -apple-system, BlinkMacSystemFont, sans-serif;

  --fs-display: 2.25rem;   /* 36 — mobile first */
  --fs-h1:      1.875rem;  /* 30 */
  --fs-h2:      1.5rem;    /* 24 */
  --fs-h3:      1.25rem;   /* 20 */
  --fs-body-lg: 1.125rem;  /* 18 */
  --fs-body:    1rem;      /* 16 — never smaller */
  --fs-small:   0.875rem;  /* 14 */
  --fs-eyebrow: 0.8125rem; /* 13 */

  --lh-display: 1.08;
  --lh-heading: 1.2;
  --lh-body:    1.7;
  --ls-eyebrow: 0.08em;

  /* Spacing */
  --sp-1: 0.25rem; --sp-2: 0.5rem;  --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-6: 1.5rem;  --sp-8: 2rem;    --sp-12: 3rem;   --sp-16: 4rem;
  --sp-24: 6rem;   --sp-32: 8rem;

  --section-y:     3.5rem;  /* 56 mobile */
  --container-max: 1200px;
  --measure-max:   680px;
  --gutter:        1.25rem;

  /* Shape */
  --radius-card:  12px;
  --radius-input: 8px;
  --radius-pill:  999px;
  /* brand.md §5 specifies 200px 200px 12px 12px. A fixed 200px reads as a
     half-dome at 343px wide and a gentle arc at 560px. Percentages hold the
     same silhouette at every size. */
  --radius-arch: 42% 42% var(--radius-card) var(--radius-card)
               / 33% 33% var(--radius-card) var(--radius-card);

  /* Motion */
  --ease:          cubic-bezier(0.22, 1, 0.36, 1);
  --dur-hover:     200ms;
  --dur-reveal:    500ms;
  --reveal-offset: 8px;

  /* Height of the persistent mobile action bar, so nothing hides behind it */
  --actionbar-h: 4.5rem;
}

@media (min-width: 48em) {
  :root {
    --fs-display: 3.5rem;
    --fs-h1:      2.75rem;
    --fs-h2:      2rem;
    --fs-h3:      1.375rem;
    --section-y:  6rem;
    --gutter:     2.5rem;
    --actionbar-h: 0rem;
  }
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  /* Anchored sections must not land under the sticky header */
  scroll-padding-top: 5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg-page);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  text-align: left;              /* never justify — brand.md §4 */
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Room for the persistent booking bar */
  padding-bottom: var(--actionbar-h);
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul { list-style: none; }
::selection { background: var(--c-sage-tint); color: var(--c-ink); }

h1, h2 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--lh-heading);
  color: var(--c-forest);
  letter-spacing: -0.01em;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3, h4 {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.3;
  color: var(--c-forest);
}

p { max-width: var(--measure-max); }

/* Visible focus everywhere — never removed */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--c-forest);
  outline-offset: 3px;
  border-radius: 2px;
}
.on-dark a:focus-visible,
.on-dark button:focus-visible {
  outline-color: var(--c-eggshell);
}

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

.skip-link {
  position: absolute; top: -100%; left: var(--gutter); z-index: 200;
  background: var(--c-forest); color: var(--c-white);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-input);
}
.skip-link:focus { top: var(--sp-2); }

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

section { padding-block: var(--section-y); }

/* Section rhythm is ONE --section-y between sections, not two.
   Padding on both sides of adjacent sections doubles it: 192px of empty
   ground at desktop, which reads as a hole rather than a rhythm.

   Sections that paint their own background (.finder, .about, .contact) keep
   both sides, because there the padding sits inside the colour band. Those
   carry a class; the transparent ones are identified by having none. */
section:not([class]) + section:not([class]) { padding-top: 0; }

/* Now that grounds alternate, the same doubling came back wherever a
   transparent section meets a coloured band: 96px below the last line, then
   96px above the next, with the colour changing halfway through. 192px of
   nothing with a seam in the middle reads as a hole, and the seam stops
   registering as a division at all.

   Where the ground changes, the change is itself the divider, so it needs
   less air around it, not more. The band keeps the padding that sits inside
   its own colour; whatever abuts it contributes half. */
section:has(+ section[class]) { padding-bottom: calc(var(--section-y) / 2); }
section[class] + section     { padding-top: calc(var(--section-y) / 2); }

/* The section above already contributes its bottom padding, so no top margin
   here. It does need space BELOW: without it the image butts straight into the
   forest band and its provisional label collides with the edge. */
/* No .band-photo in the markup at present: the photograph between services
   and the finder was pulled on 2026-08-26 rather than replaced. The rules are
   kept because the slot is expected back once there is a photograph that
   reads as a pause. Half a unit, for the same reason the sections halve at a
   change of ground -- the forest band below supplies its own inside its
   colour. */
.band-photo { margin-top: 0; margin-bottom: calc(var(--section-y) / 2); }

.measure { max-width: var(--measure-max); }

.eyebrow {
  display: block;
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);       /* not sage — see token note */
  margin-bottom: var(--sp-3);
}
.on-dark .eyebrow { color: var(--c-sage-on-dark); }

/* Clay appears here and in almost nowhere else — brand.md §3 ratio rule */
.accent-rule {
  width: 48px; height: 1px;
  background: var(--c-clay);
  border: 0;
  margin-bottom: var(--sp-6);
}

.section-head { margin-bottom: var(--sp-8); }
.section-head p { color: var(--text-muted); margin-top: var(--sp-4); }

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 3rem;                /* ≥44px touch target */
  padding: var(--sp-3) var(--sp-6);
  border-radius: var(--radius-input);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;      /* a squeezed flex item would wrap the label */
  transition: background-color var(--dur-hover) var(--ease),
              border-color var(--dur-hover) var(--ease),
              color var(--dur-hover) var(--ease);
  touch-action: manipulation;
}
.btn--primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-text);
}
.btn--primary:hover { background: var(--btn-primary-hover); }

.btn--ghost {
  border: 1px solid var(--c-forest);
  color: var(--c-forest);
}
.btn--ghost:hover { background: var(--c-sage-tint); }

.on-dark .btn--ghost {
  border-color: rgba(248, 246, 240, 0.5);
  color: var(--c-eggshell);
}
.on-dark .btn--ghost:hover {
  border-color: var(--c-eggshell);
  background: rgba(248, 246, 240, 0.08);
}

.btn--wa svg { width: 1.15em; height: 1.15em; flex: none; }

/* On a phone every standalone action runs the full measure, so they share
   one left and one right edge instead of three ragged widths down the page.
   The action bar is excluded — its two buttons sit side by side. */
@media (max-width: 47.99em) {
  .hero__actions .btn,
  .contact__actions .btn,
  .finder__foot .btn,
  .extra .btn,
  .visit__cta,
  .navpanel .btn { width: 100%; }
  .extra .btn, .visit__cta { align-self: stretch; }
}

/* --------------------------------------------------------------------------
   5. Header and navigation
   -------------------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 90;
  background: rgba(248, 246, 240, 0.94);
  -webkit-backdrop-filter:
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-hairline);
}
.header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 4.25rem;
}
.header__logo {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 3rem;
}
/* The wordmark is the whole lockup now, so it can carry a little more
   height without the header growing. */
.header__logo img { height: 3rem; width: auto; }

.header__nav { display: none; }
.header__actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }

/* The isolated action at the far right — the pattern brand.md's reference
   notes describe. Without it the language switcher was left standing in for
   a primary action, which is what made the header read as unbalanced.
   Phone keeps the persistent bottom bar instead, so it is hidden there. */
.header__cta { display: none; }


/* Language switcher — stays reachable on mobile, never hidden */
.lang {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-small);
}
.lang a, .lang span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;     /* ≥44px in both axes */
  min-height: 2.75rem;
  font-size: var(--fs-small);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}
.lang [aria-current="true"] {
  color: var(--c-forest);
  font-weight: 600;
  box-shadow: inset 0 -1px 0 var(--c-clay);   /* clay accent, hairline only */
}

.burger {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 2.75rem; height: 2.75rem;
  padding: 0 0.55rem;
}
.burger i {
  display: block; height: 1.5px; width: 100%;
  background: var(--c-forest);
  transition: transform 300ms var(--ease), opacity 200ms var(--ease);
}
.nav-open .burger i:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-open .burger i:nth-child(2) { opacity: 0; }
.nav-open .burger i:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* Full-screen panel */
.navpanel {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--c-eggshell);
  padding: 6rem var(--gutter) var(--sp-8);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 350ms var(--ease), transform 350ms var(--ease), visibility 350ms;
}
.nav-open .navpanel { opacity: 1; visibility: visible; transform: none; }
.navpanel a {
  font-family: var(--font-display);
  font-size: 1.75rem;
  color: var(--c-forest);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--border-hairline);
}
/* `.navpanel a` outranks `.btn`, so without this the action renders as a
   28px serif nav link with a bottom border — 67px tall instead of 48. */
.navpanel .btn {
  margin-top: var(--sp-8);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  padding: var(--sp-3) var(--sp-6);
  border-bottom: 0;
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */

.hero { padding-block: var(--sp-12) var(--sp-8); }
.hero__headline { margin-bottom: var(--sp-6); }
.hero__lede {
  font-size: var(--fs-body-lg);
  color: var(--text-muted);
  margin-bottom: var(--sp-8);
}
.hero__actions { display: flex; flex-direction: column; gap: var(--sp-3); }
.hero__figure { margin-top: var(--sp-12); }

/* Trust strip — three glance-level facts, above the fold on a phone */
.trust {
  background: var(--c-forest);
  color: var(--c-sage-on-dark);
}
.trust ul {
  display: grid;
  gap: 0;
}
.trust li {
  font-size: var(--fs-body);
  line-height: 1.5;
  padding: var(--sp-4) 0;
  color: var(--text-on-dark);
}
.trust li + li { border-top: 1px solid rgba(248, 246, 240, 0.18); }

/* --------------------------------------------------------------------------
   7. Photography placeholders
   Every one states the shot and its aspect ratio. Replaced by real
   photography — brand.md §7 forbids generated images of children.
   -------------------------------------------------------------------------- */

.photo {
  position: relative;
  background: var(--c-sage-tint);
  border: 1px solid var(--border-hairline);
  display: flex;
  align-items: flex-end;
  padding: var(--sp-4);
  overflow: hidden;
}
.photo--arch  { aspect-ratio: 4 / 5; border-radius: var(--radius-arch); }
.photo--card  { aspect-ratio: 4 / 5; border-radius: var(--radius-card); }
.photo--wide  { aspect-ratio: 3 / 2; border-radius: var(--radius-card); }
.photo--square{ aspect-ratio: 1 / 1; border-radius: var(--radius-card); }
.photo--band  { aspect-ratio: 3 / 2; border-radius: var(--radius-card); }

/* The image fills its reserved frame. width/height on the <img> keep the
   space reserved before it loads, so nothing shifts. */
.photo > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Grade: pulls the photography a touch closer to the palette. Raise
     --photo-grade toward 0.12 for a stronger unify, 0 to disable. */
  filter: saturate(var(--photo-sat, 0.95));
}
.photo:has(img)::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--c-clay);
  opacity: var(--photo-grade, 0.05);
  mix-blend-mode: soft-light;
  pointer-events: none;
}

/* ---- PROVISIONAL MARKING -------------------------------------------------
   Every AI placeholder carries a visible flag. brand.md §7 requires real
   photography in production and §13 #11 bans generated images of children or
   of Constanza from the shipped site.

   TO REMOVE WHEN THE REAL SHOOT LANDS: delete this one rule. The
   data-placeholder attributes can then be stripped at leisure.
   ------------------------------------------------------------------------- */
.photo[data-placeholder]::before {
  content: 'Imagen provisional';
  position: absolute;
  z-index: 2;
  left: var(--sp-3);
  bottom: var(--sp-3);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--c-ink-muted);
  background: rgba(248, 246, 240, 0.92);
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-pill);
}

@media (min-width: 48em) {
  .photo--band { aspect-ratio: 21 / 9; }
}

.photo__note {
  position: relative;
  font-size: var(--fs-eyebrow);
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-forest);
  opacity: 0.75;
}
.photo__note b { display: block; font-weight: 600; }

/* --------------------------------------------------------------------------
   8. Symptom cards
   -------------------------------------------------------------------------- */

.symptoms__grid {
  display: grid;
  gap: var(--sp-4);
  margin-bottom: var(--sp-8);
}
.symptom {
  background: var(--bg-surface);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
}
.symptom h3 { margin-bottom: var(--sp-3); }
.symptom p { color: var(--text-muted); font-size: var(--fs-body); }

.symptoms__closing {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: 1.45;
  color: var(--c-forest);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--border-hairline);
}

/* --------------------------------------------------------------------------
   9. Services
   -------------------------------------------------------------------------- */

.services__grid { display: grid; gap: var(--sp-8); }

.service {
  background: var(--bg-surface);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
  display: flex;
  flex-direction: column;        /* so service__who can sit at the bottom */
}
.service > .photo { margin-bottom: var(--sp-6); }
.service h3 { font-size: var(--fs-h3); margin-bottom: var(--sp-3); }
.service__lead { color: var(--text-body); margin-bottom: var(--sp-6); }
.service__who {
  font-size: var(--fs-small);
  color: var(--text-muted);
  margin-top: auto;              /* pins both to the bottom of the card */
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-hairline);
}

/* Long lists collapse into accordions rather than scrolling for screens */
.acc { border-top: 1px solid var(--border-hairline); }
.acc__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  min-height: 3rem;
  padding: var(--sp-4) 0;
  text-align: left;
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--c-forest);
}
.acc__icon {
  flex: none;
  width: 1rem; height: 1rem;
  position: relative;
}
.acc__icon::before,
.acc__icon::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  background: var(--c-sage);
  transition: transform var(--dur-hover) var(--ease), opacity var(--dur-hover) var(--ease);
}
.acc__icon::before { width: 100%; height: 1.5px; }
.acc__icon::after  { width: 1.5px; height: 100%; }
.acc__btn[aria-expanded="true"] .acc__icon::after { transform: scaleY(0); opacity: 0; }

.acc__panel { display: none; padding-bottom: var(--sp-4); }
.acc__panel[data-open] { display: block; }
.acc__panel li {
  position: relative;
  padding: var(--sp-2) 0 var(--sp-2) var(--sp-6);
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-hairline);
}
.acc__panel li:last-child { border-bottom: 0; }
.acc__panel li::before {
  content: '';
  position: absolute;
  left: 0; top: 1.05em;
  width: 12px; height: 1px;
  background: var(--c-sage);
}

/* --------------------------------------------------------------------------
   10. The milestone finder — the signature element
   Dark section so everything quiet around it can carry this.
   -------------------------------------------------------------------------- */

.finder {
  background: var(--bg-inverse);
  color: var(--text-on-dark);
}
.finder h2 { color: var(--c-eggshell); }
/* `p` selector needed to outrank `.section-head p`, which would otherwise
   paint this ink-muted on forest — 1.75:1, effectively invisible. */
p.finder__sub {
  color: rgba(248, 246, 240, 0.82);   /* ≥4.5:1 on forest */
  font-size: var(--fs-body-lg);
  margin-top: var(--sp-4);
}

/* The age band: horizontally scrollable, snap-aligned, also tappable.
   No dragging, no precision, and chevrons for one-handed use. */
.band { margin-top: var(--sp-8); }
/* Centred so it sits over the hairline that divides the two columns below.
   max-width matters: this is a <p>, so the global `p { max-width: 680px }`
   was capping it and centring the readout inside a 680px box pinned left
   rather than across the section. */
.band__label {
  display: flex;
  flex-direction: column;      /* unit beneath the numeral, not beside it */
  align-items: center;
  max-width: none;
  gap: var(--sp-1);
  margin-bottom: var(--sp-6);
  text-align: center;
}
.band__age {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 12vw, 4.5rem);
  line-height: 0.95;
  color: var(--c-sage-on-dark);
  font-variant-numeric: tabular-nums;
}
.band__unit {
  font-size: var(--fs-small);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(248, 246, 240, 0.72);
}

/* The hint retires once she has touched it once. */
.band__hint {
  display: block;
  margin-bottom: var(--sp-4);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: rgba(248, 246, 240, 0.7);
  transition: opacity 400ms var(--ease);
}
.band.is-touched .band__hint { opacity: 0; }

/* ---- The deck ------------------------------------------------------------
   The card itself is the control: swipe it like a photo gallery. The target
   is the whole card, so nothing here needs precision. Dots give a tappable
   alternative and show position; arrows appear only where there is room.
   ------------------------------------------------------------------------- */
.deck-wrap { position: relative; margin-top: var(--sp-6); }

.deck {
  position: relative;
  display: flex;
  gap: var(--sp-4);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* Full-bleed track, inset cards: the next card peeks at the edge so the
     gesture is discoverable without a label saying so. */
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
}
.deck::-webkit-scrollbar { display: none; }

/* Spacers let the FIRST and LAST cards reach the centre. Without them card 1
   rests flush against the left edge while every other card centres — the
   whole strip appears to shift as you swipe off the first one. */
.deck::before,
.deck::after { content: ''; flex: 0 0 9%; }      /* (100% - 82%) / 2 */

.slide {
  /* Deliberately narrower than the frame so a neighbour shows on BOTH sides.
     Adapted from the Embla reference's variable-width rhythm: the peek is
     what makes the swipe self-evident, without a label explaining it. */
  flex: 0 0 82%;
  scroll-snap-align: center;
  border: 1px solid rgba(248, 246, 240, 0.22);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
  background: rgba(248, 246, 240, 0.03);
  opacity: 0.35;
  transition: opacity 400ms var(--ease),
              border-color 400ms var(--ease),
              background-color 400ms var(--ease);
}
.slide.is-active {
  opacity: 1;
  border-color: rgba(248, 246, 240, 0.42);
  background: rgba(248, 246, 240, 0.06);
}
@media (min-width: 48em) { .slide { flex: 0 0 78%; } }

.slide .panes { border-top: 0; margin-top: 0; }
.slide .pane:first-child { padding-top: 0; }

/* The two column headings are identical on all seven cards, so they are
   stated once above the deck rather than repeated inside every slide.
   Mobile keeps them in the cards, because there the two lists stack and each
   needs its own label next to it. */
.deck__labels { display: none; }

@media (min-width: 48em) {
  .deck__labels {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 78%;                        /* matches the slide width */
    margin: 0 auto var(--sp-3);
    padding-inline: var(--sp-6);       /* matches the slide padding */
  }
  .deck__labels span {
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--c-sage-on-dark);
  }
  .deck__labels span:first-child { padding-right: var(--sp-8); }
  .deck__labels span:last-child  { padding-left: var(--sp-8); }

  .deck { margin-inline: 0; padding-inline: 0; }
  .deck::before,
  .deck::after { flex-basis: 11%; }              /* (100% - 78%) / 2 */

  /* Kept in the DOM so each list stays labelled for screen readers. */
  .slide .pane h3 {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  /* Both columns must start on the same line. `:first-child` alone zeroed
     only the left one, leaving the right column 32px lower. */
  .slide .pane { padding-top: 0; }
}

.dots {
  display: flex;
  gap: 0;                     /* each 44px box supplies its own spacing */
  justify-content: center;
  margin-top: var(--sp-4);
}
.dot {
  flex: 0 0 44px;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
}
.dot i {
  display: block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgba(248, 246, 240, 0.35);
  transition: background var(--dur-hover) var(--ease),
              transform var(--dur-hover) var(--ease);
}
.dot[aria-selected="true"] i { background: var(--c-clay); transform: scale(1.6); }

/* Arrows are a desktop affordance — on a phone the swipe is the interface */
.deck__arrow { display: none; }
@media (min-width: 48em) {
  .deck__arrow {
    display: grid;
    place-items: center;
    position: absolute;
    top: 40%;
    z-index: 2;
    width: 2.75rem; height: 2.75rem;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(248, 246, 240, 0.35);
    background: var(--c-forest);
    color: var(--c-eggshell);
    transition: background-color var(--dur-hover) var(--ease),
                border-color var(--dur-hover) var(--ease),
                opacity var(--dur-hover) var(--ease);
  }
  .deck__arrow--prev { left: calc(var(--gutter) * -1); }
  .deck__arrow--next { right: calc(var(--gutter) * -1); }
  .deck__arrow:hover:not(:disabled) { background: #33402B; border-color: var(--c-eggshell); }
  .deck__arrow:disabled { opacity: 0.25; cursor: default; }
  .deck__arrow svg { width: 1rem; height: 1rem; }
}

.band__arrow {
  flex: none;
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  border: 1px solid rgba(248, 246, 240, 0.35);
  border-radius: var(--radius-pill);
  color: var(--c-eggshell);
  transition: background-color var(--dur-hover) var(--ease),
              border-color var(--dur-hover) var(--ease),
              opacity var(--dur-hover) var(--ease);
}
.band__arrow:hover:not(:disabled) { background: rgba(248, 246, 240, 0.1); }
.band__arrow:disabled { opacity: 0.3; cursor: default; }
.band__arrow svg { width: 1rem; height: 1rem; }



/* Two columns of content */
.panes {
  display: grid;
  gap: 0;
  margin-top: var(--sp-8);
  border-top: 1px solid rgba(248, 246, 240, 0.22);
  transition: opacity 350ms var(--ease);
}
.panes[data-fading] { opacity: 0.25; }
.pane { padding-block: var(--sp-6); }
.pane + .pane { border-top: 1px solid rgba(248, 246, 240, 0.22); }
.pane h3 {
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--c-sage-on-dark);
  /* A label, not a row. The rule beneath it is heavier than the ones between
     items, and the extra space below detaches it from the first entry —
     without it the heading reads as the first line of the list. */
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid rgba(185, 196, 162, 0.45);
}
.pane li {
  font-family: var(--font-display);
  font-size: var(--fs-body-lg);
  line-height: 1.45;
  color: rgba(248, 246, 240, 0.94);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid rgba(248, 246, 240, 0.14);
}
.pane li:last-child { border-bottom: 0; }

.finder__foot { margin-top: var(--sp-8); }
.finder__note {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: rgba(248, 246, 240, 0.78);   /* ≥4.5:1 — the prototype's 50% failed */
  max-width: 62ch;
  margin-bottom: var(--sp-6);
}

/* On wide screens the note and the action sit on one line instead of stacked,
   which halves the height of the foot and keeps the CTA in view. */
@media (min-width: 48em) {
  .finder__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-8);
  }
  .finder__note { margin-bottom: 0; max-width: 68ch; }
  .finder__foot .btn { flex: none; }
}

/* --------------------------------------------------------------------------
   11. First visit — steps and the annotated observation figure
   -------------------------------------------------------------------------- */

.steps {
  counter-reset: step;
  display: flex;
  flex-direction: column;
}
.visit__cta { margin-top: var(--sp-8); align-self: center; }

@media (min-width: 48em) {
  /* The four steps share whatever height the left column dictates, rather
     than stacking at their natural height and leaving a gap above the
     action. Growing the spacing beats padding the copy — §8 asks for short
     sentences, so the answer is more room, not more words. */
  .step { flex: 1; align-items: center; }
}
@media (max-width: 47.99em) { .visit__cta { align-self: stretch; } }
.step {
  display: flex;
  gap: var(--sp-4);
  padding-block: var(--sp-6);
  border-top: 1px solid var(--border-hairline);
}
.step:last-child { border-bottom: 1px solid var(--border-hairline); }
.step__num {
  flex: none;
  width: 2rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1.3;
  color: var(--c-taupe);
  font-variant-numeric: tabular-nums;
}
.step h3 { margin-bottom: var(--sp-2); }
.step p { color: var(--text-muted); }

/* Quiet labels pointing at what she actually observes.
   On a phone the leader lines are dropped and this becomes a caption list. */
/* Sits inside the left column of the first-visit section, filling the space
   the heading alone used to leave empty. */
.observe { margin-top: var(--sp-8); }
.observe__figure { position: relative; }
.observe__list { margin-top: var(--sp-6); display: grid; gap: var(--sp-4); }
.observe__item {
  display: flex;
  gap: var(--sp-3);
  align-items: baseline;
  font-size: var(--fs-small);
  color: var(--text-muted);
}
.observe__item b {
  flex: none;
  font-weight: 600;
  color: var(--c-forest);
  font-size: var(--fs-body);
}
.observe__dot {
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--c-clay);
  transform: translateY(-2px);
}

/* --------------------------------------------------------------------------
   12. About + credentials
   -------------------------------------------------------------------------- */

.about p + p { margin-top: var(--sp-4); }
.about__text { color: var(--text-muted); }
.about__portrait { margin-bottom: var(--sp-8); }

.quote {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: 1.5;
  color: var(--c-forest);
  border-left: 2px solid var(--c-clay);
  padding-left: var(--sp-4);
  margin-block: var(--sp-6);
  max-width: var(--measure-max);
}

/* Credentials stated plainly and once — brand.md §8 */
.creds {
  margin-top: var(--sp-8);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
  background: var(--c-eggshell);
}
.creds h3 { font-size: var(--fs-body); margin-bottom: var(--sp-4); }
.creds dl { display: grid; gap: var(--sp-3); }
.creds dt {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 600;
}
.creds dd { font-size: var(--fs-body); }
.creds__list { margin-top: var(--sp-4); }

/* --------------------------------------------------------------------------
   13. Extras — workshop and home visits
   -------------------------------------------------------------------------- */

.extras { margin-top: var(--sp-16); }
/* A subhead, not a section heading: display face like the h2 above it, but at
   h3 size, so it reads one level down rather than as a second section. */
.extras__head {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  letter-spacing: -0.01em;
  color: var(--c-forest);
  margin-bottom: var(--sp-6);
}
.extras__grid { display: grid; gap: var(--sp-6); }
.extra {
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
  background: var(--bg-surface);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.extra h4 { margin-bottom: 0; }
.extra p { color: var(--text-muted); }
.extra .btn { margin-top: auto; align-self: flex-start; }

/* --------------------------------------------------------------------------
   14. Locations and contact
   -------------------------------------------------------------------------- */

.contact { background: var(--bg-page); }
.contact__body { color: var(--text-muted); margin-top: var(--sp-4); }
.contact__actions {
  display: flex; flex-direction: column; gap: var(--sp-3);
  margin-top: var(--sp-8);
}

.places { display: grid; gap: var(--sp-6); margin-top: var(--sp-12); }
.place {
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-card);
  padding: var(--sp-6);
}
.place h3 { color: var(--c-forest); font-size: var(--fs-body); margin-bottom: var(--sp-2); }
.place address {
  font-style: normal;
  color: var(--text-muted);
  font-size: var(--fs-small);
  line-height: 1.65;
}
.place__link {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 2.75rem;
  margin-top: var(--sp-3);
  font-size: var(--fs-small);
  font-weight: 600;
  /* Was sage-on-dark, which exists for forest grounds only -- on eggshell it
     measures 1.8:1. Forest on eggshell is 8.73:1 (brand.md §3). */
  color: var(--c-forest);
  box-shadow: inset 0 -1px 0 currentColor;
}

/* --------------------------------------------------------------------------
   15. Footer
   -------------------------------------------------------------------------- */

.footer {
  background: var(--c-forest);
  color: rgba(248, 246, 240, 0.8);
  padding-block: var(--sp-12);
  border-top: 1px solid rgba(248, 246, 240, 0.15);
}
.footer__logo img { height: 3rem; width: auto; margin-bottom: var(--sp-6); }
.footer nav { display: grid; gap: var(--sp-1); margin-block: var(--sp-6); }
.footer nav a {
  display: inline-flex; align-items: center;
  min-height: 2.75rem;
  font-size: var(--fs-small);
}
.footer nav a:hover { color: var(--c-eggshell); }
.footer__contact { margin-top: var(--sp-8); }
.footer__contact p { font-size: var(--fs-small); line-height: 1.9; }
.footer__zonas { margin-top: var(--sp-4); }
.footer__contact a:hover { color: var(--c-eggshell); }

.footer__legal {
  font-size: var(--fs-small);
  line-height: 1.7;
  color: rgba(248, 246, 240, 0.6);
  padding-top: var(--sp-6);
  border-top: 1px solid rgba(248, 246, 240, 0.15);
}

/* --------------------------------------------------------------------------
   16. Persistent mobile action bar — booking always within thumb reach
   -------------------------------------------------------------------------- */

.actionbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 85;
  /* grid, not flex: two 1fr columns are exactly equal, whereas flex-grow
     left the bordered ghost button 2px wider than the solid one. */
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--gutter);
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  background: rgba(253, 252, 249, 0.96);
  -webkit-backdrop-filter:
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--border-hairline);
  transition: transform 350ms var(--ease);
}
/* flex-basis 0 with min-width 0 forces a true 50/50 split; without min-width
   the longer label's min-content width wins and the twoer by  by ~10px. */
.actionbar .btn { flex: 1 1 0; min-width: 0; padding-inline: var(--sp-3); }
/* Hidden while the nav panel is open — it would sit on top of it */
.nav-open .actionbar { transform: translateY(110%); }

@media (min-width: 48em) {
  .actionbar { display: none; }
}

/* --------------------------------------------------------------------------
   17. Scroll reveals — fade with an 8px rise. Nothing more. brand.md §6
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(var(--reveal-offset));
  transition: opacity var(--dur-reveal) var(--ease) var(--d, 0ms),
              transform var(--dur-reveal) var(--ease) var(--d, 0ms);
}
.reveal.is-in { opacity: 1; transform: none; }

/* --- Craft layer -------------------------------------------------------
   Everything here stays inside brand.md §6: fade plus an 8px rise, 400-600ms,
   the one easing curve. What changes is sequencing and material, not
   technique. No parallax, no scale beyond 1.02, nothing cursor-driven.
   ---------------------------------------------------------------------- */

/* 1. The clay hairline draws itself in rather than appearing. */
.accent-rule {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 600ms var(--ease) 120ms;
}
.reveal.is-in .accent-rule,
.is-in > .accent-rule { transform: scaleX(1); }

/* 2. Photography fades in with the rest of its block.

   brand.md §6 offers a clip-path wipe under "what restraint permits", and it
   was tried here. In practice a hard edge travelling across a photograph
   announces itself as a technique, which is the opposite of what §6 is for.
   The base rule -- "fade in with an 8px rise, nothing more" -- reads calmer,
   so photography carries no reveal of its own and simply comes in with its
   block. Reverted 2026-08-26; see the decision log in brand.md §14. */

/* 3. Fixed-length sequences stagger by 70ms. */
.steps .step:nth-child(1) { --d: 0ms; }
.steps .step:nth-child(2) { --d: 70ms; }
.steps .step:nth-child(3) { --d: 140ms; }
.steps .step:nth-child(4) { --d: 210ms; }
.steps .step {
  opacity: 0;
  transform: translateY(var(--reveal-offset));
  transition: opacity var(--dur-reveal) var(--ease) var(--d, 0ms),
              transform var(--dur-reveal) var(--ease) var(--d, 0ms);
}
.steps.is-in .step { opacity: 1; transform: none; }

.observe__list .observe__item:nth-child(2) { --d: 90ms; }
.observe__list .observe__item:nth-child(3) { --d: 180ms; }
.reveal .observe__item {
  opacity: 0;
  transition: opacity var(--dur-reveal) var(--ease) var(--d, 0ms);
}
.reveal.is-in .observe__item { opacity: 1; }

/* 4. The finder's two columns settle item by item when the age changes. */
.pane li {
  animation: pane-in var(--dur-reveal) var(--ease) both;
}
.pane li:nth-child(2) { animation-delay: 60ms; }
.pane li:nth-child(3) { animation-delay: 120ms; }
@keyframes pane-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* 5. Surfaces warm on hover — colour shift only, no shadow, no scale.

   The reveal properties are repeated here on purpose. `transition` is one
   declaration per element, not a list that merges: this rule sits after
   `.reveal` at equal specificity, so declaring only the two colour properties
   silently replaced the reveal's opacity and transform transitions. These
   four card types were not fading in at all -- they snapped from opacity 0 to
   1 with no interpolation, while everything around them faded. Any new
   property animated on a card has to be added to this list too. */
.symptom, .service, .extra, .place {
  transition: background-color var(--dur-hover) var(--ease),
              border-color var(--dur-hover) var(--ease),
              opacity var(--dur-reveal) var(--ease) var(--d, 0ms),
              transform var(--dur-reveal) var(--ease) var(--d, 0ms);
}
.symptom:hover, .extra:hover { border-color: var(--c-sage); background: var(--c-sage-tint); }
.service:hover { border-color: var(--c-sage); }
.place:hover { border-color: var(--c-sage); }

/* 6. The header condenses once you leave the hero. */
.header { transition: box-shadow var(--dur-hover) var(--ease); }
.header__inner {
  transition: min-height 300ms var(--ease);
}
.header.is-condensed .header__inner { min-height: 3.5rem; }
.header.is-condensed { box-shadow: 0 1px 0 var(--border-hairline); }
.header__logo img { transition: height 300ms var(--ease); }
.header.is-condensed .header__logo img { height: 2.5rem; }

/* --------------------------------------------------------------------------
   18. Wider viewports — the phone layout widens, it is not replaced
   -------------------------------------------------------------------------- */

@media (min-width: 40em) {
  .hero__actions { flex-direction: row; }
  .symptoms__grid { grid-template-columns: repeat(2, 1fr); }
  .extras__grid { grid-template-columns: repeat(2, 1fr); }
  .places { grid-template-columns: repeat(2, 1fr); }
  .contact__actions { flex-direction: row; }
}

@media (min-width: 48em) {
  .hero__inner {
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--sp-16);
    align-items: center;
  }
  .hero__figure { margin-top: 0; }
  .hero { padding-block: var(--sp-16) var(--sp-12); }

  .services__grid { grid-template-columns: repeat(2, 1fr); }
  .service { padding: var(--sp-8); }

  .panes { grid-template-columns: 1fr 1fr; }
  .pane { padding: var(--sp-8) var(--sp-8) var(--sp-4) 0; }
  .pane + .pane {
    border-top: 0;
    border-left: 1px solid rgba(248, 246, 240, 0.22);
    padding-inline: var(--sp-8) 0;
  }

  .visit__inner { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: var(--sp-16); }
  /* stretch, not start: the portrait grows to the height of the text beside
     it rather than leaving the column empty below itself. */
  .about__inner { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: var(--sp-16); align-items: stretch; }
  .about__portrait { margin-bottom: 0; display: flex; }
  .about__portrait .photo {
    flex: 1;
    aspect-ratio: auto;            /* height comes from the column now */
    min-height: 30rem;
  }
  .creds dl { grid-template-columns: repeat(2, 1fr); gap: var(--sp-6); }

  .footer__inner {
    display: grid;
    grid-template-columns: 1.1fr 0.9fr 1fr;
    gap: var(--sp-12);
    align-items: start;
  }
  /* Those margins separated the blocks while they were stacked. Side by side
     they only push two of the three columns down, so the headings stopped
     sharing a line. The grid gap does the separating from here. */
  .footer nav, .footer__contact { margin-top: 0; }
  /* Seven links in one column made this the tallest thing in the footer and
     left the other two columns half empty. Two columns of four halves it. */
  .footer nav {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--sp-6);
  }
}

/* --------------------------------------------------------------------------
   Full desktop header.

   Deliberately NOT at 48em. Logo, five nav items, the language switcher and
   the booking action need roughly 850px between them; at 768px the browser
   resolved the shortfall by wrapping the nav labels onto two lines, which
   silently grew the header from 68px to 82px. Below this width the
   full-screen panel does the job it was built for.
   -------------------------------------------------------------------------- */
@media (min-width: 62em) {
  .header__nav {
    display: flex;
    gap: var(--sp-6);
    margin-left: var(--sp-8);
    font-size: var(--fs-body);
  }
  .header__nav a {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    white-space: nowrap;      /* never let a label become two lines */
    color: var(--c-ink);
  }
  .header__nav a::after {
    content: '';
    position: absolute; left: 0; right: 100%; bottom: 1rem;
    height: 1px; background: var(--c-clay);
    transition: right 350ms var(--ease);
  }
  .header__nav a:hover::after { right: 0; }

  .header__cta {
    display: inline-flex;
    flex: none;
    min-height: 2.5rem;
    padding-block: var(--sp-2);
    padding-inline: var(--sp-4);
    font-size: var(--fs-small);
    margin-left: var(--sp-3);
  }

  .burger, .navpanel { display: none; }
}



/* --------------------------------------------------------------------------
   19. Reduced motion — respected everywhere.
   Each effect is returned to its resting state explicitly rather than relying
   on the blanket duration override, which does not undo a clip-path or a
   transform that starts at zero.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
  .panes[data-fading] { opacity: 1; }
  .deck { scroll-behavior: auto; }
  .slide { opacity: 1 !important; }
  .accent-rule { transform: scaleX(1) !important; }
  .steps .step,
  .reveal .observe__item { opacity: 1 !important; transform: none !important; }
  .pane li { animation: none !important; }
  .header.is-condensed .header__inner { min-height: 4.25rem; }
}

/* --------------------------------------------------------------------------
   20. Print
   -------------------------------------------------------------------------- */

@media print {
  .header, .actionbar, .navpanel, .finder__foot { display: none; }
  body { padding-bottom: 0; background: #fff; }
  .reveal { opacity: 1; transform: none; }
  .slide { opacity: 1; }
}

@media (min-width: 64em) {
  .symptoms__grid { grid-template-columns: repeat(3, 1fr); }
}

/* --------------------------------------------------------------------------
   Trust strip, horizontal.

   The items are three unequal facts, not three equal ones -- 25, 25 and 50
   characters. Equal `1fr` columns therefore wrapped the third and left the
   row visibly lopsided. These columns are sized to their own content instead
   and centred as a group, so nothing wraps and the three sit on one baseline.

   It only turns horizontal at 64em because that is where the full row
   actually fits; below it the items stack, which is symmetric by definition.
   A ragged two-line-then-one-line row is worse than a clean stack.
   -------------------------------------------------------------------------- */

@media (min-width: 64em) {
  .trust ul {
    grid-template-columns: repeat(3, auto);
    justify-content: center;
    column-gap: var(--sp-16);
    align-items: center;
  }
  .trust li {
    border-top: 0 !important;
    padding-block: var(--sp-6);
    padding-inline: 0;
    position: relative;
    max-width: none;
  }
  /* Centred in the gap rather than hugging the next item, which is only
     possible because the gap is a known width. */
  .trust li + li::before {
    content: '';
    position: absolute;
    left: calc(var(--sp-16) / -2);
    top: 50%;
    transform: translateY(-50%);
    width: 1px; height: 1.75em;
    background: rgba(248, 246, 240, 0.22);
  }
}

/* --------------------------------------------------------------------------
   Footer columns.

   The contact column was the only one carrying a heading, which read as an
   oversight rather than a hierarchy. The links are now two labelled groups --
   anchors on this page, and separate pages -- so every column is titled.
   -------------------------------------------------------------------------- */

.footer nav { row-gap: var(--sp-8); }
.footer nav > div {
  display: grid;
  gap: var(--sp-1);
  /* Both labels are short enough not to wrap at the narrowest the two columns
     ever get (~94px). If a longer one is ever added it will wrap, and the
     column beside it will start a line lower -- which is exactly what
     "Otras páginas" did here. Keep them to one word. */
  /* Grid's default align-content is stretch, so the three-item column was
     spreading its rows to match the four-item one beside it: 54px steps
     against 48px, and every row off by a little more than the last. */
  align-content: start;
}

/* Ink muted measures about 1.9:1 against forest, so the footer eyebrows were
   failing contrast outright. brand.md §3 is explicit that the lightened sage
   is the only tint clearing 4.5:1 on this ground (5.16:1), so they use it
   rather than the light-surface default. */
.footer .eyebrow { color: var(--c-sage-on-dark); }

/* --------------------------------------------------------------------------
   Section grounds.

   The page was reading as one continuous sheet. #situaciones and #servicios
   sat on the same eggshell with nothing between them, and .about painted
   itself #FDFCF9 against #F8F6F0 -- a 2% step, invisible at any size.

   The rhythm is now eggshell -> sage tint -> eggshell, with forest spent on a
   single band. brand.md §3 allots roughly 80% eggshell, 15% sage family and
   5% everything else, so the tint does the dividing and the dark is kept
   scarce enough to still mean something.

   That one dark band is the milestone finder. It had been competing with a
   second forest block at #contacto, which then ran straight into the forest
   footer and read as one slab of green with a seam in it. §9 calls the finder
   the signature element; giving it the only dark ground in the body makes it
   the centre of the page instead of one of two.
   -------------------------------------------------------------------------- */

.section-tint { background: var(--c-sage-tint); }

/* Ink muted clears 5.00:1 on eggshell but only 4.31:1 on sage tint, which is
   under AA. Rather than patch each element that happens to use it, the token
   itself is redefined for this ground: everything inheriting --text-muted
   inside a tinted section resolves to full ink (11.37:1) and nothing can be
   missed. The cost is that muted copy loses its lighter weight here -- an
   acceptable trade for a ground that would otherwise fail on every paragraph
   set in it. */
.section-tint { --text-muted: var(--c-ink); }

/* --------------------------------------------------------------------------
   Long-form prose — the legal pages.

   Every other page keeps its text inside cards and section heads, each spaced
   by its own rule, so the reset at the top of this file (`* { margin: 0 }`)
   never mattered. aviso-legal.html and politica-privacidad.html are the first
   pages made of actual paragraphs, and they inherited zero margins on
   everything: headings sat flush against the paragraph above them.
   -------------------------------------------------------------------------- */

.legal p { margin-bottom: var(--sp-4); }
.legal p:last-child { margin-bottom: 0; }

/* Section size would shout on a page that is almost entirely text. At h3 size
   in the display face it still reads a clear level above the body, the same
   trick the extras subhead uses. */
.legal h2 {
  font-size: var(--fs-h3);
  margin-top: var(--sp-12);
  margin-bottom: var(--sp-3);
}
.legal > :first-child { margin-top: 0; }

/* Run-in labels: "NIF:", "Colegio profesional:", "Sobre WhatsApp." */
.legal strong { color: var(--c-forest); font-weight: 600; }

/* Underline by shadow rather than text-decoration, so descenders stay clean.

   `:not(.btn)` is load-bearing. This rule sits after the button styles and
   outranks them on specificity, so without it a button inside prose was
   painted forest-on-forest -- a solid green rectangle with its label
   invisible inside it. */
.legal a:not(.btn) {
  color: var(--c-forest);
  box-shadow: inset 0 -1px 0 var(--c-taupe);
}
.legal a:not(.btn):hover { box-shadow: inset 0 -1px 0 var(--c-forest); }

/* An aside, on the same clay hairline the consent document uses. */
.legal .note {
  border-left: 2px solid var(--c-clay);
  padding-left: var(--sp-4);
  color: var(--text-muted);
  margin-block: var(--sp-6);
}

/* --------------------------------------------------------------------------
   Acupuncture page.

   A slot awaiting a photograph that does not exist yet is not the same thing
   as an AI stand-in, so it says so. The frame still reserves its space, which
   is the point: the layout must not move when the picture arrives.
   -------------------------------------------------------------------------- */

.photo[data-placeholder="pendiente"]::before { content: 'Imagen pendiente'; }

/* The global reset strips list markers, which body copy actually wants. */
.acu-list {
  list-style: disc;
  padding-left: 1.15em;
  color: var(--text-muted);
  font-size: var(--fs-small);
  line-height: 1.6;
}
.acu-list li { margin-bottom: var(--sp-1); }
.acu-list li:last-child { margin-bottom: 0; }
.legal .acu-list { font-size: var(--fs-body); margin-bottom: var(--sp-4); }
