/* ============================================================================
   profile.css — layout for the therapist profile page.
   One responsive stylesheet, desktop-first, derived from both artboards:
     · desktop-profile.jsx  — 1440px (pad 80, rail 360, gap 40)
     · mobile-profile.jsx   — 390px  (pad 20, single column, sticky book bar)
   Breakpoints:
     1180px — gutters + rail step down (see tokens.css)
      980px — rail drops under the main column, hero CTA wraps
      640px — mobile artboard: flat sections, stacked hero, sticky bottom CTA
   ========================================================================== */

.page { max-width: var(--page-max); margin: 0 auto; }

/* -- Hero (profileHeader) -------------------------------------------------- */
/* Grid rather than flex so the chips/meta rows can span the full width at the
   mobile breakpoint (as in the 390 artboard) without re-ordering the DOM.
   Empty areas collapse, so a profile with no CTA loses the third column. */
.hero {
  margin: 24px var(--pad) 0;
  padding: 36px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "avatar id    cta"
    "avatar chips cta"
    "avatar meta  cta";
  align-items: start;
  column-gap: 36px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-hero);
}
.hero > .avatar { grid-area: avatar; }
.hero-id { grid-area: id; }
.hero > .chips { grid-area: chips; }
.hero > .meta { grid-area: meta; }
.hero-cta { grid-area: cta; }

.avatar {
  --avatar: 156px;
  width: var(--avatar);
  height: var(--avatar);
  border-radius: calc(var(--avatar) * 0.18);
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  /* ⚠ HUE 45, NOT 165 — THIS GRADIENT DOES NOT READ THE TOKENS. It is written
     in literal oklch because a gradient cannot be expressed as one custom
     property, and that is exactly why it survived the palette change: every
     token on the site moved from sage green to terracotta and this tile stayed
     green, on the largest single block of colour on a profile page, directly
     beside the therapist's name. If the accent hue moves again, it has to be
     changed here by hand — there is nothing to inherit from. */
  background: radial-gradient(120% 90% at 20% 15%,
    oklch(0.94 0.032 45) 0%, oklch(0.80 0.050 45) 60%, oklch(0.65 0.062 42) 100%);
  box-shadow: inset 0 0 0 1px oklch(0.23 0.020 40 / 0.06), 0 1px 2px oklch(0.23 0.020 40 / .05);
}
.avatar .sheen {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, oklch(0.98 0.012 70 / .35) 0%, transparent 45%, oklch(0.35 0.050 42 / .08) 100%);
}
.avatar .ini {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-serif);
  font-size: calc(var(--avatar) * 0.42);
  letter-spacing: -0.02em;
  color: var(--avatar-face);
  text-shadow: 0 1px 2px oklch(0.22 0.018 170 / .25);
}
/* The portrait, painted OVER the monogram rather than instead of it.
   `.ini` is always in the DOM and this element covers it, so a photo that 404s,
   is blocked, or has not decoded yet leaves the initials tile the design was
   built around. Nothing here paints a background: a failed <img> must be
   transparent, not a grey box. The box is fixed by `--avatar`, so the image
   cannot shift the layout whatever its intrinsic size turns out to be, and
   `object-fit: cover` keeps a non-square source from stretching a face.

   ⚠ `position` AND `z-index` ARE BOTH REQUIRED, AND THIS RULE GOING MISSING IS
   NOT A COSMETIC FAILURE. `.ini` is absolutely positioned; without this rule
   the image is a static in-flow box, positioned elements paint above in-flow
   ones, and the initials land in 52px serif across the middle of a real
   clinician's face. That shipped — a cached pre-deploy profile.css met the new
   markup and every profile read "JL" over the photograph. `z-index: 1` makes
   the stack explicit rather than a consequence of DOM order, and the `onload`
   in profile.js removes the monogram outright once the image has decoded, so
   the two failure modes (stale CSS, blocked CSS) are covered independently. */
.avatar .photo {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: transparent;
  border: 0;
}
/* Above the portrait, so the live dot is never buried by it. */
.avatar .live { z-index: 2; }

/* Only rendered when the therapist is accepting new clients. */
.avatar .live {
  position: absolute;
  right: calc(var(--avatar) * 0.06);
  bottom: calc(var(--avatar) * 0.06);
  width: calc(var(--avatar) * 0.16);
  height: calc(var(--avatar) * 0.16);
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 0 max(2px, calc(var(--avatar) * 0.04)) var(--surface);
}

.hero-id { min-width: 0; padding-top: 4px; }

.hero h1 { font-size: 52px; line-height: 1.05; letter-spacing: -0.022em; }
.hero h1 .cred { color: var(--sage-deep); font-weight: 500; }

/* title · location · license — separated by CSS dots, no markup for them */
.subline {
  margin-top: 12px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 16px;
  color: var(--ink-2);
}
.subline li { display: inline-flex; align-items: center; gap: 12px; }
.subline li + li::before {
  content: "";
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--ink-4);
  flex-shrink: 0;
}
.subline .lic { font-family: var(--font-mono); font-size: 13.5px; color: var(--ink-3); }

.hero .chips { margin-top: 22px; }

/* years · languages · network · fee */
.meta {
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 18px;
  font-size: 14px;
  color: var(--ink-2);
}
.meta li { display: inline-flex; align-items: center; gap: 18px; }
.meta li + li::before {
  content: "";
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--ink-4);
  flex-shrink: 0;
}
.meta b { color: var(--ink); font-weight: 500; }
.meta .meta-label { display: none; }   /* label form is mobile-only */
.meta .meta-tail { color: var(--ink-3); }

.hero-cta {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  width: 240px;
}
.cta-note { font-size: 13px; line-height: 1.45; color: var(--ink-3); text-align: center; }
.cta-note b { color: var(--ink); font-weight: 500; }
.cta-sub {
  padding-top: 10px;
  border-top: 1px dashed var(--line);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-3);
  text-align: center;
}

/* -- Main grid ------------------------------------------------------------- */
.layout {
  padding: 32px var(--pad) 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--rail);
  gap: var(--gap);
  align-items: start;
}
.col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.rail { display: flex; flex-direction: column; gap: 16px; position: sticky; top: 24px; }

/* -- Availability panel ---------------------------------------------------- */
/* .strip-box is transparent on desktop (the whole panel is already a card) and
   becomes its own card at the mobile breakpoint, matching the 390 artboard. */
.strip-box { border-radius: 14px; }

.stats {
  margin-top: 28px;
  padding-top: 26px;
  border-top: 1px solid var(--line-soft);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
  /* row-gap 0: with subgrid the parent's row gutter would otherwise open up
     inside every stat block. Vertical rhythm comes from the child margins. */
  gap: 0 24px;
}
/* subgrid keeps the three values on one baseline when a label wraps.
   Browsers without subgrid fall back to independent rows — same as before. */
.stat { display: grid; grid-template-rows: subgrid; grid-row: span 3; align-content: start; }
.stat .eyebrow { margin-bottom: 10px; }
.stat .v {
  font-family: var(--font-serif);
  font-size: 30px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.stat .v small { font-size: 18px; font-weight: 400; color: var(--ink-3); }
.stat .v--text { font-size: 25px; letter-spacing: -0.012em; }
.stat .v--empty { color: var(--ink-3); }   /* the em-dash "no data yet" state */
.stat .s { margin-top: 6px; font-size: 12.5px; color: var(--ink-3); }

/* -- About panel ----------------------------------------------------------- */
.bio {
  font-family: var(--font-serif);
  font-size: 18px;
  line-height: 1.65;
  letter-spacing: -0.003em;
  color: var(--ink);
  text-wrap: pretty;
  display: block;
}

/* "Read more" without a line of JavaScript: a <details> whose <summary> holds
   the whole bio. Closed → the text is line-clamped; open → clamp removed. */
.bio-toggle > summary {
  display: block;
  list-style: none;
  cursor: pointer;
}
.bio-toggle > summary::-webkit-details-marker { display: none; }
.bio-toggle > summary::marker { content: ""; }
.bio-toggle .linkbtn { margin-top: 16px; }
.bio-toggle[open] .toggle-more,
.bio-toggle:not([open]) .toggle-less { display: none; }
.bio-toggle[open] .toggle-chev { transform: rotate(180deg); }
/* Above the mobile breakpoint the bio is never clamped, so the toggle is
   hidden and the summary is inert (see RENDER-NOTES). */
.bio-toggle > summary { cursor: default; }
.bio-toggle .linkbtn { display: none; }

/* -- Experience / approaches ----------------------------------------------- */
.split { display: grid; grid-template-columns: 1.4fr 1fr; gap: 36px; }
.split > * { min-width: 0; }
.split .right { padding-left: 28px; border-left: 1px solid var(--line-soft); }
.split .eyebrow { margin-bottom: 12px; }

/* -- Platform terms (fee + session formats) -------------------------------- */
/* Deliberately reads as an inset block quoted from elsewhere, not as one of
   the therapist's own panels — these are the platform's terms. */
.plat-fee { padding: 18px 20px; margin-bottom: 22px; }
.plat-fee .eyebrow { margin-bottom: 8px; }
.plat-fee .v {
  font-family: var(--font-serif);
  font-size: 30px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.plat-fee .v small { font-size: 17px; font-weight: 400; color: var(--ink-3); }
.plat-fee .s { margin-top: 8px; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
.plat-sub { margin-bottom: 12px; }

/* -- Services -------------------------------------------------------------- */
.svc { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.svc .item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
}
.svc .ico-tile {
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--sage-tint);
  color: var(--sage-deep);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  font-size: 17px;
}
.svc .nm { font-size: 15px; font-weight: 500; color: var(--ink); }
.svc .sb { font-size: 12px; color: var(--ink-3); margin-top: 2px; }

/* The disclosure block lives in base.css — it is identical on every page type
   and was previously defined here AND in archive.css. */

/* The one line on this page that is about the page rather than the person. */
.report-l {
  padding: 4px 4px 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
  text-wrap: pretty;
}

/* -- Sticky mobile book bar ------------------------------------------------ */
.sticky-cta { display: none; }

/* ==========================================================================
   1180 → gutters/rail shrink (tokens.css), headline steps down
   ========================================================================== */
@media (max-width: 1180px) {
  .hero h1 { font-size: 42px; }
  .avatar { --avatar: 132px; }
  .hero { padding: 28px; gap: 28px; }
}

/* ==========================================================================
   980 → single column; the rail becomes a normal stack under the content
   ========================================================================== */
@media (max-width: 980px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; }
  .hero {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "avatar id"
      "avatar chips"
      "avatar meta"
      "cta    cta";
  }
  .hero-cta { width: 100%; margin-top: 22px; }
  .split { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .split .right { padding-left: 0; padding-top: 22px; border-left: none; border-top: 1px solid var(--line-soft); }
  .svc { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   640 → the 390px artboard: flat sections, stacked hero, sticky book bar
   ========================================================================== */
@media (max-width: 640px) {
  /* The header, the breadcrumb and the footer are in base.css — one definition
     for every page type, because two copies of them is how the mobile nav came
     to be `display: none` on both and replaced on neither. */

  /* Hero flattens onto the sand background (no card) */
  .hero {
    margin: 0;
    padding: 20px var(--pad) 22px;
    column-gap: 14px;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "avatar id"
      "chips  chips"
      "meta   meta"
      "cta    cta";
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
  .avatar { --avatar: 84px; }
  .hero-id { padding-top: 2px; }
  .hero h1 { font-size: 26px; line-height: 1.1; letter-spacing: -0.018em; }

  .subline { display: block; margin-top: 6px; font-size: 13px; line-height: 1.45; }
  .subline li { display: block; }
  .subline li + li::before { display: none; }
  .subline .lic { font-size: 11.5px; margin-top: 4px; display: inline-block; }

  .hero .chips { margin-top: 18px; }
  .hero .chip { padding: 5px 9px; font-size: 12px; }

  /* ⚠ 11px IS THE FLOOR ON THIS PAGE, RAISED 17 Aug 2026 BY THE LAUNCH SWEEP.
     Five rules in this block sat below it — the meta-strip labels and the
     availability stats at 9.5px, the chart axis and the callout eyebrow at
     10px, and the stat sub-line at 10.5px. Everything else on both sites that
     the sweep flagged as small is an 11px UPPERCASE label with tracking, which
     reads about as large as 13px lowercase and is the design's deliberate
     small-caps device. These five were not that:

       · 9.5px is below the size at which uppercase tracking still helps.
       · `.stat .s` — "every one of the last 30 days checked" — is a SENTENCE,
         not a label, and it was set at 10.5px. Running prose does not get the
         benefit of the doubt a two-word label does.

     This is the profile, which is 22,000 of each site's 22,300 pages and the
     one people actually read. */
  /* Meta strip becomes the 4-up labelled grid from the mobile artboard */
  .meta {
    margin-top: 18px;
    padding: 16px 0;
    gap: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
  }
  .meta li { display: block; padding-left: 10px; border-left: 1px solid var(--line-soft); min-width: 0; }
  .meta li:first-child { padding-left: 0; border-left: none; }
  .meta li + li::before { display: none; }
  .meta .meta-label { display: block; font-size: 11px; margin-bottom: 4px; }
  .meta .meta-value {
    display: block;
    font-family: var(--font-serif);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .meta .meta-tail { display: none; }   /* "years experience" etc. — label carries it */

  .hero-cta { margin-top: 18px; gap: 6px; }
  .cta-sub { display: none; }

  /* Sections flatten: no card chrome, page-gutter padding only */
  .layout { padding: 0; gap: 0; }
  .col, .rail { gap: 0; }
  .card {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 24px var(--pad) 4px;
  }
  .sec-head { flex-wrap: wrap; align-items: baseline; gap: 10px; margin-bottom: 10px; }
  .sec-head h2 { font-size: 22px; }
  /* Reading sizes up, label sizes unchanged — the same rule as the other three
     sheets. `.lede` explains what a whole panel is; `.sec-sub`, the axis, the
     legend and the eyebrows are labels and stay small. */
  .lede { margin: 0 0 16px; font-size: 15.5px; }
  .sec-sub { font-size: 14px; }

  /* …but the availability readout keeps its box, as in the artboard */
  .strip-box {
    padding: 16px;
    background: var(--surface);
    border: 1px solid var(--line);
  }
  .cell { border-radius: 3px; }
  .axis { margin-top: 8px; font-size: 11px; }
  .legend { gap: 12px; margin-top: 12px; font-size: 11px; }
  .sw { width: 9px; height: 9px; border-radius: 2px; }
  .stats { margin-top: 18px; padding-top: 16px; gap: 0 14px; }
  .stat .eyebrow { font-size: 11px; margin-bottom: 4px; }
  .stat .v { font-size: 18px; }
  .stat .v small { font-size: 12px; }
  .stat .v--text { font-size: 15px; }
  .stat .s { margin-top: 4px; font-size: 12px; }
  .callout { margin-top: 12px; padding: 14px; border-radius: 12px; }
  .callout .eyebrow { font-size: 11px; margin-bottom: 6px; }
  .callout p { font-size: 14.5px; line-height: 1.55; }

  .bio { font-size: 16px; line-height: 1.6; }
  .bio-toggle:not([open]) .bio {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 5;
    line-clamp: 5;
    overflow: hidden;
  }
  .bio-toggle > summary { cursor: pointer; }
  /* "Read more" and "Check this license in {State}" are the two text-only
     controls on this page, and both were a 21px line of text. */
  .bio-toggle .linkbtn { display: inline-flex; margin-top: 8px; }
  .linkbtn { min-height: 44px; font-size: 15px; }

  .split { gap: 18px; }
  .split .right { padding-top: 18px; }
  .empty { font-size: 13.5px; }

  .svc { grid-template-columns: minmax(0, 1fr); }
  .plat-fee { padding: 14px 16px; margin-bottom: 16px; }
  .plat-fee .v { font-size: 22px; }
  .plat-fee .v small { font-size: 13px; }
  .plat-fee .s { margin-top: 6px; font-size: 11.5px; }

  /* Rail cards keep their card treatment (as in the artboard) */
  .rail { padding: 0 var(--pad); }
  .rcard { padding: 16px; margin-top: 20px; border-radius: 14px; }
  .report-l { margin-top: 18px; font-size: 14.5px; }
  .report-l a { display: inline-flex; align-items: center; min-height: 44px; }
  .rcard-lede, .trust-copy { font-size: 14.5px; }
  .facts dt { font-size: 14px; }
  .facts dd { font-size: 15px; }
  .licbox .ico-tile { width: 38px; height: 38px; border-radius: 10px; font-size: 17px; }
  .licbox .t { font-size: 17px; letter-spacing: -0.008em; }

  /* Sticky "Book intake call" bar — same single action as the artboard */
  body { padding-bottom: 92px; }
  .sticky-cta {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 15;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px var(--pad) 14px;
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    box-shadow: var(--shadow-sticky);
  }
  /* ⚠ THE BAR IS A STRIP, NOT A PANEL — AND IT WAS NOT. Found by the launch
     sweep, 17 Aug 2026, on the page type that is 22,000 of this site's 22,300:

         430px → 98px tall      390px → 116px      360px → 169px      320px → 223px

     At 320 the bar covered A QUARTER OF THE SCREEN and the label column was
     FIFTEEN PIXELS WIDE — one character per line, "Open every one of the last
     30 days" set as a vertical ribbon of letters beside the button.

     The cause is a fixed-width button in a flex row. `.btn` is `253px` because
     nothing told it it could shrink, and `flex: 1` on `.l` only says "take the
     REMAINING space" — when there is none left, the text wraps to whatever it
     can get and the row grows downwards without limit.

     Three rules fix it and each is load-bearing:
       · the button may shrink (`flex-shrink` is 1 here, `min-width: 0` lets it
         go below its content width) but not below a thumb, and its label
         does not wrap;
       · the label column is capped at one line each for the two lines it
         holds, and truncates rather than wraps — a bar that grows is worse
         than a sentence that ends in an ellipsis;
       · and at the narrowest widths the availability line goes entirely.
         "Get started on BetterHelp" is what the bar is for; the availability
         summary is repeated in full further up the page. */
  .sticky-cta {
    align-items: center;
    gap: 10px;
  }
  .sticky-cta .l {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
  }
  .sticky-cta .avail,
  .sticky-cta .ver {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sticky-cta .avail { font-size: 12px; color: var(--ink-3); }
  .sticky-cta .avail b { color: var(--ink); font-weight: 500; }
  .sticky-cta .ver {
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--sage-deep);
  }
  /* The dot is an inline-flex child of a now-nowrap block; keep it aligned
     without letting it re-introduce a flex context that ignores the ellipsis. */
  .sticky-cta .ver .led { vertical-align: middle; }
  .sticky-cta .btn {
    flex: 0 1 auto;
    min-width: 0;
    padding: 13px 16px;
    font-size: 15px;
    white-space: nowrap;
  }
}

/* Under 400px the label loses the argument entirely. Two lines of truncated
   text next to a button that has already given up its padding is worse than
   one clear button, and the same availability figures are in the strip and the
   quick-facts card higher up the page. */
@media (max-width: 400px) {
  .sticky-cta .l { display: none; }
  .sticky-cta .btn { flex: 1 1 auto; justify-content: center; }
}

/* Print: drop the sticky bar and the interactive affordances. */
@media print {
  .sticky-cta, .skip-link, .site-nav, .navt { display: none; }
  .bio-toggle:not([open]) .bio { display: block; -webkit-line-clamp: none; line-clamp: none; }
  .card, .rcard { break-inside: avoid; box-shadow: none; }
}
