/* --- 0. Typefaces ----------------------------------------------------------
   Fraunces and Inter, self-hosted rather than loaded from Google.

   Two reasons, and the second is the real one. Google Fonts is render-blocking
   and costs two extra DNS lookups and TLS handshakes on the critical path. More
   importantly, fetching a typeface from Google sends every visitor's IP address
   to Google — including someone reading the crisis resources on the contact
   page at three in the morning. That is a poor default for a psychotherapy
   practice, so the files are served from this domain instead.

   Both faces are variable: one file covers the whole weight range, so there is
   no separate bold to download. The latin subset is what nearly every page
   needs; latin-ext is declared for the accented characters outside it (names,
   mostly) and, because of unicode-range, is only ever downloaded if a character
   in that range actually appears on the page.

   font-display: swap means text is readable in the fallback face immediately
   and reflows once the webfont lands, rather than sitting invisible.

   Both are licensed under the SIL Open Font License 1.1. See fonts/OFL.txt. */

/* Fraunces, latin */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/fraunces-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Fraunces, latin-ext */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/fraunces-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Inter, latin */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Inter, latin-ext */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ==========================================================================
   San Francisco Therapy Continuum site styles
   Direction: "Clay & Sage". Rectangular media frames; pale sage surfaces.
   Single stylesheet, no build step. Edit tokens below to reskin the site.
   ========================================================================== */

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

:root {
  /* Palette */
  --clay:        #A65A43;  /* primary action; 4.78:1 on bone, 5.05:1 under white */
  --clay-dark:   #8C4735;  /* hover / pressed */
  --clay-wash:   #F6EAE4;  /* tint panels */
  --sage:        #CAD6C6;  /* pale sage panels - carries DARK text, not white */
  --sage-deep:   #C0CFBE;  /* footer, one step down from the panels */
  --sage-text:   #45564B;  /* green TEXT on light backgrounds */
  --sage-wash:   #E9EFEA;  /* tag and placeholder tints */
  --bone:        #FBF8F3;  /* page background */
  --bone-deep:   #F3EEE5;  /* alternating band */
  --ink:         #2B2622;  /* body text */
  --muted:       #6B625B;  /* caption text; 5.65:1 on bone, safe at small sizes */
  --rule:        #8A8078;  /* hairlines and decorative only, too light for text */
  --line:        #E4DCD1;  /* borders */
  --white:       #FFFFFF;

  /* Logo kit's own palette (logo/README.md). Kept as separate tokens: the mark
     ships with these baked in, and they run warmer than the site's clay/sage.
     Do not swap the site tokens for these without redoing the contrast pass.
     Darkened from the kit's original #c67139 / #7a8a5e, which read as bright
     and cartoonish next to the type. Nothing on the site references these
     tokens - they are here as the record of what the marks contain. */
  --brand-terracotta: #A0562F;
  --brand-sage:       #5E6E45;
  --brand-cream:      #f5ead8;
  --brand-ink:        #201e1d;

  /* Semantic */
  --bg:          var(--bone);
  --fg:          var(--ink);
  --accent:      var(--clay);

  /* Type */
  --font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-body:    "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  --step--1: 0.875rem;
  --step-0:  1.0625rem;
  --step-1:  1.25rem;
  --step-2:  1.5rem;
  --step-3:  clamp(1.75rem, 1.4rem + 1.4vw, 2.25rem);
  --step-4:  clamp(2.1rem, 1.6rem + 2.1vw, 3rem);
  --step-5:  clamp(2.5rem, 1.6rem + 3.6vw, 4rem);

  /* Spacing: spacious scale */
  --s1: 0.5rem;  --s2: 0.75rem; --s3: 1rem;   --s4: 1.5rem;
  --s5: 2rem;    --s6: 3rem;    --s7: 4rem;   --s8: 6rem;  --s9: 8rem;
  --section-y: clamp(4rem, 8vw, 7.5rem);

  /* Layout */
  --wrap: 1120px;
  --wrap-wide: 1320px;   /* sections built around a photograph */
  --wrap-narrow: 760px;
  --prose: 68ch;

  /* Shape */
  --radius-sm: 4px;
  --radius-md: 10px;

  --shadow-soft: 0 1px 2px rgba(43, 38, 34, 0.04), 0 8px 24px rgba(43, 38, 34, 0.06);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-soft: cubic-bezier(0.16, 0.84, 0.44, 1);  /* long tail, no overshoot */
}

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

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s4);
  text-wrap: balance;
}

h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); line-height: 1.25; }
h4 { font-size: var(--step-1); line-height: 1.3; font-weight: 600; }

p { margin: 0 0 var(--s4); max-width: var(--prose); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

/* --clay reaches only 4.36:1 on the tinted band, so body links use the darker
   value, which clears AA on bone, the band, and the pale sage panels alike. */
a { color: var(--clay-dark); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--clay-dark); text-decoration-thickness: 2px; }

ul, ol { margin: 0 0 var(--s4); padding-left: 1.25em; max-width: var(--prose); }
li { margin-bottom: var(--s2); }
li:last-child { margin-bottom: 0; }

strong { font-weight: 600; }

:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute; left: var(--s3); top: -100px; z-index: 200;
  background: var(--clay); color: var(--white);
  padding: var(--s2) var(--s4); border-radius: var(--radius-sm);
  font-size: var(--step--1); font-weight: 600; text-decoration: none;
  transition: top 180ms var(--ease);
}
.skip-link:focus { top: var(--s3); color: var(--white); }

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

/* --- 3. Layout helpers -------------------------------------------------- */

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.wrap--narrow { width: min(100% - 2.5rem, var(--wrap-narrow)); margin-inline: auto; }
.wrap--wide { width: min(100% - 2.5rem, var(--wrap-wide)); margin-inline: auto; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(3rem, 5vw, 4.5rem); }
.section--band { background: var(--bone-deep); }

/* A section that opens a page in place of a .page-intro: the H1 needs a little
   more air above it than a mid-page band does, and none of the extra weight a
   band would add. */
.section--open { padding-block: clamp(3rem, 6vw, 5rem) var(--section-y); }
.section--sage { background: var(--sage); color: var(--ink); }
.section--sage h2, .section--sage h3 { color: var(--sage-text); }
.section--sage p { color: var(--ink); }
.section--sage a:not(.btn) { color: var(--clay-dark); }  /* must not hit buttons */
.section--sage .eyebrow { color: var(--clay-dark); }
.section--sage .eyebrow::before { background: var(--clay-dark); }

.stack > * + * { margin-top: var(--s4); }

/* --- 4. Eyebrow: the section signpost ----------------------------------- */
/* A short rule then a label. Names what kind of content follows,
   never a decorative number, because these sections are not a sequence. */

.eyebrow {
  display: flex; align-items: center; gap: var(--s2);
  font-family: var(--font-body);
  font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--clay-dark);
  margin: 0 0 var(--s4);
}
.eyebrow::before {
  content: ""; width: 28px; height: 1.5px; flex: none;
  background: var(--clay-dark);
}

/* --- 5. Buttons --------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 48px; padding: 0.8rem 1.6rem;
  font-family: var(--font-body); font-size: var(--step--1);
  font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  border: 1.5px solid transparent; border-radius: var(--radius-sm);
  white-space: nowrap;
  transition: background-color 200ms var(--ease), border-color 200ms var(--ease),
              color 200ms var(--ease), transform 200ms var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--clay); color: var(--white); border-color: var(--clay); }
.btn--primary:hover { background: var(--clay-dark); border-color: var(--clay-dark); color: var(--white); }

.btn--outline { background: transparent; color: var(--sage-text); border-color: var(--sage-text); }
.btn--outline:hover { background: var(--sage-text); color: var(--white); }

.section--sage .btn--outline { color: var(--sage-text); border-color: var(--sage-text); }
.section--sage .btn--outline:hover { background: var(--sage-text); color: var(--white); border-color: var(--sage-text); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }

/* Fine print: the dateline on the privacy page, and anywhere else a line needs
   to read as a legal note rather than as body copy. */
.small-print { font-size: var(--step--1); color: var(--muted); }

/* --- 6. Media frames ---------------------------------------------------- */
/* Rectangular, with the same 4px corner as cards and buttons. For perfectly
   sharp corners set --radius-sm to 0 (it also squares the cards and buttons),
   or hard-code `border-radius: 0` on .media alone. */

.media {
  position: relative;          /* anchors the parallax wrapper */
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--sage-wash);
  aspect-ratio: 3 / 4;
}

/* Parallax wrapper, inserted by script at runtime so the HTML you edit stays
   a plain <img>. It is 36% taller than the frame; the script drifts it by at
   most 16%, so an edge can never be exposed. The hidden top and bottom are what
   the drift reveals as you scroll. Without JavaScript this element never
   exists and the image simply fills the frame. */
.media__shift {
  position: absolute;
  left: 0; right: 0;
  top: -18%; bottom: -18%;
  will-change: transform;
}
.media__shift img { width: 100%; height: 100%; object-fit: cover; }

/* Shallower headroom for pictures whose edges carry something worth keeping.
   A taller wrapper makes object-fit: cover scale the image up, and on a
   portrait image in a portrait frame that crop comes off the left and right.
   6% instead of 18%; the script drops the drift to 5% to match. */
.media--gentle .media__shift { top: -6%; bottom: -6%; }
.media--wide { aspect-ratio: 4 / 3; }
.media img { width: 100%; height: 100%; object-fit: cover; }

/* Free-standing photographs are framed and mounted: a firm rule on the image
   edge, and a flat clay block sitting behind it and offset down and to the
   right, the way a print is pinned over a coloured mount. The block is drawn
   as a hard-edged box-shadow, so it paints outside .media's overflow: hidden,
   costs no layout, and can never push the parallax wrapper out of frame.
   Both colours are translucent tints rather than fixed hex values, so one
   rule reads correctly on every band - bone, the tinted band and sage -
   without a per-section override.
   Background photographs (the hero, .section--photo) are deliberately left
   unframed: they are the surface, not an object placed on it. */
.media:not(.media--empty) {
  --frame-offset: clamp(10px, 1.3vw, 18px);
  border: 2px solid rgba(43, 38, 34, 0.55);
  box-shadow: var(--frame-offset) var(--frame-offset) 0 0 rgba(166, 90, 67, 0.40);
}

/* On the sage band the clay mount would sit on a green ground and go muddy,
   so it lightens to the same warm cream the band's own type sits on. */
.section--sage .media:not(.media--empty) {
  box-shadow: var(--frame-offset) var(--frame-offset) 0 0 rgba(251, 248, 243, 0.70);
}

/* The mount is dropped on narrow screens, where the photograph runs nearly
   edge to edge and the offset block would be squeezed against the margin. */
@media (max-width: 560px) {
  .media:not(.media--empty) { --frame-offset: 7px; }
}

/* Placeholder shown until a real photograph is dropped in. */
.media--empty {
  display: grid; place-items: center; padding: var(--s5);
  border: 1.5px dashed var(--rule);
  text-align: center;
}
.media--empty span {
  font-size: var(--step--1); color: var(--muted); max-width: 22ch; line-height: 1.5;
}

/* --- 6b. Photo band ------------------------------------------------------ */
/* Light treatment: a soft photograph under a pale veil, with DARK text.
   The earlier version scrimmed a sunlit photo to 74% and still could not
   guarantee contrast: 17% of that image was blown to pure white, which would
   have needed an 83% scrim to be safe, i.e. no visible photograph at all.
   Inverting it solves both problems: the veil is light, the photo reads
   clearly, and the darkest pixel in this image still leaves ink at 10.2:1,
   the sage headings at 5.3:1 and the clay eyebrow at 4.7:1. */

.section--photo {
  background-color: var(--bone);
  background-image:
    linear-gradient(rgba(251, 248, 243, 0.48), rgba(251, 248, 243, 0.48)),
    url("../images/cloudlight.webp");
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  color: var(--ink);
}
.section--photo h2, .section--photo h3 { color: var(--sage-text); }
.section--photo p { color: var(--ink); }
.section--photo .eyebrow { color: var(--clay-dark); }
.section--photo .eyebrow::before { background: var(--clay-dark); }
.section--photo a:not(.btn) { color: var(--clay-dark); }
.section--photo .btn--outline { color: var(--sage-text); border-color: var(--sage-text); }
.section--photo .btn--outline:hover { background: var(--sage-text); color: var(--white); border-color: var(--sage-text); }
.section--photo .cta-band__phone { color: var(--sage-text); }
.section--photo .cta-band__phone:hover { color: var(--clay-dark); }

/* --- 7. Header ---------------------------------------------------------- */
/* The mark is a ridgeline above open water: one landscape running from summit
   to sea, which is the continuum the practice is named for. It carries the
   identity so the type can stay quiet. */

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(251, 248, 243, 0.94);
  backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  display: flex; align-items: center; justify-content: flex-end;
  gap: var(--s4); min-height: 96px;
}
/* The wordmark takes the slack, so the links and the phone number stay
   grouped on the right rather than being spread across the bar. */
.site-header__inner > .wordmark { margin-right: auto; }

.wordmark {
  display: flex; align-items: center; gap: 0.85rem;
  color: var(--sage-text); text-decoration: none;
}
/* The mark ships at 200x130. Never stretched — width drives, height follows,
   and it is never rendered below the 72px the logo kit specifies. */
.wordmark__logo { width: 108px; height: auto; flex: none; display: block; }
@media (max-width: 560px) { .wordmark__logo { width: 84px; } }
.wordmark__mark { flex: none; color: var(--clay); transition: color 260ms var(--ease); }
.wordmark:hover .wordmark__mark { color: var(--sage-text); }

.wordmark__text {
  font-family: var(--font-display); font-size: 1.32rem; font-weight: 600;
  letter-spacing: -0.012em; line-height: 1.18; white-space: nowrap;
}
.wordmark__text span {
  display: block; font-family: var(--font-body); font-size: 0.82rem;
  font-weight: 500; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--muted); margin-top: 4px; white-space: nowrap;
}

.nav { display: flex; align-items: center; gap: var(--nav-gap); }
.site-header .btn {
  flex: none;                              /* never squeezed by the link list */
  min-height: 42px; font-size: var(--nav-btn-size);
  padding: 0.55rem var(--nav-btn-pad);
}
.nav__list {
  display: flex; align-items: center; flex: none; flex-wrap: nowrap;
  gap: var(--nav-gap); list-style: none; margin: 0; padding: 0;
}
.nav__list li { margin: 0; }
.nav__link {
  font-size: var(--nav-size); font-weight: 500; color: var(--ink);
  text-decoration: none; padding: var(--s2) 0; position: relative; white-space: nowrap;
}

/* One row, all the way down to the point where the header stacks.
   Eight links, a wordmark and a phone number do not fit a 1200px laptop at
   full size, so the whole header is sized off the viewport rather than fixed:
   everything holds its 1440px proportions on a wide screen and tapers evenly
   as the window narrows. Nothing shrinks past the point where it overlaps,
   because the list and the button both refuse to flex. */
:root {
  --nav-gap:     1.15rem;
  --nav-size:    0.82rem;
  --nav-btn-size: 0.75rem;
  --nav-btn-pad: 0.95rem;
}
/* Above the fluid range the browser measures this list's max-content about one
   gap short of where its items actually lay out, so the last link ends up
   almost touching the phone number. There is plenty of slack in a 1320px bar
   at this width, so the button simply takes an explicit gutter of its own
   rather than trusting that measurement. Below 1441px the list measures
   correctly and the container gap alone is enough. */
@media (min-width: 1441px) {
  .site-header .btn { margin-left: 1.5rem; }
}

@media (max-width: 1440px) {
  :root {
    --nav-gap:      clamp(0.5rem,  2.34vw - 0.98rem, 1.15rem);
    --nav-size:     clamp(0.68rem, 0.5vw  + 0.32rem, 0.82rem);
    --nav-btn-size: clamp(0.66rem, 0.32vw + 0.43rem, 0.75rem);
    --nav-btn-pad:  clamp(0.55rem, 1.44vw - 0.35rem, 0.95rem);
  }
  .site-header__inner { gap: clamp(0.7rem, 2.9vw - 1.1rem, 1.5rem); }
  .wordmark { gap: clamp(0.45rem, 1.44vw - 0.45rem, 0.85rem); }
  .wordmark__logo { width: clamp(80px, 6.98vw + 7.5px, 108px); }
  .wordmark__text { font-size: clamp(1.02rem, 1.2vw + 0.24rem, 1.32rem); }
  .wordmark__text span { font-size: clamp(0.68rem, 0.56vw + 0.32rem, 0.82rem); }
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1.5px;
  background: var(--clay); transform: scaleX(0); transform-origin: left;
  transition: transform 220ms var(--ease);
}
.nav__link:hover { color: var(--clay-dark); }
.nav__link:hover::after, .nav__link[aria-current="page"]::after { transform: scaleX(1); }
.nav__link[aria-current="page"] { color: var(--clay-dark); }

/* --- 7b. Nav dropdown ------------------------------------------------------
   Built on <details>/<summary> rather than a button and a script, so it opens
   and closes with no JavaScript at all and gets keyboard support for free.
   The script below only adds the conveniences: close on Escape, close when you
   click elsewhere, close after following a link. */

/* The menu button. Hidden at every width except the narrow block below, and
   only there when scripting is available - without JavaScript the links stay
   listed in the header, exactly as they were before this button existed. */
.nav__toggle {
  display: none; flex: none;
  width: 44px; height: 44px; padding: 0;
  align-items: center; justify-content: center;
  background: none; color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 200ms var(--ease), color 200ms var(--ease);
}
.nav__toggle:hover { border-color: var(--clay); color: var(--clay-dark); }

/* Three bars that fold into a cross when the panel is open. */
.nav__bars, .nav__bars::before, .nav__bars::after {
  display: block; width: 18px; height: 1.5px; background: currentColor;
  transition: transform 220ms var(--ease), background-color 160ms var(--ease);
}
.nav__bars { position: relative; }
.nav__bars::before, .nav__bars::after { content: ""; position: absolute; left: 0; }
.nav__bars::before { top: -6px; }
.nav__bars::after  { top: 6px; }
.nav__toggle[aria-expanded="true"] .nav__bars { background: transparent; }
.nav__toggle[aria-expanded="true"] .nav__bars::before { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] .nav__bars::after  { transform: translateY(-6px) rotate(-45deg); }

.nav__group { position: relative; }
.nav__menu > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.34rem; }
.nav__menu > summary::-webkit-details-marker { display: none; }
.nav__summary::after { content: none; }          /* no underline sweep on the trigger */
.nav__summary .caret,
.nav__menu > summary::marker { display: none; }

/* The caret, drawn rather than typed so it lines up with the cap height. */
.nav__menu > summary .nav__caret {
  width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform 200ms var(--ease);
}
.nav__menu[open] > summary .nav__caret { transform: translateY(1px) rotate(-135deg); }
.nav__menu[open] > summary { color: var(--clay-dark); }

.nav__submenu {
  list-style: none; margin: 0; padding: var(--s3) 0;
  position: absolute; top: calc(100% + 0.7rem); left: 50%; transform: translateX(-50%);
  min-width: 15rem; z-index: 120;
  background: var(--bone); border: 1px solid var(--line);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-soft);
}
.nav__submenu li { margin: 0; }
.nav__submenu .nav__link {
  display: block; padding: 0.5rem var(--s5); white-space: nowrap;
}
.nav__submenu .nav__link::after { left: var(--s5); right: var(--s5); bottom: 0.3rem; }

/* Narrow screens collapse the links behind a button, so the bar stays one
   line: wordmark, phone number, menu. That is the whole point of the
   collapse - the phone number is the conversion on this site, and it has to
   be on screen when the page opens rather than below three rows of links.
   At this width the bar is one line, so it can also stay sticky and keep the
   number reachable from anywhere on the page.
   Without JavaScript the panel is simply always open and the button never
   appears, which is the layout this header had before. */
@media (max-width: 1040px) {
  .site-header__inner {
    display: grid; grid-template-columns: 1fr auto auto;
    align-items: center; gap: var(--s3) var(--s3);
    padding-block: var(--s3); min-height: 0;
  }
  .site-header__inner > .wordmark { grid-column: 1; grid-row: 1; margin-right: 0; }
  .site-header .btn { grid-column: 2; grid-row: 1; align-self: center;
                      min-height: 44px; padding: 0.6rem 1rem; font-size: 0.74rem; }
  .js .nav__toggle { display: inline-flex; grid-column: 3; grid-row: 1; }

  .nav {
    grid-column: 1 / -1; grid-row: 2;
    flex-direction: column; align-items: stretch; gap: var(--s3);
  }
  .js .nav { display: none; }
  .js .nav.is-open { display: block; }

  .nav__list {
    flex: 1 1 auto; flex-wrap: wrap; justify-content: flex-start; gap: 0.1rem 1.25rem;
    padding-top: var(--s3); border-top: 1px solid var(--line);
  }
  /* Roomier hit areas: WCAG 2.2 asks for 24x24 minimum, this gives ~38px. */
  .nav__link { font-size: 0.9rem; padding: 0.6rem 0; }
  /* On narrow screens the panel simply expands in place, so nothing floats
     over content on a phone. */
  .nav__group { width: 100%; }
  .nav__submenu {
    position: static; transform: none; min-width: 0;
    background: none; border: none; box-shadow: none;
    padding: 0 0 var(--s3) var(--s5);
  }
  .nav__submenu .nav__link { padding: 0.5rem 0; }
}

/* Below this the wordmark and the phone number will not share a line: the two
   of them plus the menu button need 561px and a 390px phone offers 350. So the
   number takes a row of its own and the bar goes back to two lines - still
   about 145px, against the 230px it was when every link was listed, and the
   number lands around 85px down, well inside the opening screen.
   Two lines is too much to pin, though: it would hold nearly a fifth of a
   phone screen for the whole scroll, so the header stops being sticky here. */
@media (max-width: 560px) {
  .site-header { position: static; }
  .wordmark__text { font-size: 1.14rem; }
  .wordmark__text span { font-size: 0.72rem; letter-spacing: 0.12em; }
  .wordmark__mark { width: 38px; height: 29px; }
  .site-header__inner { grid-template-columns: 1fr auto; }
  .site-header .btn { grid-column: 1 / -1; grid-row: 2; justify-self: stretch; }
  .nav { grid-row: 3; }
}

/* --- 8. Hero ------------------------------------------------------------ */

/* The hero sits on a photograph rather than beside one, and the photograph is
   the point: redwood trunks converging into the canopy. So the scrim is dark
   and asymmetric rather than a flat cream wash - heavy under the column of
   type on the left, almost nothing over the right two fifths, where the trees
   stay at full strength. The type reverses out to white to pay for it. On a
   phone the text spans the whole width, so the gradient runs top to bottom
   instead of left to right. */
.hero {
  display: grid; align-items: center;
  min-height: clamp(30rem, 64vh, 42rem);
  padding-block: clamp(4rem, 7vw, 6.5rem);
  background-color: #221D19;
  background-image:
    linear-gradient(96deg,
      rgba(20, 16, 13, 0.78) 0%,
      rgba(20, 16, 13, 0.66) 30%,
      rgba(20, 16, 13, 0.36) 58%,
      rgba(20, 16, 13, 0.12) 84%,
      rgba(20, 16, 13, 0.08) 100%),
    url("../images/redwood-grove.webp");
  background-size: cover;
  background-position: center 46%;
  background-repeat: no-repeat;
}
@media (max-width: 900px) {
  .hero {
    min-height: clamp(28rem, 74vh, 40rem);
    background-image:
      linear-gradient(
        rgba(20, 16, 13, 0.40) 0%,
        rgba(20, 16, 13, 0.62) 55%,
        rgba(20, 16, 13, 0.74) 100%),
      url("../images/redwood-grove-1000.webp");
    background-position: center 34%;
  }
}
.hero__grid {
  display: grid; gap: clamp(2.5rem, 5vw, 4.5rem);
  grid-template-columns: 1fr; align-items: center;
}
@media (min-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 36rem); }
}

/* Reversed type. The shadows are wide and faint - not a visible drop shadow,
   just enough to keep the letterforms off a bright patch of bark. */
.hero .eyebrow { color: rgba(255, 255, 255, 0.88); }
.hero .eyebrow::before { background: rgba(255, 255, 255, 0.72); }
.hero h1 {
  color: var(--white); margin-bottom: var(--s5);
  text-shadow: 0 1px 26px rgba(12, 9, 7, 0.55);
}
.hero__lede {
  font-size: var(--step-1); line-height: 1.55; color: rgba(255, 255, 255, 0.94);
  margin-bottom: var(--s6); text-shadow: 0 1px 20px rgba(12, 9, 7, 0.5);
}
.hero__note { font-size: var(--step--1); color: rgba(255, 255, 255, 0.80); margin-top: var(--s5); }
.hero .btn--outline { color: var(--white); border-color: rgba(255, 255, 255, 0.75); }
.hero .btn--outline:hover { background: var(--white); color: var(--ink); border-color: var(--white); }

/* Two languages side by side. Tighter than the image splits, with a rule
   between the columns so the eye can tell which text it is reading. Stacks on
   anything narrower than a tablet. */
.split--bilingual { gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
@media (min-width: 900px) {
  .split--bilingual > div + div {
    border-left: 1px solid var(--line);
    padding-left: clamp(2rem, 4vw, 3.5rem);
  }
}
.lang-label {
  font-family: var(--font-body); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--sage-text);
  margin-bottom: var(--s4);
}

/* --- 9. Split sections (alternating text / image) ----------------------- */

.split { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--media-first .split__media { order: -1; }
  /* Photo on the right while staying first in the DOM, so a stacked phone
     layout still shows the portrait above the name rather than below it. */
  .split--media-last .split__media { order: 1; }
}
.split__media { max-width: 460px; width: 100%; }
.split__media--wide { max-width: 580px; }

/* A section built around one photograph: wider container, and the image takes
   the larger column. Roughly 780px of image instead of 460-580px. */
@media (min-width: 900px) {
  .split--feature { grid-template-columns: 0.82fr 1.18fr; }
}
.split--feature .split__media,
.split--feature .split__media--wide { max-width: 820px; }

/* --- 10. Cards ---------------------------------------------------------- */

.grid { display: grid; gap: var(--s5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }

.card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: var(--s5);
  display: flex; flex-direction: column;
}
/* A card title takes the h3 look whatever level the document outline needs it
   to be. On the groups page the cards sit directly under the h1, so they are
   marked up as h2 to keep the outline from skipping a level. */
.card h2, .card h3 { font-size: var(--step-2); line-height: 1.25; margin-bottom: var(--s3); }
.card p { font-size: var(--step-0); color: var(--ink); }
.card__meta {
  margin-top: auto; padding-top: var(--s4);
  font-size: var(--step--1); color: var(--muted);
}
.card__link {
  margin-top: var(--s4); font-size: var(--step--1); font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; text-decoration: none;
  display: inline-flex; align-items: center; gap: var(--s1);
}
.card__link::after { content: "\2192"; transition: transform 200ms var(--ease); }
.card__link:hover::after { transform: translateX(3px); }

.card--link { transition: border-color 200ms var(--ease), box-shadow 200ms var(--ease); }
.card--link:hover { border-color: var(--clay); box-shadow: var(--shadow-soft); }

/* --- 10b. Group chooser and detail --------------------------------------- */

.group-pick {
  display: grid; gap: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
}

/* Status label on a group card. */
.pill {
  display: inline-block; align-self: flex-start;
  font-family: var(--font-body); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.3rem 0.6rem; border-radius: 2px;
  background: var(--sage-wash); color: var(--sage-text);
  margin-bottom: var(--s3);
}
.pill--forming { background: var(--clay-wash); color: var(--clay-dark); }

/* Anchored detail sections. The offset clears the sticky header so a jump
   link does not land with the heading hidden underneath it. */
.group-detail { scroll-margin-top: 96px; }

.group-meta {
  margin: var(--s5) 0 var(--s6);
  padding: var(--s4) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  display: grid; gap: var(--s3);
  max-width: var(--prose);
}
.group-meta > div {
  display: grid; grid-template-columns: 9rem 1fr;
  gap: var(--s2) var(--s4); align-items: baseline;
}
.group-meta dt {
  font-family: var(--font-body); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}
.group-meta dd { margin: 0; font-size: var(--step-0); }

@media (max-width: 560px) {
  .group-meta > div { grid-template-columns: 1fr; gap: 0.15rem; }
}

/* --- 11. Therapist grid ------------------------------------------------- */

.people { display: grid; gap: var(--s6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.person__photo { margin-bottom: var(--s4); }
.person h3 { margin-bottom: var(--s1); }
.person__credential {
  font-size: var(--step--1); color: var(--clay-dark); font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: var(--s3);
}
.person__role { font-size: var(--step--1); color: var(--muted); margin-bottom: var(--s3); }
.person__credit { font-size: 0.7rem; color: var(--muted); margin: var(--s3) 0 0; letter-spacing: 0.02em; }
.person p { font-size: var(--step-0); }

/* A clinician row: portrait beside a full bio. Replaces the old card grid,
   which forced every bio to be the same short length. */
@media (min-width: 900px) {
  .split--person { grid-template-columns: 0.58fr 1.42fr; align-items: start; }
}
.split--person .split__media { max-width: 340px; }
.split--person h2 { margin-bottom: var(--s2); }

/* --- 12. Approach entries ----------------------------------------------- */

.approach { border-top: 1px solid var(--line); padding-top: var(--s5); margin-bottom: var(--s7); }
.approach:last-child { margin-bottom: 0; }
.approach__name { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3); margin-bottom: var(--s4); }
/* The heading level inside an .approach depends on where the component sits:
   h2 on the approaches page, where the articles hang straight off the h1,
   and h3 on the conditions page, where they sit under a section heading.
   Both are pinned to the same size here, so the outline can be correct on
   each page without the two pages looking different. */
.approach__name h2,
.approach__name h3 { font-size: var(--step-2); line-height: 1.25; margin: 0; }
.approach__tag {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--sage-text); background: var(--sage-wash);
  padding: 0.3rem 0.6rem; border-radius: 2px;
}
.approach__body { display: grid; gap: var(--s5); grid-template-columns: 1fr; }
@media (min-width: 820px) { .approach__body { grid-template-columns: 1.3fr 1fr; } }
.approach__aside {
  background: var(--clay-wash); padding: var(--s5); border-radius: var(--radius-sm);
  align-self: start;
}
.approach__aside h3,
.approach__aside h4 {
  font-size: var(--step-1); line-height: 1.3; font-weight: 600;
  margin-bottom: var(--s3); color: var(--sage-text);
}
.approach__aside p, .approach__aside li { font-size: var(--step--1); color: var(--ink); }
.approach__aside ul { margin-bottom: 0; }

/* A long list of concerns, set in columns so it scans instead of scrolls. */
.concern-list {
  columns: 3 190px;
  column-gap: var(--s6);
  list-style: none;
  padding: 0;
  margin: var(--s5) 0 0;
  max-width: none;
}
.concern-list li {
  break-inside: avoid;
  position: relative;
  padding-left: 1.05rem;
  margin-bottom: var(--s2);
  font-size: var(--step--1);
  line-height: 1.5;
}
.concern-list li::before {
  content: "";
  position: absolute; left: 0; top: 0.62em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--clay);
}

/* --- 13. Steps ---------------------------------------------------------- */
/* Numbered here on purpose: getting started IS an ordered sequence. */

.steps { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); max-width: none; }
.steps li { margin: 0; }
.step__num {
  font-family: var(--font-display); font-size: var(--step-2); color: var(--clay);
  display: block; margin-bottom: var(--s2); line-height: 1;
}
.steps h3 { font-size: var(--step-1); margin-bottom: var(--s2); }
.steps p { font-size: var(--step--1); color: var(--muted); }

/* --- 14. FAQ ------------------------------------------------------------ */

.faq { max-width: var(--wrap-narrow); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; padding: var(--s4) var(--s5) var(--s4) 0;
  font-family: var(--font-display); font-size: var(--step-1); font-weight: 500;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  font-family: var(--font-body); font-size: 1.5rem; font-weight: 400; color: var(--clay);
  transition: transform 200ms var(--ease);
}
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq summary:hover { color: var(--clay); }
.faq details > div { padding: 0 var(--s5) var(--s5) 0; }
.faq details > div p { color: var(--muted); }

/* --- 15. Values / trust strip ------------------------------------------- */

.values { display: grid; gap: var(--s6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.value h3 { font-size: var(--step-1); margin-bottom: var(--s2); }
.value p { font-size: var(--step--1); }

/* --- 16. Call-to-action band -------------------------------------------- */

.cta-band { text-align: center; }
.cta-band .eyebrow { justify-content: center; }
.cta-band p { margin-inline: auto; }
.cta-band .btn-row { justify-content: center; margin-top: var(--s6); }
.cta-band__phone {
  font-family: var(--font-display); font-size: var(--step-3);
  color: var(--sage-text); text-decoration: none; display: inline-block; margin-top: var(--s5);
}
.cta-band__phone:hover { color: var(--clay-dark); }

/* --- 17. Footer --------------------------------------------------------- */

.site-footer { background: var(--sage-deep); color: var(--ink); padding-block: var(--s8) var(--s6); font-size: var(--step--1); border-top: 1px solid rgba(69,86,75,0.16); }
.site-footer a { color: var(--ink); text-decoration: none; }
.site-footer a:hover { color: var(--sage-text); text-decoration: underline; }
/* Contact is the one link in the footer that is an action rather than a
   destination, so it leads its column and carries the accent colour and a
   little more weight. The arrow is drawn in CSS, so the link text itself stays
   the single word "Contact" for anything reading the markup. */
/* --clay-dark manages only 4.21:1 against the sage footer, which fails AA at
   this size, so the accent is taken one step darker here. Measured 5.09:1. */
.site-footer .footer__contact { font-weight: 600; color: #7A3D2E; }
.site-footer .footer__contact::after {
  content: "\2192"; display: inline-block; margin-left: 0.35rem;
  transition: transform 200ms var(--ease);
}
.site-footer .footer__contact:hover { color: #63311F; }
.site-footer .footer__contact:hover::after { transform: translateX(3px); }

.site-footer h3 { color: var(--sage-text); font-family: var(--font-body); font-size: 0.72rem;
  letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600; margin-bottom: var(--s3); }
.footer__grid { display: grid; gap: var(--s6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.footer__grid ul { list-style: none; padding: 0; margin: 0; }
.footer__grid li { margin-bottom: var(--s2); }
.footer__logo { width: 88px; height: auto; display: block; margin-bottom: var(--s3); }
.footer__wordmark { font-family: var(--font-display); font-size: var(--step-2); color: var(--sage-text); display: block; margin-bottom: var(--s3); }
.footer__bottom {
  margin-top: var(--s7); padding-top: var(--s5); border-top: 1px solid rgba(69,86,75,0.20);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); justify-content: space-between;
  font-size: 0.8rem; color: var(--sage-text);
}

/* Crisis notice: always reachable, never styled as an alarm. */
.crisis {
  background: var(--sage); color: var(--ink);
  padding: var(--s4) 0; font-size: 0.85rem; text-align: center;
}
.crisis a { color: var(--clay-dark); }
.crisis p { max-width: none; margin: 0; }

/* --- 18. Page intro ----------------------------------------------------- */

.page-intro { padding-block: clamp(3rem, 6vw, 5rem) 0; }

/* A page-intro normally runs into a section on the same cream ground, so there
   is no seam and no bottom padding is needed. Where it runs straight into a
   photographic band the colour edge lands on the last line of the lede, which
   reads as clipped. Give it room in that case only. */
.page-intro:has(+ .section--photo) { padding-bottom: clamp(2.5rem, 5vw, 4rem); }
.page-intro h1 { margin-bottom: var(--s5); }
.page-intro__lede { font-size: var(--step-1); line-height: 1.55; color: var(--muted); }

/* --- 18b. The thread ------------------------------------------------------
   One hairline in the left margin that draws downward as each section comes
   into view. Because the sections are contiguous, the segments join into a
   single unbroken line running the length of the page — the practice is called
   a continuum, and this is that idea rather than a decoration.

   Deliberately restrained: one pixel, the same hairline colour as the borders,
   a small clay node where each section begins. It sits in the margin, never
   over content, and is inert to the pointer. Shown only where there is real
   margin to put it in, and never when reduced motion is requested. */

@media (min-width: 1240px) and (prefers-reduced-motion: no-preference) {
  .js .section.reveal { position: relative; }

  .js .section.reveal::before,
  .js .section.reveal::after {
    content: "";
    position: absolute;
    left: calc(50% - 596px);
    pointer-events: none;
  }

  /* the drawn segment */
  .js .section.reveal::before {
    top: 0; bottom: 0;
    width: 1px;
    background: var(--line);
    transform: scaleY(0);
    transform-origin: top center;
  }
  .js .section.reveal.is-visible::before {
    transform: scaleY(1);
    transition: transform 1100ms var(--ease-soft) 120ms;
  }

  /* the node where a section begins */
  .js .section.reveal::after {
    top: var(--section-y);
    width: 5px; height: 5px;
    margin-left: -2px;
    border-radius: 50%;
    background: var(--clay);
    opacity: 0;
    transform: scale(.4);
  }
  .js .section.reveal.is-visible::after {
    opacity: 1;
    transform: scale(1);
    transition: opacity 500ms var(--ease-soft) 420ms, transform 500ms var(--ease-soft) 420ms;
  }

  /* the photo band closes the page; a hairline over a photograph reads as a seam */
  .js .section--photo.reveal::before,
  .js .section--photo.reveal::after { display: none; }
}

/* --- 19. Scroll reveal -------------------------------------------------- */

/* Sections do not fade in as slabs. Their parts arrive in reading order:
   eyebrow, heading, body, then cards, about 70ms apart, which reads as
   settling rather than sliding. Photographs get their own longer, slower
   treatment so they feel heavier than the text beside them.

   Gated on the .js class set by an inline script in <head>: without
   JavaScript the class never lands and every section renders normally.
   Content must never depend on a script to be visible. */

@media (prefers-reduced-motion: no-preference) {
  .js .anim {
    opacity: 0;
    transform: translateY(14px);
  }
  .js .is-visible .anim {
    opacity: 1;
    transform: none;
    transition:
      opacity   760ms var(--ease-soft) var(--d, 0ms),
      transform 760ms var(--ease-soft) var(--d, 0ms);
  }

  /* Portraits do not move at all: no drift, no settle-scale. A face easing
     in from an overscale looks like a zoom effect applied to a person. They
     fade in with everything else and otherwise hold still. */
  .js .anim.media.person__photo img,
  .js .is-visible .anim.media.person__photo img {
    transform: none;
    transition: none;
  }

  /* A photograph settles into its frame instead of sliding up: the frame
     fades, the image itself eases down from a slight overscale. Slower than
     the text so the two do not move in lockstep. */
  .js .anim.media { transform: none; }
  .js .anim.media img {
    transform: scale(1.04);
    transition: transform 1300ms var(--ease-soft) var(--d, 0ms);
  }
  .js .is-visible .anim.media img { transform: scale(1); }

  /* The eyebrow's short rule draws itself out, left to right. It is the one
     piece of ornament the design already had, so it is the one that moves. */
  .js .anim.eyebrow::before {
    transform: scaleX(0);
    transform-origin: left center;
  }
  .js .is-visible .anim.eyebrow::before {
    transform: scaleX(1);
    transition: transform 700ms var(--ease-soft) calc(var(--d, 0ms) + 160ms);
  }

  /* Parallax and the settle-in scale live on different elements: the
     wrapper moves, the image scales, so neither overwrites the other. */

  /* Whatever opens a page runs the same sequence on load, from a little
     further down, because there is nothing above it to anchor against. */
  .js .hero .anim,
  .js .page-intro .anim { transform: translateY(18px); }
}
