/* =========================================================================
   The MLD Register - main.css
   ONE source-of-truth stylesheet. Design tokens first, then base,
   components, utilities, page-specific sections. All style edits go here.

   Identity: "The Living Ledger" (see DESIGN.md). Committed bottle-green on
   warm bone paper with aged-brass detail; Source Serif 4 display over
   Hanken Grotesk body; ledger-entry captions, index numbering and the
   scalloped verification seal as signature motifs. Mobile-first.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Design tokens
   ------------------------------------------------------------------------- */
:root {
  /* Palette (OKLCH; neutrals tinted toward the brand hues, never #000/#fff) */
  --ink: oklch(0.24 0.02 165);
  --ink-soft: oklch(0.42 0.02 165);
  --ink-mute: oklch(0.50 0.016 165); /* >=4.5:1 on paper, paper-2 and green-wash */
  --paper: oklch(0.972 0.008 95);
  --paper-2: oklch(0.943 0.012 95);
  --surface: oklch(0.99 0.004 95);
  /* Filter-panel cards. Rick's specified value (25 Jul 2026), kept as the
     authored hex so it is exactly the colour he picked; it sits in the same
     warm hue-95 family as paper/surface, a shade lighter than paper-2 so the
     cards lift off the panel behind them. */
  --filter-card: #fcfaf1;
  --line: oklch(0.9 0.012 110);
  --line-strong: oklch(0.8 0.02 110);
  --green: oklch(0.36 0.055 165);
  --green-deep: oklch(0.27 0.045 168);
  --green-wash: oklch(0.93 0.02 160);
  --brass: oklch(0.62 0.09 85);
  --brass-deep: oklch(0.52 0.085 80);
  --brass-soft: oklch(0.9 0.045 90);
  --verified: oklch(0.5 0.09 160);
  --verified-wash: oklch(0.94 0.025 160);
  --danger: oklch(0.5 0.13 25);
  --danger-wash: oklch(0.95 0.02 25);
  --focus: oklch(0.55 0.13 250);

  /* On-green (light text on the committed colour needs +line-height too) */
  --on-green: oklch(0.96 0.01 120);
  --on-green-soft: oklch(0.83 0.02 140);

  /* Typography */
  --font-serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --font-sans: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI',
               Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Rhythm */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: clamp(3.5rem, 8vw, 6rem);
  --radius: 4px;
  --radius-lg: 12px;
  --shadow-1: 0 1px 2px oklch(0.27 0.045 168 / 0.07), 0 1px 8px oklch(0.27 0.045 168 / 0.05);
  --shadow-2: 0 2px 8px oklch(0.27 0.045 168 / 0.09), 0 12px 32px oklch(0.27 0.045 168 / 0.08);
  /* 80rem = 1280px, the common modern page shell (Tailwind's 7xl; Bootstrap
     sits either side at 1140 and 1320). The old 74rem was undocumented and
     inside the normal range, but it was costing the one page that needs the
     room: almost all the extra goes to the finder's results column, because
     the map beside it is a fixed 22rem. Prose is unaffected either way -
     .prose, guides and forms cap themselves at 46-52rem and every paragraph
     at 70ch, so this widens listings and admin tables, not reading measure. */
  --container: 80rem;
  --container-narrow: 46rem;
  --ease-out: cubic-bezier(0.165, 0.84, 0.44, 1); /* ease-out-quart */

  /* Component tones: every literal a component rule needs, hoisted so a
     per-brand theme.css can re-skin without touching component CSS.
     Values are the engine's Living Ledger defaults. */
  --header-bg: #f7f6f0;
  --header-bg-home: #fff;
  --link-underline: oklch(0.62 0.09 85 / 0.75);
  --on-green-hairline: oklch(0.96 0.01 120 / 0.16);
  --on-green-hairline-strong: oklch(0.96 0.01 120 / 0.18);
  --on-green-mute: oklch(0.72 0.02 150);
  --btn-secondary-border: oklch(0.36 0.055 165 / 0.45);
  --off-white: oklch(0.99 0.004 95);
  --tone-danger-border: oklch(0.7 0.08 25);
  --tone-danger-ink: oklch(0.38 0.12 25);
  --tone-success-border: oklch(0.65 0.08 160);
  --tone-success-ink: oklch(0.35 0.08 160);
  --tone-verified-border: oklch(0.6 0.08 160);
  --tone-verified-ink: oklch(0.35 0.09 160);
  --tone-neutral-border: oklch(0.55 0.06 165);
  --tone-warn-ink: oklch(0.42 0.08 80);
  --notice-border: oklch(0.7 0.04 160);
  --search-keyline: #92afa4;
  --filter-ink: #727272;
  --filter-line: #a8a8a8;
  --cta-ring: oklch(0.62 0.09 85 / 0.35);
  --cta-ring-soft: oklch(0.62 0.09 85 / 0.2);
  --cta-outline: oklch(0.96 0.01 120 / 0.5);
  --cta-outline-wash: oklch(0.96 0.01 120 / 0.1);
  --radius-stamp: 3px;
  --flourish-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20360%20240'%3E%3Cg%20fill='none'%20stroke='%23F2EFE4'%20stroke-width='2.5'%20stroke-linecap='round'%3E%3Cpath%20d='M-10,120C60,70,140,170,220,120S350,70,380,110'/%3E%3Cpath%20d='M-10,150C60,100,140,200,220,150S350,100,380,140'/%3E%3Cpath%20d='M-10,180C60,130,140,230,220,180S350,130,380,170'/%3E%3C/g%3E%3C/svg%3E");
  --select-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23727272' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* -------------------------------------------------------------------------
   2. Font faces (self-hosted variable files, exactly two - no CDN)
   ------------------------------------------------------------------------- */
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/source-serif-4-var.woff2') format('woff2');
}

@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/hanken-grotesk-var.woff2') format('woff2');
}

/* -------------------------------------------------------------------------
   3. Reset and base
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--font-serif);
  font-weight: 600;
  line-height: 1.14;
  color: var(--ink);
  margin: 0 0 var(--space-4);
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.2rem, 5vw, 3.4rem); }
h2 { font-size: clamp(1.6rem, 3.2vw, 2.3rem); margin-top: var(--space-6); }
h3 { font-size: clamp(1.25rem, 2vw, 1.5rem); margin-top: var(--space-5); }
h4 { font-size: 1.1rem; }

p { margin: 0 0 var(--space-4); max-width: 70ch; text-wrap: pretty; }
li { text-wrap: pretty; }

a {
  color: var(--green);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2.5px;
  text-decoration-color: var(--link-underline);
  transition: color 160ms var(--ease-out), text-decoration-color 160ms var(--ease-out);
}

a:hover { color: var(--green-deep); text-decoration-color: currentColor; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

img { max-width: 100%; height: auto; display: block; }

ul, ol { padding-left: 1.4rem; margin: 0 0 var(--space-4); }
li { margin-bottom: var(--space-2); }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--space-6) 0; }

blockquote {
  margin: var(--space-5) 0;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
  font-family: var(--font-serif);
  font-style: italic;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--space-5);
  font-size: 1.1rem;
}

th, td {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-soft);
  border-bottom: 2px solid var(--brass);
}

::selection { background: var(--brass-soft); color: var(--ink); }

/* -------------------------------------------------------------------------
   4. Layout primitives
   ------------------------------------------------------------------------- */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

.container-narrow {
  max-width: var(--container-narrow);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

.section { padding-block: var(--space-8); }
.section-tint { background: var(--paper-2); }
/* Collapse the top padding when a section follows another of the SAME
   background (e.g. two paper sections in a row), so the shared background
   does not read as one enormous empty gap. Applied per instance, never
   blanket, because colour-banded sections need their own top padding. */
.section-flush-top { padding-block-start: 0; }
.section-green {
  background: var(--green-deep);
  color: var(--on-green-soft);
}
.section-green h2, .section-green h3 { color: var(--on-green); }
.section-green p { line-height: 1.75; }
.section-green a { color: var(--on-green); text-decoration-color: var(--brass); }
.section-green a:hover { color: var(--brass-soft); }
.section-green .text-muted { color: var(--on-green-soft); }

/* Quiet corner flourish: the logo's flow-wave lines, whisper-faint in the
   bottom-right of a green band. Opt-in per section via .section-flourish. */
.section-flourish { position: relative; overflow: hidden; }

.section-flourish > .container { position: relative; z-index: 1; }

.section-flourish::after {
  content: '';
  position: absolute;
  right: -5rem;
  bottom: -3rem;
  width: 30rem;
  height: 20rem;
  background: var(--flourish-image) no-repeat;
  background-size: contain;
  opacity: 0.12;
  pointer-events: none;
}

/* Light surfaces inside a green section keep the ink palette */
.section-green .verification-box,
.section-green .card { color: var(--ink-soft); }
.section-green .verification-box h2, .section-green .verification-box h3,
.section-green .card h2, .section-green .card h3 { color: var(--ink); }
.section-green .verification-box a:not(.chip),
.section-green .card a:not(.chip) { color: var(--green); text-decoration-color: var(--link-underline); }
.section-green .verification-box a:not(.chip):hover,
.section-green .card a:not(.chip):hover { color: var(--green-deep); }
.section-green .card .text-muted { color: var(--ink-mute); }
/* The featured card's Verified stamp is a plain .chip like every other one on
   the site now; keep its ink readable against the card on the green band. */
.section-green .card a.chip { color: var(--ink-soft); }

.section-lead {
  max-width: 44rem;
  color: var(--ink-soft);
  font-size: 1.2rem;
  font-family: var(--font-serif);
  line-height: 1.6;
}

.section-green .section-lead { color: var(--on-green-soft); }

.grid-2, .grid-3, .grid-4 {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 960px) {
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}

/* -------------------------------------------------------------------------
   5. Header
   ------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--green-deep);
  color: var(--on-green);
  padding: var(--space-3) var(--space-5);
  z-index: 100;
}

.skip-link:focus { left: 0; color: var(--on-green); }

.site-header {
  background: var(--header-bg); /* interior pages; homepage is #fff (see .page-home) */
  border-bottom: 1px solid var(--line);
  position: relative;
  z-index: 20;
}

/* Brand lockup on the left, vertically centred against the right-hand stack
   (utility row + nav). This is what makes the logo read as centred in the
   header instead of stranded below an empty utility band. */
.site-header-grid {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  padding-block: var(--space-6) var(--space-6);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  flex: none;
  text-decoration: none;
  color: var(--green-deep);
}

.wordmark:hover { color: var(--green); }

/* The full lockup: seal + wordmark + strapline, sized for real presence
   (mirrors the footer sign-off). */
.wordmark-lockup {
  display: block;
  height: 4.25rem;
  width: auto;
}

/* Right-hand stack: member utility row above the primary nav. */
.site-header-bar {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-4);
}

.footer-brand img { max-width: min(420px, 100%); height: auto; }

.site-nav ul {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav li { margin: 0; }

.site-nav a:not(.btn) {
  text-decoration: none;
  color: var(--ink-soft);
  font-size: 0.98rem;
  font-weight: 600;
  padding: var(--space-2) 0;
  border-bottom: 2px solid transparent;
}

.site-nav a:not(.btn):hover,
.site-nav a:not(.btn)[aria-current="page"] {
  color: var(--green-deep);
  border-bottom-color: var(--brass);
}

.nav-toggle {
  display: none;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}

.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 16px;
  height: 2px;
  background: currentColor;
  position: relative;
  content: '';
}

.nav-toggle-bars::before { position: absolute; top: -5px; }
.nav-toggle-bars::after { position: absolute; top: 5px; }

@media (max-width: 900px) {
  /* The right stack becomes its own full-width row under the lockup: utility
     + toggle share a line, the nav drops to a full-width line below when
     opened. flex-basis 100% keeps the row's position IDENTICAL whether the
     menu is open or closed - previously opening the menu inflated this box to
     full width and its flex-end alignment made the controls jump right. */
  .site-header-bar {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-start;
    flex-basis: 100%;
    gap: var(--space-3) var(--space-4);
  }
  .js .nav-toggle { display: inline-flex; }
  .js .site-nav { display: none; flex-basis: 100%; width: 100%; }
  .js .site-nav.open { display: block; padding-block: var(--space-3) var(--space-2); }
  .js .site-nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .js .site-nav a:not(.btn) {
    display: block;
    padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--line);
  }
}

/* PHONE HEADER: the lockup gets its own centred row with more presence (3rem
   -> 3.75rem, +25%), and the utility + Menu line centres beneath it. Must sit
   AFTER the 900px block, which also targets .site-header-bar's justification. */
@media (max-width: 600px) {
  .wordmark-lockup { height: 3.75rem; }
  .site-header-grid { justify-content: center; }
  .wordmark { flex-basis: 100%; justify-content: center; }
  .site-header-bar { justify-content: center; }
}

/* Member utility row (log in + Join), right-aligned at the top of the stack. */
.site-header-utility {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.header-login {
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.header-login:hover, .header-login[aria-current="page"] { color: var(--green-deep); }

/* Homepage only: the logo + menu row sits on pure white. The utility row
   (log in + Join) keeps its usual tint. */
.page-home .site-header { background: var(--header-bg-home); }

/* Site-wide notice bar (operator setting notice_bar_text; empty = hidden).
   One quiet line above the header for register-wide announcements. */
.notice-bar { background: var(--green-deep); color: var(--on-green); }
.notice-bar p {
  max-width: none; /* centred <p> gotcha: the base 70ch cap pins it left */
  margin: 0;
  padding-block: var(--space-2);
  text-align: center;
  font-size: 0.95rem;
  line-height: 1.45;
}
.notice-bar a { color: inherit; }

/* -------------------------------------------------------------------------
   6. Footer
   ------------------------------------------------------------------------- */
.site-footer {
  background: var(--green-deep);
  color: var(--on-green-soft);
  margin-top: var(--space-8);
  padding-block: var(--space-7) var(--space-6);
  font-size: 0.95rem;
  line-height: 1.75;
}

.footer-brand {
  padding-bottom: var(--space-6);
  margin-bottom: var(--space-6);
  border-bottom: 1px solid var(--on-green-hairline);
}

.footer-brand a { text-decoration: none; display: inline-block; }

.footer-columns {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--on-green-hairline);
}

@media (min-width: 640px) {
  .footer-columns { grid-template-columns: repeat(3, 1fr); }
}

.footer-heading {
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--brass-soft);
  margin: 0 0 var(--space-4);
}

.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin-bottom: var(--space-3); }

.footer-col a { color: var(--on-green-soft); text-decoration: none; }
.footer-col a:hover { color: var(--on-green); text-decoration: underline; text-decoration-color: var(--brass); }

.footer-legal {
  padding-top: var(--space-5);
  color: var(--on-green-mute);
  font-size: 0.85rem;
}

.footer-legal p { max-width: none; }
.footer-disclaimer { margin-bottom: 0; }

/* Phone number in the footer: a visible trust signal, a touch brighter than
   the surrounding legal text. */
.footer-phone {
  font-size: 1rem;
  color: var(--on-green-soft);
  margin-bottom: var(--space-4);
}
.footer-phone strong { color: var(--on-green); }
.footer-phone a { color: var(--on-green); text-decoration-color: var(--brass); }

/* -------------------------------------------------------------------------
   7. Buttons
   ------------------------------------------------------------------------- */
.btn {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
  padding: 0.85rem 1.7rem;
  border-radius: var(--radius);
  border: 2px solid transparent;
  cursor: pointer;
  transition: background-color 180ms var(--ease-out), color 180ms var(--ease-out),
              border-color 180ms var(--ease-out), transform 180ms var(--ease-out);
}

.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--green);
  color: var(--on-green);
}

.btn-primary:hover { background: var(--green-deep); color: var(--on-green); }

.btn-secondary {
  background: transparent;
  color: var(--green);
  border-color: var(--btn-secondary-border);
}

.btn-secondary:hover { border-color: var(--green); background: var(--green-wash); color: var(--green-deep); }

.btn-brass {
  background: var(--brass-deep); /* white text needs >=4.5:1: brass-deep = 5.4:1 */
  color: var(--off-white);
}

.btn-brass:hover { background: color-mix(in oklab, var(--brass-deep), var(--ink) 12%); color: var(--off-white); }

.btn-sm { padding: 0.55rem 1.1rem; font-size: 0.92rem; }
.btn-lg { padding: 1.05rem 2.2rem; font-size: 1.08rem; }
.btn-block { display: block; width: 100%; }

.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

.btn-row { display: flex; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-5); }

/* -------------------------------------------------------------------------
   8. Forms
   ------------------------------------------------------------------------- */
.field { margin-bottom: var(--space-5); }

.field label {
  display: block;
  font-weight: 700;
  font-size: 1.1rem;
  margin-bottom: var(--space-2);
  color: var(--ink);
}

.field-hint {
  font-size: 0.9rem;
  color: var(--ink-mute);
  margin-top: var(--space-1);
  margin-bottom: 0;
}

/* Required-field asterisk and the inline validation message under a field. */
.req { color: var(--danger); font-weight: 700; margin-left: 0.1rem; }

.field-error {
  color: var(--danger);
  font-size: 0.9rem;
  font-weight: 600;
  margin: var(--space-2) 0 0;
}

/* An invalid field gets a danger-toned border so the eye lands on it. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--danger);
}

.join-required-note { margin-bottom: var(--space-5); }

input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
input[type="password"], input[type="search"], input[type="number"], input[type="date"],
select, textarea {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--ink-mute); /* >=3:1 boundary vs surface and paper (WCAG 1.4.11) */
  border-radius: var(--radius);
  padding: 0.75rem 0.95rem;
  transition: border-color 160ms var(--ease-out);
}

/* ONE select treatment for the whole site (Rick, 25 Jul 2026). There were
   three - the base rule's native arrow at 18px/400, the filter row at
   15.52px/600 grey with a chevron inset 14.4px, and the sort control at
   15.2px/600 with it inset 12.8px - which is exactly the inconsistency he
   spotted. Everything below now inherits font, weight and colour from the
   shared input rule above; only the chevron and the room made for it live
   here, so a component can never quietly re-style its dropdowns again.
   Component rules may still set width or height (the hero search field is
   deliberately taller); they must not set font-size, colour or the chevron. */
select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-right: 2.75rem;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 0.7rem auto;
}

/* The native option list is drawn by the browser and ignores CSS; Chromium's
   appearance: base-select opts into an in-page picker that does not, so the
   grey/white OS highlight becomes the brand green. Guarded, because Safari
   and Firefox have not shipped it - there the picker stays native, which is
   the same experience the site has always had, not a broken one. */
@supports (appearance: base-select) {
 /* Desktop pointers only. On a phone the native picker is a well-tuned
    bottom sheet and replacing it with an in-page list is a downgrade - and
    the whole point of opting in is the HOVER colour, which touch does not
    have. So phones keep the native control and lose nothing. */
 @media (hover: hover) and (pointer: fine) {
  select, ::picker(select) { appearance: base-select; }
  /* We draw our own chevron; suppress the one base-select adds. */
  select::picker-icon { display: none; }

  ::picker(select) {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-2);
    padding: var(--space-1);
  }

  /* Options are real DOM children, so they are styled directly - NOT as
     descendants of the ::picker() pseudo-element, which does not match. */
  select option {
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius);
    color: var(--ink);
    background: transparent;
  }

  /* Rick: the OS grey-with-white-text highlight should read as brand. */
  select option:hover,
  select option:focus {
    background: var(--green);
    color: var(--on-green);
  }

  /* The value currently held, shown quietly so it is not mistaken for hover. */
  select option:checked {
    background: var(--green-wash);
    color: var(--green-deep);
  }
  select option:checked:hover {
    background: var(--green);
    color: var(--on-green);
  }

  /* The tick base-select puts against the chosen row, toned to the brand. */
  select option::checkmark { color: var(--green); }
 }
}

input:hover, select:hover, textarea:hover { border-color: var(--ink-soft); }

input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--focus);
  outline-offset: 0;
  border-color: var(--focus);
}

textarea { min-height: 8.5rem; resize: vertical; }

/* File inputs: the native "Choose file" button gets a small accent-coloured
   button style, matched across the app (member dashboard, onboarding, preview,
   admin). Two rules (standard + webkit) because a browser drops a whole rule if
   it does not understand one selector in a group. */
input[type="file"] { font: inherit; color: var(--ink-soft); max-width: 100%; }
input[type="file"]::file-selector-button {
  font: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  padding: 0.45rem 0.95rem;
  margin-right: var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: var(--brass-deep); /* Rick 17 Jul: file buttons read as the ACCENT, not the same green as real buttons */
  color: var(--on-green);
  cursor: pointer;
  transition: background-color 160ms var(--ease-out);
}
input[type="file"]::file-selector-button:hover { background: var(--brass); }
input[type="file"]::-webkit-file-upload-button {
  font: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  padding: 0.45rem 0.95rem;
  margin-right: var(--space-3);
  border: 0;
  border-radius: var(--radius);
  background: var(--brass-deep);
  color: var(--on-green);
  cursor: pointer;
}

.checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.checkbox-row input[type="checkbox"] {
  width: 1.2rem;
  height: 1.2rem;
  margin-top: 0.2rem;
  flex: none;
  accent-color: var(--green);
}

.checkbox-row label { font-weight: 400; margin: 0; }

.form-error {
  background: var(--danger-wash);
  border: 1px solid var(--tone-danger-border);
  border-radius: var(--radius);
  color: var(--tone-danger-ink);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}

.form-success {
  background: var(--verified-wash);
  border: 1px solid var(--tone-success-border);
  border-radius: var(--radius);
  color: var(--tone-success-ink);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}

/* Honeypot: visually removed, still present for bots */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* -------------------------------------------------------------------------
   9. Chips (styled as inked stamps)
   ------------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.42rem 0.7rem;
  border-radius: var(--radius-stamp);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
  white-space: nowrap;
}

.chip-verified { background: var(--verified-wash); border-color: var(--tone-verified-border); color: var(--tone-verified-ink); }
.chip-revalidated { background: var(--green-wash); border-color: var(--tone-neutral-border); color: var(--green-deep); }
.chip-available { background: var(--green-wash); border-color: var(--tone-neutral-border); color: var(--green-deep); }
.chip-founding, .chip-featured { background: var(--brass-soft); border-color: var(--brass); color: var(--tone-warn-ink); }
.chip-lapsed { background: var(--paper-2); border-color: var(--line-strong); color: var(--ink-mute); }
.chip-removed { background: var(--danger-wash); border-color: var(--tone-danger-border); color: var(--danger); }

.chip svg { flex: none; }

/* -------------------------------------------------------------------------
   10. Ledger motifs: index lists, entry captions, dotted leaders
   ------------------------------------------------------------------------- */

/* Numbered index list (trust points, steps): 01-04 in serif over hairlines */
.index-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
  grid-template-columns: 1fr;
}

@media (min-width: 860px) {
  .index-list { grid-template-columns: repeat(2, 1fr); column-gap: var(--space-7); }
}

.index-list > li {
  display: flex;
  gap: var(--space-5);
  align-items: baseline;
  padding-block: var(--space-5);
  border-top: 1px solid var(--line);
  margin: 0;
}

.index-num {
  font-family: var(--font-serif);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--brass);
  flex: none;
  min-width: 2.4rem;
  font-variant-numeric: tabular-nums;
}

.index-list p { margin: 0; color: var(--ink-soft); font-size: 1.1rem; }
.index-list strong { display: block; color: var(--ink); font-size: 1.3rem; margin-bottom: 0.2rem; }

.section-green .index-list > li { border-top-color: var(--on-green-hairline-strong); }
.section-green .index-list p { color: var(--on-green-soft); }
.section-green .index-list strong { color: var(--on-green); }
.section-green .index-num { color: var(--brass-soft); }

/* Ledger caption bar under photographs */
.ledger-photo { position: relative; }

.ledger-photo img {
  width: 100%;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
}

.ledger-caption {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: var(--space-3);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.ledger-caption::before {
  content: '';
  display: block;
  width: 2rem;
  height: 1px;
  background: var(--brass);
}

/* Dotted leader rows (verification box, certificate) */
.leader-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: var(--space-3);
  font-size: 0.97rem;
}

.leader-row .leader-label { font-weight: 600; color: var(--ink-soft); flex: none; }

.leader-row .leader-dots {
  flex: 1;
  border-bottom: 2px dotted var(--line-strong);
  transform: translateY(-4px);
  min-width: 1.5rem;
}

.leader-row .leader-value { font-weight: 600; color: var(--ink); text-align: right; }

/* -------------------------------------------------------------------------
   11. Hero (asymmetric editorial split)
   ------------------------------------------------------------------------- */
.hero {
  background: var(--paper);
  overflow: hidden;
}

.hero-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  align-items: center;
  padding-block: var(--space-7);
}

@media (min-width: 960px) {
  .hero-grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-8);
    padding-block: var(--space-8);
  }
}

.hero h1 { margin-bottom: var(--space-4); max-width: 13em; }

/* Positioning line above the hero h1. Same voice as .welcome-eyebrow; its
   own rule because the hero sits on paper, not the welcome surface, and the
   welcome variant carries spacing this slot does not want. */
.hero-eyebrow {
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--green);
  max-width: none;
  margin-bottom: var(--space-3);
}

.hero-subhead {
  font-size: 1.3rem;
  font-family: var(--font-serif);
  color: var(--ink-soft);
  max-width: 44rem;
  margin-bottom: var(--space-6);
  line-height: 1.6;
}

.search-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-2);
  max-width: 38rem;
}

.search-box label {
  display: block;
  font-weight: 700;
  margin-bottom: var(--space-3);
}

.search-box-row {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.search-box-row input[type="search"],
.search-box-row input[type="text"] {
  flex: 1 1 14rem;
  font-size: 1.05rem;
}

.search-box-row .btn { flex: none; }

/* Search fields wear the sage keyline (requested: 3px solid #92afa4).
   On the finder it marks the two controls that define the SEARCH - where and
   how far - against the filters that refine it, now that both sit on one bar. */
.search-box-row input[type="search"],
.search-box-row input[type="text"],
.search-box-row input[type="email"],
.finder-field-loc input[type="search"],
.finder-field-radius select {
  border: 3px solid var(--search-keyline);
}

.search-microcopy {
  font-size: 0.9rem;
  color: var(--ink-mute);
  margin: var(--space-3) 0 0;
}

/* -------------------------------------------------------------------------
   12. Editorial image trio (no card chrome; hairline-ruled columns)
   ------------------------------------------------------------------------- */
.editorial-trio {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 860px) {
  .editorial-trio { grid-template-columns: repeat(3, 1fr); }
}

.editorial-item { border-top: 2px solid var(--green); padding-top: var(--space-4); }

.editorial-item img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-4);
}

.editorial-item h3 { margin-top: 0; font-size: 1.5rem; }
.editorial-item p { color: var(--ink-soft); font-size: 1.1rem; margin-bottom: 0; }

/* -------------------------------------------------------------------------
   13. Cards (kept for result entries and tier cards only)
   ------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-1);
}

.card h3 { margin-top: 0; }

.card-link-list { list-style: none; padding: 0; margin: 0; }
.card-link-list li { margin-bottom: var(--space-3); }

/* -------------------------------------------------------------------------
   14. Notices, disclaimers, verification box
   ------------------------------------------------------------------------- */
.notice {
  background: var(--green-wash);
  border: 1px solid var(--notice-border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: var(--space-5) 0;
  font-size: 1.125rem;
}

.disclaimer-box {
  background: var(--paper-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: var(--space-6) 0 var(--space-5);
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.verification-box {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-1);
}

.verification-box-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--line);
}

.verification-box-head h2, .verification-box-head h3 {
  margin: 0;
  font-size: 1.25rem;
  /* Match the 34px seal height so seal-headed and text-only box heads
     rule at the same baseline in a two-box row. */
  min-height: 2.125rem;
  display: flex;
  align-items: center;
}

.verification-box-head .seal { color: var(--green); }

.verification-box-footer {
  font-size: 0.85rem;
  color: var(--ink-mute);
  border-top: 1px solid var(--line);
  padding-top: var(--space-3);
  margin-bottom: 0;
}

/* -------------------------------------------------------------------------
   15. FAQ (details/summary)
   ------------------------------------------------------------------------- */
.faq-item { border-bottom: 1px solid var(--line); }

.faq-item summary {
  cursor: pointer;
  font-weight: 600;
  font-family: var(--font-serif);
  font-size: 1.3rem;
  padding: var(--space-4) var(--space-6) var(--space-4) 0;
  position: relative;
  list-style: none;
}

.faq-item summary:hover, .filter-sheet summary:hover { color: var(--green-deep); }

.faq-item summary::-webkit-details-marker { display: none; }

.faq-item summary::after {
  content: '+';
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-serif);
  font-size: 1.5rem;
  color: var(--brass);
}

.faq-item[open] summary::after { content: '\2212'; }

.faq-item .faq-answer { padding: 0 0 var(--space-4); color: var(--ink-soft); }

/* -------------------------------------------------------------------------
   16. Breadcrumbs
   ------------------------------------------------------------------------- */
.breadcrumbs {
  font-size: 0.9rem;
  color: var(--ink-mute);
  padding-block: var(--space-4);
}

.breadcrumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; }
.breadcrumbs li { margin: 0; display: flex; gap: var(--space-2); align-items: center; }
.breadcrumbs li + li::before { content: '·'; color: var(--brass); }
.breadcrumbs a { color: var(--ink-mute); text-decoration: none; }
.breadcrumbs a:hover { color: var(--green); text-decoration: underline; }

/* -------------------------------------------------------------------------
   17. CTA band
   ------------------------------------------------------------------------- */
.cta-band {
  background: var(--green-deep);
  color: var(--on-green-soft);
  border-radius: var(--radius-lg);
  padding: clamp(2rem, 5vw, 3.5rem);
  position: relative;
  overflow: hidden;
}

.cta-band::after {
  content: '';
  position: absolute;
  right: -6rem;
  top: -6rem;
  width: 22rem;
  height: 22rem;
  border-radius: 50%;
  border: 1px solid var(--cta-ring);
  pointer-events: none;
}

.cta-band::before {
  content: '';
  position: absolute;
  right: -3rem;
  top: -3rem;
  width: 16rem;
  height: 16rem;
  border-radius: 50%;
  border: 1px solid var(--cta-ring-soft);
  pointer-events: none;
}

.cta-band h2, .cta-band h3 { color: var(--on-green); margin-top: 0; }
.cta-band p { max-width: 44rem; line-height: 1.75; }

.cta-band .btn-primary { background: var(--brass-deep); color: var(--off-white); }
.cta-band .btn-primary:hover { background: color-mix(in oklab, var(--brass-deep), var(--ink) 12%); color: var(--off-white); }
.cta-band .btn-secondary { color: var(--on-green); border-color: var(--cta-outline); }
.cta-band .btn-secondary:hover { background: var(--cta-outline-wash); color: var(--on-green); border-color: var(--on-green); }

/* -------------------------------------------------------------------------
   18. Result entries (search, town pages) - ledger entry styling
   ------------------------------------------------------------------------- */
.result-card {
  display: flex;
  gap: var(--space-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--space-4);
  transition: box-shadow 200ms var(--ease-out), border-color 200ms var(--ease-out);
}

.result-card:hover { box-shadow: var(--shadow-2); border-color: var(--line-strong); }

.result-card.featured { border-color: var(--brass); }

.result-photo {
  flex: none;
  width: 8rem;
  height: 8rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--green-wash);
  display: grid;
  place-items: center;
  color: var(--green);
  font-family: var(--font-serif);
  font-size: 2.2rem;
}

.result-photo img { width: 100%; height: 100%; object-fit: cover; }

.result-main { flex: 1; min-width: 0; }

.result-name { font-size: 1.6rem; margin: 0 0 var(--space-1); }
.result-name a { text-decoration: none; color: var(--ink); }
.result-name a:hover { text-decoration: underline; text-decoration-color: var(--brass); }

.result-meta {
  font-size: 0.85rem;
  color: var(--ink-mute);
  margin-bottom: var(--space-3);
  font-variant-numeric: tabular-nums;
}

.result-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }

/* Provenance block (partials/provenance_chips.php): "Checked by us" over one
   row of stamps, "Told to us by the therapist" over another. Every chip inside
   keeps the plain .chip style deliberately - see the partial's header for why
   colour must not carry this distinction. The label is sentence case and quiet
   so it reads as a caption against the uppercase stamps it introduces. */
.provenance { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-3); }
.prov-row { display: flex; flex-direction: column; gap: 0.4rem; }
.prov-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-mute);
  line-height: 1.2;
}
.prov-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }

@media (max-width: 540px) {
  .result-card { flex-direction: column; }
}

/* -------------------------------------------------------------------------
   19. Map
   ------------------------------------------------------------------------- */
.map-frame {
  height: 26rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--paper-2);
  /* Leaflet's own sheet puts controls at z-index 1000 and its marker and
     popup panes at 600/700. Without a stacking context here those numbers
     escape into the root and beat anything the page pins over the map - this
     is the third time that has bitten this page. One line ends the argument
     permanently: everything Leaflet does is now sealed inside the frame. */
  isolation: isolate;
}

/* Results stack in one column: map banner on top, then the full-width list. */
.search-layout {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

.search-layout .map-sticky { order: -1; }
/* 22rem in a ~1100px-wide banner is a 3:1 letterbox, and fitBounds satisfies
   both axes - so the short side chose the zoom and the long side filled the
   slack with France. Every doubling of height buys a zoom level; 28rem is
   enough to move a typical 50-mile search from zoom 8 to 9 without the map
   dominating the page. */
.search-layout .map-frame { height: 22rem; }

/* Only wide viewports have the problem: a narrow phone map has no excess
   width to fill, so it keeps the shorter banner rather than eating half the
   screen. */
@media (min-width: 720px) {
  .search-layout .map-frame { height: 28rem; }
}

/* --- The FINDER's map: a column beside the results, not a banner over them
       (Rick, 26 Jul 2026) ---------------------------------------------------
   Measured at 1440x800, the banner's top edge landed at 798px with the fold
   at 800: a sliver of something large and colourful peeking at the bottom of
   the screen is the strongest scroll cue an interface has, and it is what
   sent the first patient who tested this page past the filters entirely.
   Beside the results the map cannot do that, and it also finishes the
   over-zoom fix - the 3.1:1 letterbox was why fitBounds' short axis chose the
   zoom and the spare width filled with 260 miles of coastline.
   SCOPED to the finder: .search-layout is shared with town and lander pages,
   which have no filter bar and keep their single-column banner. */
@media (min-width: 960px) {
  .search-layout.search-layout-finder {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    /* start, not the default stretch: a stretched grid item fills the row
       height, which leaves a sticky child with zero travel. Same pattern as
       .profile-layout. */
    align-items: start;
  }
  /* Second in DOM and second visually, so focus order matches what is seen. */
  .search-layout.search-layout-finder .map-sticky {
    order: 0;
    position: sticky;
    /* Parked BELOW the pinned filter bar, not at the top of the viewport.
       The bar is opaque and sticks at top:0, so a map parked at --space-4
       had its top strip buried - Leaflet's +/- zoom buttons included, which
       made them unclickable for the whole scroll. The bar's height is not a
       constant (the active-filter chips live in it and it re-wraps), so
       main.js measures it into --finder-bar-h; the fallback is the measured
       one-row height for the no-JS case, where the bar still sticks. */
    top: calc(var(--finder-bar-h, 8rem) + var(--space-4));
  }
  .search-layout.search-layout-finder .map-frame { height: min(34rem, calc(100vh - 8rem)); }
}

/* Below the column breakpoint the map goes AFTER the results rather than
   above them. On a 375px phone the banner alone pushed the first therapist
   past 1600px; the point of the page is the therapists. */
@media (max-width: 959.98px) {
  .search-layout.search-layout-finder .map-sticky { order: 1; }
}

/* -------------------------------------------------------------------------
   20. Pricing tiers
   ------------------------------------------------------------------------- */
.tier-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 720px) { .tier-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .tier-grid { grid-template-columns: repeat(4, 1fr); } }

.tier-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-1);
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
}

.tier-card.best-value { border: 2px solid var(--brass); }

.tier-flag {
  position: absolute;
  top: -0.85rem;
  left: var(--space-5);
  background: var(--brass-deep); /* white text needs >=4.5:1: brass-deep = 5.4:1 */
  color: var(--off-white);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.28rem 0.7rem;
  border-radius: var(--radius-stamp);
}

/* Self-sufficient so span.tier-name (/join) and h2.tier-name (/pricing)
   render identically; also lifts tier names into the 1.3rem heading step. */
.tier-name {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--ink);
  line-height: 1.14;
  margin: 0 0 var(--space-3);
}

.tier-price {
  font-family: var(--font-serif);
  font-size: 2.1rem;
  font-weight: 700;
  color: var(--green-deep);
  margin-bottom: var(--space-1);
  font-variant-numeric: tabular-nums;
}

.tier-price-note { font-size: 0.9rem; color: var(--ink-mute); margin-bottom: var(--space-4); }

/* Card scale is scoped to cards; verification boxes and profiles inherit
   body size so the tick lists read as one system with their neighbours. */
.tier-features { list-style: none; padding: 0; margin: 0 0 var(--space-5); }
.tier-card .tier-features { font-size: 0.95rem; }
.verification-box .tier-features li { margin-bottom: var(--space-3); }

.tier-features li {
  padding-left: 1.5rem;
  position: relative;
  margin-bottom: var(--space-2);
}

.tier-features li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.42rem;
  width: 0.85rem;
  height: 0.45rem;
  border-left: 2px solid var(--verified);
  border-bottom: 2px solid var(--verified);
  transform: rotate(-45deg);
}

.tier-card .btn { margin-top: auto; }

/* -------------------------------------------------------------------------
   21. Prose (long-form legal/guide content)
   ------------------------------------------------------------------------- */
.prose { max-width: var(--container-narrow); margin-inline: auto; }
.prose h2 { margin-top: var(--space-7); }
.prose h3 { margin-top: var(--space-6); }
.prose li { margin-bottom: var(--space-3); }
/* An opening heading gets its top gap from the section padding, not an extra
   margin: without this, a prose block that starts with an h2 has a bigger gap
   above the heading than below it. */
.prose > :first-child { margin-top: 0; }

.prose-meta {
  font-size: 0.9rem;
  color: var(--ink-mute);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-6);
}

/* -------------------------------------------------------------------------
   22. Page headers (interior pages)
   ------------------------------------------------------------------------- */
.page-header {
  padding-block: var(--space-7) var(--space-6);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.page-header h1 { margin-bottom: var(--space-3); }
.page-header .lead {
  font-size: 1.2rem;
  font-family: var(--font-serif);
  color: var(--ink-soft);
  max-width: 46rem;
  margin-bottom: 0;
}

/* Page titles (Rick, 16 Jul 2026): on desktop EVERY page-title block is
   centred (the homepage hero is its own component, not a .page-header, so it
   keeps its layout; admin pages keep their functional left alignment). On
   mobile all page titles read left-aligned - the base state below the
   breakpoint. */
@media (min-width: 640px) {
  body:not(.page-admin) .page-header { text-align: center; }
  body:not(.page-admin) .page-header .lead { margin-inline: auto; }
}

/* Compact variant, used by the finder once a search has run (Rick, 26 Jul
   2026). The full block is 218px of a 800px screen restating what the visitor
   already typed, and it pushed the map's top edge to within two pixels of the
   fold - which is what made people scroll straight past the filters. The h1
   and the /verification-standard link both stay; only their weight changes.
   A modifier on the element, not a body class: .page-header is used by 41
   templates and the body class does not vary with search state. */
.page-header-compact { padding-block: var(--space-5) var(--space-4); }
.page-header-compact h1 {
  font-size: clamp(1.55rem, 3.2vw, 2.15rem);
  margin-bottom: var(--space-2);
}
.page-header-compact .lead { font-size: 1.02rem; }

/* -------------------------------------------------------------------------
   23. Dashboard and admin (functional, same tokens)
   ------------------------------------------------------------------------- */
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}

.panel h2 { margin-top: 0; font-size: 1.45rem; } /* Rick 17 Jul: larger section titles, dashboard + admin */

.stat-row { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }

.stat {
  background: var(--green-wash);
  border-radius: var(--radius);
  padding: var(--space-4);
  text-align: center;
}

.stat-number {
  font-family: var(--font-serif);
  font-size: 1.9rem;
  font-weight: 700;
  color: var(--green-deep);
  display: block;
  font-variant-numeric: tabular-nums;
}

.stat-label { font-size: 0.85rem; color: var(--ink-soft); }

.table-scroll { overflow-x: auto; }

.status-pill {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-stamp);
  background: var(--paper-2);
  color: var(--ink-soft);
}

.status-pill.ok { background: var(--verified-wash); color: var(--tone-verified-ink); }
.status-pill.warn { background: var(--brass-soft); color: var(--tone-warn-ink); }
.status-pill.bad { background: var(--danger-wash); color: var(--danger); }

/* -------------------------------------------------------------------------
   24. Error pages
   ------------------------------------------------------------------------- */
.error-page { text-align: center; padding-block: var(--space-8); }

.error-code {
  font-family: var(--font-serif);
  font-size: 5rem;
  font-weight: 700;
  color: var(--brass);
  line-height: 1;
  margin-bottom: var(--space-4);
}

.error-page .search-box { margin-inline: auto; text-align: left; margin-top: var(--space-6); }
.error-page p { margin-inline: auto; }

.error-detail {
  text-align: left;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-4);
  font-size: 0.85rem;
}

/* -------------------------------------------------------------------------
   25. Reveal-on-scroll (progressive enhancement; JS adds .reveal-ready)
   ------------------------------------------------------------------------- */
.reveal { opacity: 1; transform: none; }

.js.reveal-ready .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out);
}

.js.reveal-ready .reveal.revealed { opacity: 1; transform: none; }

.js.reveal-ready .reveal:nth-child(2) { transition-delay: 70ms; }
.js.reveal-ready .reveal:nth-child(3) { transition-delay: 140ms; }
.js.reveal-ready .reveal:nth-child(4) { transition-delay: 210ms; }

@media (prefers-reduced-motion: reduce) {
  .js.reveal-ready .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  .btn, a, input, select, textarea, .result-card { transition: none !important; }
}

/* -------------------------------------------------------------------------
   26. Utilities
   ------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.text-muted { color: var(--ink-mute); }
.text-small { font-size: 1.1rem; }
.text-nowrap { white-space: nowrap; }

/* Wider column gap for two-column editorial sections */
@media (min-width: 640px) {
  .grid-gap-lg { gap: var(--space-8); }
}
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }

/* Secret-field state badge (admin settings): shows whether a password/API key
   is stored, without ever revealing it. */
.secret-badge {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 0.12em 0.6em;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.5;
  vertical-align: middle;
}
.secret-badge.is-set { background: var(--green-wash); color: var(--green); }
.secret-badge.is-unset { background: var(--line); color: var(--ink-mute); }

/* Editable long-text setting (e.g. the AI drafting instructions). */
.settings-textarea {
  width: 100%;
  min-height: 12rem;
  font-size: 0.9rem;
  line-height: 1.55;
  resize: vertical;
}
.mx-auto { margin-inline: auto; }

/* =========================================================================
   Page-specific sections are appended below by the relevant build package.
   Keep every addition token-driven: no new colours, no new fonts.
   ========================================================================= */

/* --- Homepage --- */
/* The hero search prompt reads as a small title above the field. */
.page-home .search-box label { font-size: 1.25rem; }

.trust-strip {
  background: var(--surface);
  border-block: 1px solid var(--line);
  padding-block: var(--space-5);
}

/* First row of the trust strip needs no hairline above it on desktop */
@media (min-width: 860px) {
  .trust-strip .index-list > li:nth-child(-n+2) { border-top: 0; }
}

/* Mobile (single column): only the very first row drops its hairline, so the
   strip's own top border is not doubled by a stray rule above "01". */
.trust-strip .index-list > li:first-child { border-top: 0; }

/* Featured members band: cards centre in the committed-green surface at any
   count (one card at launch must not strand two empty columns), and the
   entries carry the ledger scale used in search/town results. */
.featured-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .featured-grid {
    grid-template-columns: repeat(auto-fit, minmax(16rem, 24rem));
    justify-content: center;
  }
}

.featured-name { margin-top: 0; font-size: 1.3rem; }
.featured-name a { text-decoration: none; color: var(--ink); }
.featured-name a:hover { text-decoration: underline; text-decoration-color: var(--brass); }

.featured-meta {
  font-size: 0.85rem;
  color: var(--ink-mute);
  margin-bottom: var(--space-3);
  font-variant-numeric: tabular-nums;
}

.guide-link {
  display: block;
  font-family: var(--font-serif);
  font-size: 1.3rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--ink);
  padding: var(--space-4) var(--space-6) var(--space-4) 0;
  position: relative;
}

.guide-link::after {
  content: '\2192';
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  color: var(--brass);
  transition: transform 200ms var(--ease-out);
}

.guide-link:hover { color: var(--green); }
.guide-link:hover::after { transform: translate(4px, -50%); }

li.faq-item { list-style: none; margin: 0; }

/* --- Admin navigation --- */
.admin-nav {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-6);
}

.admin-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  list-style: none;
  margin: 0;
  padding: var(--space-3) 0;
}

.admin-nav li { margin: 0; }

.admin-nav a {
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding: var(--space-2) 0;
  border-bottom: 2px solid transparent;
}

.admin-nav a:hover, .admin-nav a[aria-current="page"] {
  color: var(--green-deep);
  border-bottom-color: var(--brass);
}

.admin-nav-logout { margin-left: auto; }

/* --- Guides hub and articles --- */
.guides-hub-list { max-width: 52rem; margin-block: var(--space-6); margin-inline: auto; }
.guides-hub-list + .disclaimer-box { max-width: 52rem; margin-inline: auto; }
.guide-link-desc { margin: -0.4rem 0 var(--space-4); max-width: 46rem; font-size: 1.1rem; }

.guide-article { padding-block: var(--space-4) var(--space-7); }

/* Guide titles follow the site-wide rule: centred on desktop, left on
   mobile; the article body stays editorial left at every width. */
@media (min-width: 640px) {
  .guide-article > h1 { text-align: center; }
}

.guide-intro {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  line-height: 1.65;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--space-5);
  margin-bottom: var(--space-5);
}

/* --- Package: static-pages (B5 /for-therapists, B6 /pricing,
       B7 /verification-standard, B9 /about, B16 /faq) ---
   Token-driven only: existing custom properties, no new colours or fonts. */

/* For-therapists hero: centred text block over a full-width ledger photo,
   on white (crisper than the warm-bone interior). */
.page-for-therapists .hero { background: var(--surface); }
.hero-stack { padding-block: var(--space-7); }

.hero-stack-text {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.hero-stack-text h1,
.hero-stack-text .hero-subhead,
.hero-stack-text p { margin-inline: auto; }

/* For-therapists hero: a wider measure than the home hero so the subhead
   holds fewer, more confident lines. */
.page-for-therapists .hero-stack-text { max-width: 53rem; }
.page-for-therapists .hero-subhead { max-width: 53rem; margin-bottom: var(--space-7); }

.hero-stack-text .btn-row { justify-content: center; }

/* Mobile: sales-hero text reads left like every other title block. */
@media (max-width: 639.98px) {
  .hero-stack-text { text-align: left; }
  .hero-stack-text .btn-row { justify-content: flex-start; }
  .hero-stack-text .hero-secondary-link { align-self: flex-start; }
}
.hero-stack-photo { margin-top: var(--space-6); }
.hero-stack-photo img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }

.hero-secondary-link {
  align-self: center;
  font-weight: 600;
}

.under-hero {
  font-size: 0.9rem;
  color: var(--ink-mute);
  margin: var(--space-4) 0 0;
}

#what-you-get { scroll-margin-top: var(--space-6); }

/* Comparison table: the register column reads as the committed entry */
.compare-table th:last-child,
.compare-table td:last-child { background: var(--green-wash); }
.compare-table td:last-child { color: var(--ink); font-weight: 500; }
.compare-table td:first-child { color: var(--ink-mute); }
.compare-table th:last-child { color: var(--green-deep); border-bottom-color: var(--green); }

.compare-note {
  font-family: var(--font-serif);
  font-style: italic;
  color: var(--ink-soft);
  max-width: 62ch;
  margin-top: var(--space-5);
  margin-bottom: 0;
}

/* Founding offer table */
.offer-table strong { color: var(--green-deep); }

/* The founding offer table explains each tier via a "?" tooltip in column 1
   instead of a heavy paragraph block. No scroll wrapper (short content wraps
   on mobile), so the bubbles are never clipped. */
.tier-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.offer-table .tip-icon {
  width: 1.35rem;
  height: 1.35rem;
  min-width: 1.35rem;
  min-height: 1.35rem;
  font-size: 0.75rem;
}

.offer-table .tip-bubble { text-transform: none; letter-spacing: normal; width: 18rem; }

@media (max-width: 560px) {
  .offer-table { font-size: 0.9rem; }
  .offer-table th, .offer-table td { padding: var(--space-2) var(--space-3); }
}

/* Verification standard page */
@media (min-width: 860px) {
  .index-list-stack { grid-template-columns: 1fr; }
}

.means-not-list { list-style: none; padding: 0; margin: 0; }

.means-not-list li {
  padding-left: 1.5rem;
  position: relative;
  margin-bottom: var(--space-3);
}

.means-not-list li::before {
  content: '';
  position: absolute;
  left: 0.1rem;
  top: 0.68rem;
  width: 0.75rem;
  height: 2px;
  background: var(--ink-mute);
}

.school-list { list-style: none; padding: 0; margin: var(--space-5) 0; max-width: 46rem; }

.school-list li {
  margin: 0;
  padding: var(--space-4) 0;
  border-top: 1px solid var(--line);
}

.school-list li:last-child { border-bottom: 1px solid var(--line); }

.school-list strong {
  font-family: var(--font-serif);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--ink);
}

.school-list .school-detail { color: var(--ink-soft); }

/* Pricing page */
.tier-note {
  font-size: 0.85rem;
  color: var(--ink-mute);
  margin: var(--space-3) 0 0;
}

.tier-card .tier-note { margin-top: var(--space-3); }

.pricing-foot {
  border-top: 2px solid var(--brass);
  padding-top: var(--space-5);
  max-width: 60rem;
  margin-inline: auto;
}

.pricing-foot ul { list-style: none; padding: 0; margin: 0; }

.pricing-foot li {
  font-size: 0.95rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-3);
  max-width: 75ch;
}

/* About page: founder sign-off styled as a ledger signature line */
.founder-sig {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-serif);
  font-size: 1.2rem;
  margin-top: var(--space-5);
}

.founder-sig::before {
  content: '';
  display: block;
  width: 2rem;
  height: 1px;
  background: var(--brass);
  flex: none;
}

/* -------------------------------------------------------------------------
   Package: legal-contact (contact page routes list + form panel).
   Legal pages reuse the existing .prose layout and need no new styles.
   Token-driven only: no new colours, no new fonts.
   ------------------------------------------------------------------------- */

.contact-grid { align-items: start; }

/* Ruled list of contact routes, in the ledger hairline idiom. */
.contact-routes {
  list-style: none;
  margin: 0;
  padding: 0;
}

.contact-routes li {
  margin: 0;
  padding-block: var(--space-5);
  border-top: 1px solid var(--line);
}

.contact-routes li:first-child {
  border-top: 0;
  padding-top: 0;
}

.contact-routes li:last-child {
  border-top: 1px solid var(--brass-soft);
}

.contact-routes p {
  margin: 0;
  color: var(--ink-soft);
}

.contact-routes p strong { color: var(--ink); }

/* The form panel mirrors the verification-box treatment. */
.contact-form-panel {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-1);
}

/* Both form panels (contact + profile enquiry) share one heading size and
   run the heading straight into the form, no internal rule. */
.contact-form-panel h2, .enquiry-section h2 {
  margin-top: 0;
  font-size: 1.5rem;
  margin-bottom: var(--space-5);
}

/* Inline field validation message. */
.field-error { color: var(--danger); }

/* =========================================================================
   Package: search-towns
   Find a Therapist search page (/find-a-therapist) and town pages
   (/mld-therapist/[town]). Merged into main.css by the orchestrator.
   Token-driven only: existing custom properties, no new colours, no fonts.
   ========================================================================= */

.finder-field label {
  display: block;
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: var(--space-2);
}

/* The location field is the ONLY growing item on the bar, and that is what
   keeps the row honest: whatever width is left over goes into it, so the bar
   always ends exactly where it should. Two rows could not do that - one of
   them always had slack, which became either an empty gap or an 848px box
   for an eight-character postcode. Its basis is small so it yields to the
   fixed controls first and only then takes the remainder - CRUCIALLY, flex
   line-breaking uses these basis sizes, so the basis total (not the grown
   widths) is what decides whether the row stays on one line. */
.finder-field-loc { flex: 1 1 6rem; min-width: 0; }
.finder-field-radius { flex: 0 0 auto; width: 8rem; }
.finder-filters-row > .btn { flex: 0 0 auto; }

/* Orientation line between the landing bar and the landing photo, centred on
   the same 60rem column so the three read as one composed block. Explicit
   max-width:none because the base p{max-width:70ch} pins a text-align:center
   paragraph left of centre (the recurring centred-paragraph gotcha). */
.finder-landing-hint {
  max-width: none;
  margin: var(--space-4) auto 0;
  text-align: center;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* --- Landing state photo: matches the landing bar's 60rem (Rick, 26 Jul) --- */
.finder-landing {
  max-width: 60rem;
  margin-block: var(--space-5) var(--space-7);
  margin-inline: auto;
}
.finder-landing .ledger-caption { display: flex; justify-content: center; max-width: none; }
.finder-landing .ledger-caption::after {
  content: '';
  display: block;
  width: 2rem;
  height: 1px;
  background: var(--brass);
}

/* --- Layout: filters live in the search panel; results own the full width --- */
.finder-layout {
  margin-bottom: var(--space-7);
}

/* --- The sticky filter bar ------------------------------------------------
   The bar has to keep up with the results, or a visitor who scrolls loses
   every control and has no way back short of scrolling to the top - which is
   exactly what happened to the first patient who tested the page.
   position: sticky only travels inside its own containing block, so the bar
   sits in .finder (which spans the controls AND the results) rather than
   inside the search form, which ends a few pixels below it. Its controls stay
   wired to the form with form="search-form".
   The z-index is not decorative: Leaflet's panes sit at 400+, and this file
   already records two shipped bugs from losing that stacking fight. */
.finder {
  position: relative;
}

.finder-bar {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  padding: var(--space-4) var(--space-5);
  margin-block: var(--space-5) var(--space-6);
}

/* Before a search has run the bar is the page's hero: 60rem = the 960px Rick
   specified (26 Jul), controls at the site's hero-search height rather than
   the compact toolbar height, and the landing photo matches its width so the
   two read as one composed block. */
.finder-bar-landing { max-width: 60rem; margin-inline: auto; --filter-control-h: 3.4rem; }

/* It sticks only while COLLAPSED. Open, it is 670px of panel, and pinning
   that to the top of the viewport would bury the results it exists to
   narrow; so it drops back into flow and main.js scrolls it into view, which
   also stops the button opening a panel the visitor cannot see.
   Gated on BOTH :has() and the js-finder class main.js sets, because each
   guard covers a way the bar could otherwise strand the panel: without
   :has() the panel is always open, so the bar would be permanently pinned at
   full height; without JS nothing scrolls the panel into view, so opening it
   while scrolled would render it off-screen above the visitor. In either
   case a bar that does not stick is the honest degradation. */
/* Not below 720px. There the seven controls wrap to about 400px of bar, and
   pinning half a phone screen costs more than it saves - the bar now starts
   at 469px on a 375px-wide phone, so it is on screen when you arrive without
   needing to be nailed there. A compact stuck state (condition + All filters
   only) would earn stickiness back on a phone; that needs stuck-detection
   and is its own piece of work. */
@media (min-width: 720px) {
  @supports selector(:has(*)) {
    .js-finder .finder:has(.finder-more:not([open])) .finder-bar {
      position: sticky;
      top: 0;
      z-index: 500;
    }
  }
}

/* --- Filter sheet: a details element, collapsed by default so it works
       everywhere without JS; main.js opens it on wide viewports --- */
.filter-sheet {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.filter-sheet summary {
  cursor: pointer;
  list-style: none;
  font-weight: 700;
  padding: var(--space-4) var(--space-5);
  position: relative;
}

.filter-sheet summary::-webkit-details-marker { display: none; }

.filter-sheet summary::after {
  content: '+';
  position: absolute;
  right: var(--space-5);
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-serif);
  font-size: 1.4rem;
  color: var(--brass);
}

.filter-sheet[open] summary::after { content: '\2212'; }
.filter-sheet[open] summary { border-bottom: 1px solid var(--line); }

.filter-body { padding: var(--space-5); }

.filter-group {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-5);
  min-width: 0;
}

/* A fieldset's legend is anchored to the top EDGE of the border box and
   ignores the fieldset's top padding, so inside a padded card it rendered
   sitting on the card's rim rather than within it. Floating takes it out of
   that special rendering model and into normal flow, where the 20px padding
   contains it like everything else. */
.filter-group legend {
  float: left;
  width: 100%;
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.3;
  padding: 0;
  margin-bottom: var(--space-3);
}

/* The float needs clearing, or the first sibling's box starts alongside it. */
.filter-group legend + * { clear: both; }

.filter-group .checkbox-row {
  margin-bottom: var(--space-3);
  align-items: center;
  gap: var(--space-2);
}

.filter-group .checkbox-row input[type="radio"] {
  width: 1.1rem;
  height: 1.1rem;
  flex: none;
  margin: 0;
  accent-color: var(--green);
}

.filter-group .checkbox-row input[type="checkbox"] { margin-top: 0; }
.filter-group .checkbox-row label { font-size: 0.95rem; }

.filter-reset { margin: var(--space-4) 0 0; }

/* --- Tooltips (filter toggles, Featured label): CSS-only bubble --- */
.tip {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.tip-icon {
  display: inline-grid;
  place-items: center;
  width: 1.5rem;   /* 24px min target (WCAG 2.5.8) */
  height: 1.5rem;
  min-width: 24px;
  min-height: 24px;
  border: 1px solid var(--ink-mute);
  border-radius: 50%;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 0.8rem;
  line-height: 1;
  color: var(--ink-mute);
  cursor: help;
}

.tip-bubble {
  position: absolute;
  z-index: 30;
  bottom: calc(100% + 0.55rem);
  left: 50%;
  transform: translateX(-50%);
  width: 15rem;
  max-width: 74vw;
  background: var(--green-deep);
  color: var(--on-green);
  font-family: var(--font-sans);
  font-size: 0.92rem;
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: normal;
  text-transform: none;
  white-space: normal;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms var(--ease-out);
  pointer-events: none;
}

.tip:hover .tip-bubble,
.tip:focus .tip-bubble,
.tip:focus-within .tip-bubble {
  opacity: 1;
  visibility: visible;
}

/* Escape-dismissed (WCAG 1.4.13); re-arms on pointer/focus leave via main.js */
.tip.tip-dismissed .tip-bubble { opacity: 0 !important; visibility: hidden !important; }

/* --- Results microcopy --- */
/* Count on the left, sort on the right: a sort is not a filter, so it belongs
   with the results it orders rather than in the filter panel. */
.results-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-5);
}

.results-count {
  font-family: var(--font-serif);
  font-size: 1.3rem;
  font-weight: 600;
  margin-bottom: 0;
  font-variant-numeric: tabular-nums;
}

.results-sort-control {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.results-sort-control label {
  font-weight: 700;
  font-size: 0.95rem;
  white-space: nowrap;
}

/* Width only - see the one select rule; height + centring match the finder
   bar controls exactly, so "Nearest first" is the same species of control
   as "Need help with?". */
.results-sort-control select {
  width: auto;
  height: var(--filter-control-h, 2.75rem);
  padding-block: 0;
  align-items: center;
  align-content: center;
  white-space: nowrap;
}

/* Wraps to its own line inside the head, so the head's gap owns the spacing. */
.results-sort { flex-basis: 100%; margin: 0; }

/* --- Result card extras (shared partial) --- */
/* View profile floats at the right, centred on the photo's band, without
   reserving a full-height column - so the chips tile the full card width. */
.result-card { position: relative; }

.result-cta {
  position: absolute;
  right: var(--space-6);
  top: calc(var(--space-6) + 4rem); /* padding + half the 8rem photo */
  transform: translateY(-50%);
}

/* Keep every line that shares the floating button's vertical band clear of it.
   The rating and the Google note belong here too: they sit in the same band and
   only ever escaped because they were short. Both lists must stay in step, or a
   line gets the clearance on desktop and keeps it once the button unfloats. */
.result-main .result-name,
.result-main .result-meta,
.result-main .result-rating,
.result-main .result-google-note { padding-right: 10.5rem; }

@media (max-width: 540px) {
  .result-cta { position: static; transform: none; margin-top: var(--space-3); }
  .result-cta .btn { display: block; width: 100%; }
  .result-main .result-name,
  .result-main .result-meta,
  .result-main .result-rating,
  .result-main .result-google-note { padding-right: 0; }
}

a.chip { text-decoration: none; }
a.chip:hover { border-color: var(--verified); }

/* "Matches your search: ..." - the one line that says why this member is in
   these results. Its own line rather than more chips, and quieter than the
   chip row above it: the dated verification chip is the strongest claim on
   the card and nothing added later may out-shout it. Full width, because it
   sits below the floating View profile button's band. */
.result-matches {
  margin: var(--space-2) 0 0;
  max-width: none;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.result-matches-label {
  font-weight: 600;
  color: var(--ink);
}

/* Shortlist tick. Ships hidden (the `hidden` attribute) and main.js reveals
   it, so a no-JS visitor never meets a control that would do nothing. Sits
   under the floating View profile button in the same column, which is why it
   needs no positioning of its own and follows that button's mobile collapse
   for free. */
.compare-tick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin-top: var(--space-2);
  font-size: 0.85rem;
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
}

/* A class selector beats the user agent's [hidden] { display: none }, so
   `display: flex` above silently defeated the attribute the markup and the
   gate both rely on: the tick rendered for a no-JS visitor and beside a
   two-result search, which is exactly what it must never do. Any component
   that sets display and ships hidden needs this line. */
.compare-tick[hidden] { display: none; }

.compare-tick input { cursor: pointer; }
.compare-tick.is-disabled { opacity: 0.45; cursor: default; }
.compare-tick.is-disabled input { cursor: default; }

/* The tray. Fixed to the bottom so it stays reachable while the visitor keeps
   scrolling results, and translated out of the way entirely when the
   shortlist is empty - a permanently parked bar over the last result row is
   just lost screen. */
.compare-tray {
  position: fixed;
  z-index: 500; /* above the Leaflet map, which sits at 400+ */
  left: 50%;
  bottom: var(--space-4);
  transform: translate(-50%, calc(100% + var(--space-6)));
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  transition: transform 0.2s var(--ease-out);
  max-width: calc(100vw - var(--space-4) * 2);
}

.compare-tray.is-open { transform: translate(-50%, 0); }

.compare-tray-count {
  margin: 0;
  max-width: none;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
}

.compare-tray-clear {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.85rem;
  color: var(--ink-mute);
  text-decoration: underline;
  cursor: pointer;
}

/* One selected is not a comparison, so the button reads as not-yet rather
   than broken (main.js also blocks the click). */
.compare-tray-go.is-disabled {
  opacity: 0.5;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .compare-tray { transition: none; }
}

.result-featured-flag { margin-bottom: var(--space-2); }

/* The Featured chip sits at the card's left edge; anchor its bubble left so
   the disclosure never clips off-screen on narrow phones. */
.result-featured-flag .tip-bubble { left: 0; transform: none; }

/* --- Notify-me block (reuses the cta-band component) --- */
.notify-block {
  margin-block: var(--space-6);
  margin-inline: auto;
  max-width: 52rem;
  scroll-margin-top: var(--space-5);
}

.notify-block .notify-form { max-width: 34rem; }
.notify-block .search-box-row { margin-top: var(--space-2); }
.notify-block .notify-consent { color: var(--on-green-soft); }
.notify-block .notify-consent a { color: var(--on-green); text-decoration-color: var(--brass); }
.notify-block .form-success { border-color: var(--brass); }

/* One shared control height for every finder control, INCLUDING the sort
   dropdown beside the result count - it sat at 55px against the bar's 44px
   and read as a different species (Rick, 26 Jul). On .finder so the landing
   variant can override it for the hero. */
.finder { --filter-control-h: 2.75rem; }

/* THE bar: where, how far, what for, the quick toggles, More filters, and
   Search always at the far right (Rick, 26 Jul). One shared control height is
   what makes seven controls read as one bar rather than a search box with
   filters bolted underneath - which is how the old two-row version read, and
   why it got skipped entirely. The 12px gap is deliberate: it is what keeps
   the row on ONE line at the container width even with the badge showing and
   "Lymphoedema management" selected - the two states that used to tile
   "All filters" onto a second row. */
.finder-filters-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}

/* Fixed-height controls need their block padding REMOVED, not fought. The
   base input rule carries 12px top and bottom; inside a 44px border-box that
   left a ~15px window for a 30px line, so the text rendered dropped and
   clipped (Rick's 26 Jul screenshot). With no block padding the fixed height
   centres a single line natively in inputs, and align-content centres the
   option text that base-select renders as real DOM. */
.finder-filters-row input[type="search"],
.finder-filters-row select,
.finder-filters-row > .btn {
  height: var(--filter-control-h);
  padding-block: 0;
}

.finder-filters-row > .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* base-select gotchas, MEASURED not assumed (26 Jul): the select renders as
   inline-FLEX, so vertical centring needs align-ITEMS - align-content alone
   leaves the value slot at the top, which is the "still not centred" bug
   Rick caught twice. And the selected option is real DOM, so in a
   width-capped select a long label WRAPS and paints below the border box.
   One line, centred, always. */
.finder-filters-row select {
  align-items: center;
  align-content: center;
  white-space: nowrap;
}

/* Sizes to its content (the label or the selected option, whichever is
   wider), because ellipsising the site's most important filter would be
   worse than letting the location field give up some slack. */
.finder-field-condition { flex: 0 0 auto; }
.finder-field-condition select { width: 100%; min-width: 11rem; }
.finder-field-condition label { white-space: nowrap; }

/* The bar's tooltips open DOWNWARD. Pinned to the top of the viewport there
   is nothing above the bar to open into. Scoped to the bar, because .tip is
   shared with result cards and both brands' pricing tables. */
.finder-bar .tip-bubble {
  bottom: auto;
  top: calc(100% + 0.55rem);
}

/* NOTE: the two surface toggles are NOT hidden on narrow viewports, however
   tempting the ~40px of sticky-bar height is. Their real <input> lives here
   and the panel copies are bare mirror labels, so a display:none here takes
   the only focusable control for Home visits and Taking new clients out of
   the tab order entirely - pointer-operable only, WCAG 2.1.1. The row already
   wraps, so on a phone they simply take their own line. */

/* On a phone every field takes its own full-width line - the standard calm
   mobile form - except the two toggles, which pair up. A first attempt kept
   desktop-ish widths and left the radius stranded alone at 128px, which is
   the exact stranded-control sin the design rules ban. */
@media (max-width: 559.98px) {
  .finder-field-loc,
  .finder-field-condition,
  .finder-more,
  .finder-filters-row > .btn { flex: 1 1 100%; }
  .finder-field-radius { flex: 1 1 100%; width: auto; }
  .finder-field-condition select { min-width: 0; }
  .finder-more > summary { width: 100%; justify-content: center; }
}

/* Labelled filter control: the label is visible now (an unlabelled dropdown
   reading "Any reason" tells you nothing about what it filters). */
.finder-filter-field label {
  display: block;
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: var(--space-2);
}

.finder-filters-row > .tip { height: var(--filter-control-h); }

/* More filters expands IN FLOW, on its own full-width line of the filter row.
   It was an overlay anchored to the button; that was wrong twice over. The
   map's Leaflet panes sit at z-index 400+, so an overlay under them can never
   win a stacking fight, and a panel anchored to a control halfway down the
   page runs off the bottom of the viewport as soon as it holds more than a
   few filters - which is the exact direction this list is meant to grow.
   In flow it costs a downward push of the map and results, and in exchange it
   can never underlap anything, never leaves the viewport, and behaves
   identically at every width with no JS at all. */
/* Sits at the right-hand end of the SAME row as the other controls. The panel
   it opens is a sibling of that row, not a child of this element, so the
   button can be inline while the panel spans the full width beneath - see the
   :has() rules below. */
/* NO margin-left:auto. An auto margin eats free space BEFORE flex-grow gets
   a look in, so pushing this button to the right edge would starve the
   location field of the slack it is there to absorb - and put the gap back
   between the last chip and the button, which is what it looked like before
   (535px of nothing at 1280). It sits where it falls, next to the filters it
   opens. */
.finder-more {
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* The button keeps its place at the right of the panel; only the body below
   it is full width, so opening the panel never moves the control you clicked. */
.finder-more > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  height: var(--filter-control-h);
  padding: 0 2.2rem 0 var(--space-4);
  border: 1px solid var(--filter-line);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 0.97rem;
  white-space: nowrap;
}

.finder-more[open] > summary { border-color: var(--green); }
.finder-more[open] > summary { border-bottom: 1px solid var(--green); }

.finder-more > summary::after { right: var(--space-4); }

.filter-count {
  display: inline-grid;
  place-items: center;
  min-width: 1.4rem;
  height: 1.4rem;
  padding-inline: 0.35rem;
  border-radius: var(--radius-stamp);
  background: var(--green);
  color: var(--on-green);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

/* The badge SLOT is always rendered and merely invisible at zero, so the
   button is the same width whether or not filters are applied. When it
   appeared from nowhere it widened the button, tipped the row past the
   container, and tiled "All filters" onto its own line (Rick, 26 Jul). */
.filter-count-empty { visibility: hidden; }

/* The panel: a sibling of the filter row, revealed by :has() when the details
   above is open. Progressive enhancement in the honest direction - a browser
   without :has() never hides it, so every filter stays reachable rather than
   being sealed behind a toggle that does nothing.
   ONE flat panel, no headed sub-sections (Rick, 26 Jul: with five controls
   plus the treatments band, "Your therapist" and "Appointments" were
   furniture): a row of tick filters, a row of dropdowns, the treatments
   band, the provenance line. */
.finder-bar > .filter-body {
  margin-top: var(--space-4);
  padding: var(--space-5) 0 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

@supports selector(:has(*)) {
  .finder-bar:has(.finder-more:not([open])) > .filter-body { display: none; }
}

/* --- Pre-launch notice dialog (layout.php + main.js) ---
   Native <dialog>: the browser centres it and paints ::backdrop; these rules
   only dress it in the .welcome-* single-message vocabulary. No transition,
   so prefers-reduced-motion needs no override. z-index is irrelevant to a
   modal dialog (top layer), so Leaflet's 400+ and the bar's 500 cannot sit
   over it. */
/* Browsers without <dialog> support have no UA rule hiding a closed dialog,
   so without this the element renders as a permanent inline box (and its
   method="dialog" button degrades to a query-stripping GET). Supporting
   browsers are unaffected: showModal() sets the open attribute. */
dialog:not([open]) { display: none; }

.notice-modal {
  max-width: min(34rem, calc(100vw - 2 * var(--space-5)));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2, var(--shadow-1));
  padding: clamp(1.5rem, 4vw, 2.5rem);
  text-align: center;
}

.notice-modal::backdrop { background: rgba(26, 34, 30, 0.55); }

.notice-modal h2 { margin: 0 0 var(--space-3); }

.notice-modal p {
  max-width: none;
  margin: 0 0 var(--space-5);
  font-size: 1.125rem;
  line-height: 1.6;
}

.notice-modal form { margin: 0; }

/* Surgery-type sub-facet: a full-width band of its own directly under the
   bar row, visible whenever its parent condition is chosen - never inside
   the More filters panel, because it continues the bar's primary question
   ("Need help with?"... which surgery?) and a collapsed panel would hide it
   from exactly the patient it was built for. Its own row also means it can
   never tile the one-line bar, the fault facet_short exists to prevent
   (13 Aug 2026). */
.finder-bar > .finder-subfacet {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

/* Tick filters sit side by side and wrap; a forced row's note breaks below
   its own control without disturbing its neighbours. */
.filter-checks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-7);
}

/* The three dropdowns share one line on desktop, each a readable width
   rather than a third of the page. */
.filter-selects {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .filter-selects { grid-template-columns: repeat(3, minmax(0, 18rem)); }
}

.filter-selects .finder-filter-field { margin: 0; }

.filter-body .filter-group { margin: 0; }

.filter-group-note {
  font-size: 0.9rem;
  color: var(--ink-mute);
  margin: 0 0 var(--space-3);
}

/* A group sub-heading that FOLLOWS a chip grid (the Training band's
   "Further training" after the schools row) needs air above it, or it sits
   on the rim of the row it does not belong to and the two groups read as
   one run of ticks. */
.filter-group .filter-check-grid + .filter-group-note {
  margin-top: var(--space-5);
}

/* One filter per row. SHORT LABEL FIRST, explanation only where it earns its
   place - that is the whole difference between this and the version Rick read
   as "a lot of information": a paragraph under every tick turned six controls
   into 851px. Safety-relevant notes stay visible; the rest sit behind the
   keyboard-reachable "?" icon. Never behind hover alone - .tip-bubble has
   pointer-events:none and no tap trigger, so a hover-only note does not exist
   on a phone. */
.filter-row { margin-bottom: var(--space-3); }
.filter-row:last-child { margin-bottom: 0; }

.filter-row-control {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.filter-row-note {
  display: block;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink-mute);
  margin-top: var(--space-1);
  padding-left: 1.7rem; /* clears the chip's tick box */
}

/* The provenance mark. It replaces two headed cards and two paragraphs: at
   the moment of choosing a filter the question is "what do I want?", not "who
   told you that?". Built from the verified tokens so whatcounsellor's
   theme.css re-skins it for free. */
.filter-checked-pill {
  display: inline-block;
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--tone-verified-border);
  border-radius: var(--radius-stamp);
  background: var(--verified-wash);
  color: var(--tone-verified-ink);
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

.filter-provenance {
  margin: 0;
  max-width: none;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

.filter-body .finder-filter-field select { width: 100%; }
.filter-body .finder-filter-field label { display: flex; align-items: center; gap: 0.5rem; }

/* One line under a select, for a control that needs a word of reassurance
   rather than a "?" bubble. The school filter is the only one that does: its
   options are five surnames a patient has no way to rank, and the honest
   answer (you almost certainly do not need to choose) has to be visible
   rather than hidden behind an icon, or it does not do its job. */
.filter-field-note {
  margin: var(--space-2) 0 0;
  max-width: none;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

/* The treatments band keeps its hairline so it reads as its own section of
   the panel - it is the one block Rick singled out as reading clearly, and
   its shape is unchanged. */
.finder-bar > .filter-body > .filter-group-wide {
  border-top: 1px solid var(--line);
  padding-top: var(--space-5);
}

/* Ticks in columns, not one tall stack: nine stacked checkboxes made the
   declared side four times the height of the verified side and pushed the
   price and gender controls off the bottom. Auto-fit means the count can
   grow without the layout being redesigned again. */
.filter-check-grid {
  display: grid;
  gap: var(--space-3) var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

/* The roomy variant: a wider column floor for lists carrying long names
   (the Training band's course entries), so a name stays on one line and
   the chips wrap as balanced rows instead of stranding one on its own. */
.filter-check-grid-roomy {
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

/* Wrapping labels stay hanging-indented past their tick box. */
.filter-check-grid .filter-chip {
  white-space: normal;
  align-items: flex-start;
}
.filter-check-grid .filter-chip::before { flex: none; margin-top: 0.1rem; }

/* Says out loud that the register narrowed the results itself. */
.results-notice {
  background: var(--verified-wash);
  border-left: 3px solid var(--verified);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
  font-size: 0.95rem;
  max-width: none;
}

/* A forced filter is shown ticked but not changeable; the tick still reads as
   applied rather than greyed into looking inactive. */
.filter-chip-input:disabled + .filter-chip { cursor: default; }
.filter-chip-input:disabled + .filter-chip::before {
  color: var(--surface);
  background: var(--verified);
  border-color: var(--verified);
}


/* --- Applied filters: one removable chip each, so nothing narrows the
       results invisibly --- */
.active-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
}

.active-filters a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem var(--space-3);
  border: 1px solid var(--filter-line);
  border-radius: var(--radius-stamp);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--filter-ink);
  background: var(--surface);
}

.active-filters a:hover {
  border-color: var(--green);
  color: var(--green-deep);
}

.active-filters a span[aria-hidden] { font-size: 1.05rem; line-height: 1; }

.active-filters-clear a {
  border: 0;
  padding-inline: 0;
  text-decoration: underline;
  background: none;
}

/* The condition dropdown matches the checkbox toggles: same grey, and a
   custom chevron padded in from the right edge */
/* Width only. Type, colour and the chevron come from the one select rule. */
.finder-filters-row select { width: auto; }

.finder-filters-row .filter-reset { margin: 0; }

/* Toggle chips: visible, instant, one tap. The input stays real for
   no-JS submits and accessibility; the label wears the pill. */
.filter-chip-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--filter-ink);
  white-space: nowrap;
  transition: color 160ms var(--ease-out);
  /* Enlarge the hit area to >=24px (WCAG 2.5.8) without shifting layout. */
  padding-block: 3px;
  margin-block: -3px;
}

.filter-chip::before {
  content: '\2713';
  display: grid;
  place-items: center;
  width: 1.15rem;
  height: 1.15rem;
  font-size: 0.75rem;
  line-height: 1;
  color: transparent;
  background: var(--surface);
  border: 2px solid var(--filter-line);
  border-radius: var(--radius-stamp);
  transition: background-color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}

.filter-chip:hover::before { border-color: var(--green); }

.filter-chip-input:checked + .filter-chip { color: var(--green-deep); }

.filter-chip-input:checked + .filter-chip::before {
  color: var(--surface);
  background: var(--green);
  border-color: var(--green);
}

.filter-chip-input:focus-visible + .filter-chip {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* --- Town pages --- */
.town-listing { margin-block: var(--space-6); }

.town-links { padding-block: var(--space-6) var(--space-4); max-width: 52rem; }

.town-nearby, .town-guides { max-width: none; }

.town-blocks p { color: var(--ink-soft); }

/* Pack-authored local editorial (brands/<key>/town_content/<slug>.php) */
.town-local .container { max-width: 52rem; }
.town-local p { color: var(--ink-soft); }
.town-local section + section { margin-block-start: var(--space-6); }

/* =========================================================================
   Package: profile-check
   Therapist profile pages, the enquiry flow and Check a Therapist.
   Token-driven additions only; merged into main.css by the orchestrator.
   ========================================================================= */

/* --- Profile masthead (header block, B3) --------------------------------- */
.profile-masthead {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding-block: var(--space-6);
}

.profile-header {
  display: flex;
  gap: var(--space-6);
  align-items: center;
  flex-wrap: wrap;
}

.profile-photo {
  flex: none;
  width: 12.5rem;
  height: 12.5rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--green-wash);
  display: grid;
  place-items: center;
  color: var(--green);
  font-family: var(--font-serif);
  font-size: 2.4rem;
  box-shadow: var(--shadow-1);
}

.profile-photo img { width: 100%; height: 100%; object-fit: cover; }

.profile-head-main { flex: 1; min-width: min(100%, 20rem); }

/* Action buttons sit to the right, centred against the profile photo */
.profile-head-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  align-self: center;
  min-width: 13rem;
}

@media (max-width: 719px) {
  .profile-head-actions { width: 100%; flex-direction: row; flex-wrap: wrap; }
  .profile-head-actions .btn { flex: 1 1 12rem; }
}

@media (min-width: 720px) {
  .profile-head-actions { margin-left: auto; flex: none; }
}

.profile-head-main h1 { margin-bottom: var(--space-2); font-size: clamp(2rem, 4vw, 2.9rem); }

.profile-subline {
  color: var(--ink-mute);
  font-size: 0.97rem;
  margin-bottom: var(--space-4);
  font-variant-numeric: tabular-nums;
}

.profile-header .btn-row { margin-top: var(--space-5); }

/* --- Profile layout: verification box first on mobile, right on desktop -- */
.profile-layout {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 960px) {
  .profile-layout { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-7); }
  .profile-layout .profile-main { order: 1; }
  .profile-layout .profile-aside { order: 2; position: sticky; top: var(--space-4); }
}

.profile-section { margin-bottom: var(--space-7); }
.profile-section:last-child { margin-bottom: 0; }
.profile-section h2 { margin-top: 0; }
/* Sub-headings inside About (help-with, treatments): clearly subordinate to
   the section title, clearly senior to body text. */
.profile-section h3 { font-size: 1.3rem; margin-top: var(--space-6); margin-bottom: var(--space-3); }

/* Hero rating line: stars link down to #reviews. */
.profile-rating { margin-bottom: var(--space-3); max-width: none; }
.profile-rating a { text-decoration: none; color: var(--ink); }
.profile-rating a:hover strong { text-decoration: underline; }

/* Member-declared facts folded into About when the standalone section went
   (qualified year, background) - quiet, one line. */
.profile-about-meta { color: var(--ink-mute); font-size: 0.95rem; }

/* The rail's quick card: what a decided visitor needs without re-reading the
   page - rating, price from, the action. Desktop only: on a phone the aside
   renders directly under the masthead, which already shows the stars and the
   same button, and the same thing twice in one viewport is clutter. */
.profile-quick {
  display: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
  text-align: center;
}

@media (min-width: 960px) {
  .profile-quick { display: block; }
  /* The quick card now owns the primary action on desktop - the masthead
     showing the same button two inches above it was the same duplication
     this page was just cleaned of. The masthead keeps the secondary actions
     (website, call); below 960px the card is hidden and the masthead button
     comes back. */
  .profile-head-actions .btn-primary { display: none; }
}

.profile-quick-fee { margin: 0 0 var(--space-4); max-width: none; color: var(--ink-soft); }
.profile-quick-cta { display: block; width: 100%; }
.profile-quick-phone { margin: var(--space-3) 0 0; max-width: none; font-size: 0.95rem; color: var(--ink-mute); }

/* Ruled fact lists (training, locations) - ledger rows, not bullets */
.profile-facts, .profile-locations { list-style: none; padding: 0; margin: 0; }

.profile-facts > li, .profile-locations > li {
  margin: 0;
  padding-block: var(--space-3);
  border-top: 1px solid var(--line);
}

.profile-facts > li:last-child, .profile-locations > li:last-child { border-bottom: 1px solid var(--line); }

.profile-locations { margin-bottom: var(--space-5); }

.map-frame.profile-map { height: 20rem; margin-bottom: var(--space-5); }

/* Reviews (collected through VerifiedPractitioner, synced nightly) */
.review-entry { border-top: 1px solid var(--line); padding-block: var(--space-4); }
.review-entry:last-of-type { border-bottom: 1px solid var(--line); }

.review-head { display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-2); }

.review-rating { color: var(--brass-deep); font-weight: 700; font-size: 0.85rem; }

/* Star glyphs (partial stars.php): brass fills over a hairline outline.
   Sized in ems so they scale with the line they sit in. */
.stars { display: inline-flex; align-items: center; gap: 0.1em; vertical-align: -0.12em; }
.stars svg { width: 1.05em; height: 1.05em; display: block; }
.stars-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Aggregate line at the top of the profile reviews section. */
.review-aggregate {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 1.15rem;
  margin-bottom: var(--space-4);
}
.review-aggregate .stars { font-size: 1.3rem; }

/* The member's public response under a review: ruled in, quieter voice. */
.review-reply {
  margin-top: var(--space-3);
  padding-left: var(--space-4);
  border-left: 2px solid var(--brass-soft);
  color: var(--ink-soft);
  font-size: 0.97rem;
}

/* Star rating line on result cards (data-gated: reviews present only). */
.result-rating {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
  font-size: 0.97rem;
}
.result-rating { flex-wrap: wrap; }
.result-rating .stars { font-size: 1.05rem; }
/* The Google signpost is review information, neither an operator check nor a
   member claim, so it sits under the rating rather than in the provenance rows
   - and on its OWN line, so it can never be read as the VP star figure. */
.result-google-note {
  color: var(--ink-mute);
  font-size: 0.9rem;
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
}

/* Two-source reviews (profile): the live Google card is framed from
   VerifiedPractitioner's origin (attribution and the Maps key stay there);
   main.js sizes the frame from its postMessage, and the CSS height is the
   JS-free fallback. Sources render as separate labelled blocks, never
   combined. */
.review-source + .review-source { margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--line); }
.review-source-head { font-size: 1.08rem; margin-bottom: var(--space-2); }
.google-place-frame {
  display: block;
  width: 100%;
  max-width: 30rem;
  height: 52px;
  border: 0;
  /* Hidden until the embedded VP page posts its height message (main.js).
     If the card cannot render - VP down, place disconnected, or the local
     dev fixture - the visitor sees the explainer and the "Read the reviews
     on Google" link instead of a dead box with VP's fallback link in it
     (Rick caught exactly that on the dev fixture, 26 Jul). Loading and
     sizing behaviour on live is unchanged: same lazy iframe, same height
     message, it just becomes visible when the card is real. */
  visibility: hidden;
  margin-bottom: var(--space-2);
}

/* Enquiry form panel */
.enquiry-section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-1);
  scroll-margin-top: var(--space-6);
}

/* Long review lists: five show, the rest sit behind a native expander so a
   member with a hundred reviews does not become a hundred-screen page. Inline
   rather than a link off to Google or VP: the visitor who is reading reviews
   is two scrolls from the enquiry form, and sending them to another tab is
   how a directory loses the enquiry. Google's own full list keeps its
   external link above. */
.reviews-more > summary {
  cursor: pointer;
  list-style: none;
  display: inline-block;
  margin-block: var(--space-4) 0;
  font-weight: 600;
  color: var(--green-deep);
  text-decoration: underline;
  text-decoration-color: var(--brass);
}
.reviews-more > summary::-webkit-details-marker { display: none; }
.reviews-more[open] > summary { display: none; }

/* Profile footer: report link + disclaimer line */
.profile-footer {
  margin-top: var(--space-7);
  border-top: 1px solid var(--line);
  padding-top: var(--space-5);
  font-size: 0.9rem;
  color: var(--ink-mute);
}

.profile-footer p { max-width: none; }

/* Enquiry confirmation screen */
.enquiry-success { padding-block: var(--space-7); }
.enquiry-success .enquiry-success-seal { color: var(--green); margin-bottom: var(--space-4); }

/* --- Check a Therapist (B8) ------------------------------------------- */
.page-check .container-narrow { max-width: 56rem; }
/* The single search input already carries the sage keyline; drop the panel
   chrome so /check is not a box drawn immediately inside another box. */
.page-check .search-box {
  max-width: none;
  background: transparent;
  border: 0;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}

.check-results { margin-top: var(--space-6); }

/* Check cards carry an avatar (left) like search results; inherit the
   flex row from .result-card. */
.check-card .result-main { max-width: none; }
.check-card .result-name, .check-card .result-meta { padding-right: 0; }
.check-card .result-name { margin-bottom: var(--space-2); }

/* Name block and "View full profile" on one row, the button centred on the
   name; leader rows sit below at full width. */
.check-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.check-head-name { min-width: 0; }
.check-head-name .result-meta { margin-bottom: 0; }
.check-head .btn { flex: none; }

.check-checklist { grid-template-columns: 1fr; }

.check-footer-line { margin-top: var(--space-7); }
.check-footer-line p { max-width: none; }

/* =========================================================================
   pkg-badge - /verify verification card page (badge click-through)
   Token-driven additions only; merged into main.css by the orchestrator.
   ========================================================================= */

/* The card sits in a narrow measure, like a certificate on the desk. */
.verify-wrap { max-width: 34rem; }

/* Name and status chip stacked beside the seal in the box head. */
.verify-head-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

/* =========================================================================
   Package: join-stripe (join flow + Stripe hand-off)
   Staged CSS for merge into public/assets/css/main.css by the orchestrator.
   Token-driven only: existing custom properties, no new colours or fonts.
   ========================================================================= */

/* Join flow progress indicator: Choose tier -> Your details -> Payment ->
   Documents (A2). One stepper for the whole journey; main.js advances it
   live between the two /join panels. Ruled steps with serif index numbers,
   echoing the ledger index motif. */
.join-progress {
  list-style: none;
  display: flex;
  gap: var(--space-4);
  padding: 0;
  margin: var(--space-5) auto var(--space-6);
  max-width: var(--container-narrow);
}

.join-progress li {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  padding-top: var(--space-3);
  border-top: 2px solid var(--line);
  color: var(--ink-mute);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.join-progress li.is-current { border-top-color: var(--brass); color: var(--ink); }
.join-progress li.is-done { border-top-color: var(--green); color: var(--green-deep); }

.join-progress-num { font-family: var(--font-serif); font-size: 1.05rem; font-weight: 600; }

/* Narrow screens: four steps will not fit on one row. "Documents" alone has a
   min-content width wider than a quarter of a 320px viewport, and a flex item
   defaults to min-width:auto, so it refused to shrink and pushed the whole
   page sideways - 55px at 320 and 15px at 360, on the paid signup funnel.
   Two by two instead. minmax(0,1fr) caps the track, and min-width:0 is needed
   on BOTH boxes: on the li because it is a grid item, and again on the label
   because the li is itself a flex container, so the span carries its own
   min-width:auto. Without the second one a longer label, or the fallback font
   shown during font-display:swap, could still push the row out. */
@media (max-width: 540px) {
  .join-progress {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3) var(--space-4);
  }
  .join-progress li { min-width: 0; }
  .join-progress-label { min-width: 0; overflow-wrap: anywhere; }
}

/* JS-gated controls (join flow Next/Back): visible only once main.js has
   stamped html.js, so the no-JS render never shows a dead button. */
html:not(.js) .js-only { display: none !important; }

/* Join panels: the two /join screens (Choose your tier / Your details).
   Both render stacked without JS; main.js hides one at a time and animates
   the entry. Hidden inputs still submit - [hidden] never disables fields. */
.join-panel[hidden] { display: none; }

.join-panel-actions {
  /* The submit button stays first in the DOM (so Enter submits the form);
     row-reverse renders it on the RIGHT with the back link on the left. */
  display: flex;
  flex-direction: row-reverse;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-5);
  margin-top: var(--space-6);
}

/* A button dressed as an inline link (e.g. "Back to tiers" on /join). */
.btn-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 1rem;
  color: var(--green);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2.5px;
  cursor: pointer;
}

.btn-link::before { content: "\2190\00a0"; }

.btn-link:hover { text-decoration-thickness: 2px; }

@media (prefers-reduced-motion: no-preference) {
  .join-panel-enter { animation: join-panel-in 0.28s ease both; }
  @keyframes join-panel-in {
    from { opacity: 0; transform: translateY(0.5rem); }
    to { opacity: 1; transform: none; }
  }
}

/* Stripe Embedded Checkout container: the card form renders here inside a
   Stripe-hosted iframe. Reserve height so the page does not jump while the
   iframe loads; Stripe's own UI paints over the paper background. */
.stripe-embed {
  margin: var(--space-6) 0;
  min-height: 30rem;
  border-radius: var(--radius);
}

.stripe-embed-loading { padding: var(--space-6) 0; text-align: center; }

/* The Payment Link fallback block starts hidden and is revealed by JS only
   when the embed fails. .btn-row's display:flex would defeat the [hidden]
   attribute (equal specificity, later in the cascade), so pin it. */
[data-stripe-embed-fallback][hidden] { display: none; }

/* Concierge editable preview (/dashboard/preview): the member's finished profile
   as an editable form; the approve / save actions sit at the foot of the form. */
.preview-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}
.preview-actions .btn { min-width: 12rem; }
.preview-actions-note {
  margin: var(--space-3) 0 0;
  font-size: 0.9rem;
  color: var(--ink-mute);
}

/* The join content sits under the page header; give it room to breathe so
   the stepper is not cramped against the header. */
.page-join main > .container { padding-top: var(--space-7); }

/* Post-payment confirmation (/welcome): a single centred column with one clear
   next-step CTA. Deliberately NOT the /join/pending status leader-table - at
   the payment moment a status table only competes with the action we want. */
.welcome-confirm {
  max-width: 60rem;
  text-align: center;
  padding-bottom: var(--space-8);
}
.welcome-hero {
  max-width: 44rem;
  margin-inline: auto;
}
.welcome-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--green-wash);
  color: var(--green);
  margin-bottom: var(--space-4);
}
.welcome-eyebrow {
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--green);
  max-width: none;
  margin-bottom: var(--space-3);
}
.welcome-hero h1 { margin-bottom: var(--space-4); }
.welcome-hero .lead {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  color: var(--ink-soft);
  max-width: 40rem;
  margin-inline: auto;
  margin-bottom: var(--space-6);
}
.welcome-cta { margin-bottom: var(--space-4); }
.welcome-cta .btn { min-width: 15rem; }
.welcome-note {
  font-size: 0.95rem;
  color: var(--ink-mute);
  max-width: 34rem;
  margin-inline: auto;
  margin-bottom: 0;
}
.welcome-rule {
  margin-block: var(--space-8);
  border-top-color: var(--line);
}
.welcome-steps-title {
  margin-top: 0;
  margin-bottom: var(--space-6);
}
.welcome-steps {
  list-style: none;
  padding: 0;
  margin: 0 auto var(--space-8);
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  text-align: left;
  max-width: 30rem;
}
@media (min-width: 760px) {
  .welcome-steps {
    grid-template-columns: repeat(3, 1fr);
    max-width: none;
    gap: var(--space-7);
  }
}
.welcome-steps > li { margin: 0; }
.welcome-step-num {
  display: block;
  font-family: var(--font-serif);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--brass);
  font-variant-numeric: tabular-nums;
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
}
.welcome-steps h3 { margin: 0 0 var(--space-2); font-size: 1.2rem; }
.welcome-steps p { margin: 0; color: var(--ink-soft); font-size: 1.05rem; }
.welcome-reassure {
  max-width: 44rem;
  margin-inline: auto;
  margin-bottom: var(--space-4);
  font-size: 0.95rem;
  color: var(--ink-mute);
}
.welcome-reassure:last-child { margin-bottom: 0; }

/* Concierge onboarding (/dashboard before a member is live): ONE focused,
   guided screen - the member's three things (answers, address, documents), or
   the waiting / approval state. Deliberately no section menu, no self-service
   panels, no competing CTAs. Engine-level (tokens only) so every concierge
   brand inherits it. */
.onboard-intro {
  font-size: 1.1rem;
  color: var(--ink-soft);
  margin: 0 auto var(--space-6);
  max-width: 44rem;
  text-align: center;
}
.onboard-intro p { margin: 0; }
.onboard-intro strong { color: var(--ink); }

.onboard-progress { margin-bottom: var(--space-6); text-align: center; }

.onboard-step-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.onboard-step-head h2 { margin: 0; }
.onboard-step-hint {
  margin: var(--space-1) 0 0;
  font-size: 0.95rem;
  color: var(--ink-mute);
}
.onboard-num {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--brass-soft);
  color: var(--brass-deep);
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
}
.onboard-step-status { margin-left: auto; flex: 0 0 auto; }
.onboard-step.is-done .onboard-num {
  background: var(--green-wash);
  color: var(--green);
}
.onboard-summary {
  margin: 0 0 var(--space-2);
  color: var(--ink-soft);
}
.onboard-form { margin-top: var(--space-2); }

/* The member's own photo step: current photo (or initials) beside the upload. */
.onboard-photo-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.onboard-photo-row .onboard-form { margin-top: 0; flex: 1 1 16rem; }
.onboard-photo-current {
  flex: 0 0 auto;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--brass-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.onboard-photo-current img { width: 100%; height: 100%; object-fit: cover; }
.onboard-photo-empty {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--brass-deep);
}
.onboard-num svg { display: block; }

.onboard-edit { margin-top: var(--space-2); }
.onboard-edit > summary {
  cursor: pointer;
  color: var(--green);
  font-size: 0.95rem;
  font-weight: 600;
}
.onboard-edit-body { margin-top: var(--space-4); }

.onboard-confirm {
  text-align: center;
  max-width: 40rem;
  margin: 0 auto var(--space-6);
}
.onboard-confirm p { margin: 0 auto; max-width: 38rem; }
/* max-width: none on these centred <p>s: without it they inherit the base
   p{max-width:70ch}, which pins the box left so text-align:center lands the
   content left of the true page centre. */
.onboard-cta { text-align: center; margin-bottom: var(--space-6); max-width: none; }
.onboard-cta .btn { min-width: 15rem; }

.onboard-received {
  margin: var(--space-6) auto;
  max-width: 22rem;
  width: fit-content;
  text-align: left;
}

.onboard-change {
  border-top: 1px solid var(--line);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  text-align: center;
}
.onboard-change > summary {
  cursor: pointer;
  color: var(--green);
  font-weight: 600;
}
.onboard-change-body { margin-top: var(--space-5); text-align: left; }
.onboard-change h2 { font-size: 1.05rem; margin-bottom: var(--space-3); }

.onboard-reassure {
  font-size: 0.9rem;
  color: var(--ink-mute);
  margin: var(--space-6) auto 0;
  max-width: 40rem;
  text-align: center;
}
.onboard-signout {
  margin-top: var(--space-6);
  max-width: none;
  text-align: center;
  font-size: 0.9rem;
}
.onboard-signout a { color: var(--ink-mute); }

.join-fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-7);
  min-width: 0;
}

/* /join tier chooser: two boxes - Registered (with its billing options) and
   Featured - replacing the old four-card row. The four Stripe tier keys are
   unchanged; the billing radios inside a box submit the right one. */
.join-two-boxes {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}

@media (min-width: 800px) {
  .join-two-boxes { grid-template-columns: 1fr 1fr; }
}

.tier-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  padding: clamp(var(--space-5), 4vw, var(--space-6));
  transition: border-color 180ms var(--ease-out), box-shadow 180ms var(--ease-out);
}

.tier-box:has(input[type="radio"]:checked) {
  border-color: var(--green);
  box-shadow: 0 0 0 1px var(--green), var(--shadow-2);
}

.tier-box-head { margin-bottom: var(--space-4); }
.tier-box-name { font-size: 1.4rem; margin: 0 0 var(--space-1); }
.tier-box-price {
  font-family: var(--font-serif);
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--green-deep);
  margin: 0 0 var(--space-2);
}
.tier-box-sub { color: var(--ink-soft); margin: 0; }
.tier-plus-lead { font-weight: 600; margin: 0 0 var(--space-3); }
.tier-box .tier-card-note { margin-top: var(--space-4); }

.tier-billing-label {
  font-weight: 700;
  font-size: 0.95rem;
  margin: var(--space-5) 0 var(--space-3);
}

.tier-billing-group { display: flex; flex-direction: column; gap: var(--space-3); }

.tier-billing {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  cursor: pointer;
  transition: border-color 140ms var(--ease-out), background 140ms var(--ease-out);
}

.tier-billing:hover { border-color: var(--line-strong); }
.tier-billing:has(input:checked) { border-color: var(--green); background: var(--green-wash); }
.tier-billing input { margin-top: 0.25rem; flex-shrink: 0; }
.tier-billing-text { display: flex; flex-direction: column; gap: 0.15rem; }
.tier-billing-price { font-weight: 700; font-size: 1.02rem; color: var(--ink); }
.tier-billing-note { font-size: 1rem; color: var(--ink-mute); line-height: 1.45; }

/* Small best-value marker for a billing option (used on /pricing). */
.tier-billing-flag {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tone-warn-ink);
  background: var(--brass-soft);
  border-radius: var(--radius-stamp);
  padding: 0.1rem 0.4rem;
  margin-left: 0.35rem;
  vertical-align: 0.08em;
}

/* On /pricing the billing rows are informational, not selectable: drop the
   pointer cursor and hover affordance so they do not read as clickable. */
.pricing-tiers .tier-billing { cursor: default; }
.pricing-tiers .tier-billing:hover { border-color: var(--line); }

/* The standard-comparison line sits tight under the tier cards */
.join-fieldset > .text-small { margin: var(--space-5) 0 0; }

.join-fieldset legend { padding: 0; }

.tier-pick {
  display: flex;
  flex-direction: column;
  cursor: pointer;
  font-weight: 400;
  transition: border-color 180ms var(--ease-out), box-shadow 180ms var(--ease-out);
}

.tier-pick .tier-radio-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.tier-pick input[type="radio"] {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  accent-color: var(--green);
}

.tier-pick .tier-name { margin: 0; }
.tier-pick .tier-price { display: block; }

.tier-price-strap {
  display: block;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--green-deep);
  margin-bottom: var(--space-1);
}

.tier-pick .tier-price-note { display: block; }

.tier-card-note {
  display: block;
  font-size: 0.85rem;
  color: var(--ink-mute);
  border-top: 1px solid var(--line);
  padding-top: var(--space-3);
  margin-top: auto;
}

.tier-pick:hover { border-color: var(--line-strong); box-shadow: var(--shadow-2); }
.tier-pick:has(input[type="radio"]:checked) { border-color: var(--green); box-shadow: var(--shadow-2); }
.tier-pick:has(input[type="radio"]:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }

/* Application form fields */
.join-fields { max-width: var(--container-narrow); margin-inline: auto; margin-bottom: var(--space-8); }

.field-grid {
  display: grid;
  gap: 0 var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .field-grid-2 { grid-template-columns: repeat(2, 1fr); }
  /* Label-grow fallback: inputs line up when one LABEL wraps. */
  .field-grid-2 > .field { display: flex; flex-direction: column; }
  .field-grid-2 > .field > label { flex-grow: 1; }
  /* Subgrid (all modern browsers): label, control and hint each share a row
     across the pair, so the inputs sit level whatever wraps - a two-line
     label OR a hint present on only one side. */
  @supports (grid-template-rows: subgrid) {
    .field-grid-2 { grid-template-rows: repeat(4, auto); }
    .field-grid-2 > .field { display: grid; grid-template-rows: subgrid; grid-row: span 4; align-content: start; }
    .field-grid-2 > .field > label { align-self: end; }
  }
}

/* Optional additional practice locations */
.join-extra-locations { margin-bottom: var(--space-5); }

.join-extra-locations summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--green);
  padding-block: var(--space-2);
}

.join-extra-locations summary:hover { color: var(--green-deep); }

/* Ruled ledger idiom, matching the dashboard's additional-locations block,
   rather than boxes-within-the-form. */
.location-row {
  border-top: 1px solid var(--line);
  padding: var(--space-4) 0 0;
  margin: var(--space-4) 0 0;
}

.location-row-title {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: var(--space-3);
}

/* =========================================================================
   pkg-dashboard - member auth pages (/login, /forgot-password,
   /reset-password), the member dashboard (/dashboard) and the printable
   membership certificate (/dashboard/certificate).
   Token-driven additions only; merged into main.css by the orchestrator.
   ========================================================================= */

/* --- Auth pages: a single calm panel, like a form on good paper --------- */
.auth-wrap { max-width: 26rem; margin-inline: auto; }

.auth-panel { padding: var(--space-6); }

.auth-seal {
  display: flex;
  justify-content: center;
  color: var(--green);
  margin-bottom: var(--space-5);
}

.auth-links { margin: var(--space-5) 0 0; font-size: 0.95rem; }

.auth-aside { text-align: center; }

/* --- Dashboard layout: sticky section nav beside the panels ------------- */
/* Member dashboard (16 Jul 2026): one narrow column, Overview open at the
   top, every other section an admin-section accordion. Anchor targets land
   clear of the viewport edge. */
.dash-section .panel,
.dash-section .admin-section { scroll-margin-top: var(--space-6); }

/* Dashboard header (Rick, 17 Jul 2026 v2 polish): title + welcome on the
   LEFT, "View your public profile" on the RIGHT (opens a new tab); wraps
   to stacked-left on small screens. Overrides the global centred rule. */
body .page-header.dash-header { text-align: left; }
body .page-header.dash-header .lead { margin-inline: 0; }
.dash-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4) var(--space-6);
  flex-wrap: wrap;
}
.dash-header-title h1 { margin-bottom: var(--space-2); }
.dash-header-action { max-width: none; margin: 0; }

/* ---- Dashboard v2 (Rick, 17 Jul 2026): top menu + sub-tabs + 75/25 grid.
   The menu band mirrors the admin-nav idiom; the sub-tabs are quiet pills;
   the right column holds the quick-action cards. */
.dash-menu { background: var(--surface); border-bottom: 1px solid var(--line); }
.dash-menu ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  list-style: none;
  margin: 0;
  padding: var(--space-3) 0;
}
.dash-menu li { margin: 0; }
.dash-menu a {
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding: var(--space-2) 0;
  border-bottom: 2px solid transparent;
}
.dash-menu a:hover, .dash-menu a.is-active { color: var(--green-deep); border-bottom-color: var(--brass); }
.dash-menu li.dash-menu-out { margin-left: auto; } /* li-qualified so it outweighs .dash-menu li */
.dash-menu-out a { color: var(--ink-mute); display: inline-flex; align-items: center; gap: 0.45rem; }

.dash-subtabs { background: var(--paper-2); border-bottom: 1px solid var(--line); }
.dash-subtabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  list-style: none;
  margin: 0;
  padding: var(--space-2) 0;
}
.dash-subtabs li { margin: 0; }
.dash-subtabs a {
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
}
.dash-subtabs a:hover { color: var(--green-deep); }
.dash-subtabs a[aria-current="page"] { background: var(--green-wash); color: var(--green-deep); }

.dash-grid { display: grid; gap: var(--space-6); align-items: start; }
@media (min-width: 960px) {
  .dash-grid { grid-template-columns: 3fr 1fr; }
  .dash-grid-single { grid-template-columns: 1fr; }
}
.dash-main { min-width: 0; }
.dash-side .panel { padding: var(--space-4); }
.dash-side h2 { margin-bottom: var(--space-3); }
.dash-side .checklist { font-size: 0.92rem; }
.dash-quick-links { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }

/* Sidebar availability buttons breathe (Rick 17 Jul). */
.dash-availability-form { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* Referral link/message each carry their own Copy button (Rick 17 Jul). */
.dash-copy-row { display: flex; gap: var(--space-2); align-items: flex-start; }
.dash-copy-row textarea { flex: 1; min-width: 0; }
.dash-copy-btn { flex: none; display: inline-flex; align-items: center; gap: 0.4rem; }
.dash-quick-links a { font-weight: 600; }
.dash-copy-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--green);
  text-decoration: underline;
  text-decoration-color: var(--link-underline);
  cursor: pointer;
}
.dash-copy-link:hover { color: var(--green-deep); }

/* For-therapists "proof" section: the live badge and the specimen
   certificate side by side (Rick, 17 Jul 2026). */
.proof-grid { display: grid; gap: var(--space-6); align-items: stretch; }
@media (min-width: 860px) { .proof-grid { grid-template-columns: 1fr 1fr; } }
.proof-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.proof-card h3 { margin: var(--space-5) 0 var(--space-3); }
.proof-visual { display: flex; justify-content: center; }
.proof-visual img {
  display: block;
  width: 100%;
  max-width: 340px;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.proof-visual-badge {
  align-items: center;
  background: var(--green-deep);
  border-radius: var(--radius);
  padding: var(--space-8) var(--space-5);
}
.proof-visual-badge svg { width: min(300px, 100%); height: auto; }

/* The Overview's calm status line: green = all fine, brass = a date is
   coming up, grey = received/awaiting us. */
.dash-status {
  border: 1px solid var(--line);
  border-left: 5px solid var(--green);
  background: var(--green-wash);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}
.dash-status p { max-width: none; }
.dash-status-warn { border-left-color: var(--brass-deep); background: var(--brass-soft); }
.dash-status-info { border-left-color: var(--ink-mute); background: var(--paper-2); }

.dash-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  margin-bottom: var(--space-4);
}

/* Two form fields side by side where there is room. */
.dash-field-pair { display: grid; gap: 0 var(--space-4); }

@media (min-width: 720px) {
  .dash-field-pair { grid-template-columns: 1fr 1fr; }
  /* Label-grow fallback: inputs line up when one LABEL wraps (the pair cells
     are equal height, so growing the shorter label pushes its input down). */
  .dash-field-pair > .field { display: flex; flex-direction: column; }
  .dash-field-pair > .field > label { flex-grow: 1; }
  /* Subgrid (all modern browsers): label, control and hint each share a row
     across the pair, so the inputs sit level whatever wraps - a two-line
     label OR a hint present on only one side (the label-grow fallback alone
     pushed the hint-less field's input down by the hint height, which is
     exactly the "misaligned password fields" Rick saw on the New password /
     New password again pair). */
  @supports (grid-template-rows: subgrid) {
    .dash-field-pair { grid-template-rows: repeat(4, auto); }
    .dash-field-pair > .field { display: grid; grid-template-rows: subgrid; grid-row: span 4; align-content: start; }
    .dash-field-pair > .field > label { align-self: end; }
  }
}

/* Grouped checkboxes read as one ruled ledger block. */
.dash-fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-5);
}

.dash-fieldset legend {
  font-weight: 700;
  font-size: 0.95rem;
  padding-inline: var(--space-2);
}

.dash-fieldset .checkbox-row:last-of-type { margin-bottom: var(--space-2); }

/* --- Onboarding checklist and completion meter (A2 step 8) -------------- */
.meter {
  height: 0.6rem;
  border-radius: 999px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  overflow: hidden;
}

.meter-fill {
  height: 100%;
  background: var(--green);
  border-radius: 999px;
  transition: width 300ms var(--ease-out);
}

.meter-done-0 { width: 0; }
.meter-done-1 { width: 16.7%; }
.meter-done-2 { width: 33.3%; }
.meter-done-3 { width: 50%; }
.meter-done-4 { width: 66.7%; }
.meter-done-5 { width: 83.3%; }
.meter-done-6 { width: 100%; }

.meter-count { margin-top: var(--space-2); }

.checklist { list-style: none; margin: var(--space-4) 0 0; padding: 0; counter-reset: checklist; }

.checklist li {
  counter-increment: checklist;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

.checklist li::before {
  content: counter(checklist, decimal-leading-zero);
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--brass);
  flex: none;
  min-width: 1.6rem;
}

.checklist .checklist-done { color: var(--ink-mute); }
.checklist .checklist-done span { text-decoration: line-through; text-decoration-color: var(--line-strong); }
.checklist .checklist-done::after {
  content: '\2713';
  margin-left: auto;
  color: var(--verified);
  font-weight: 700;
}

/* --- Photo section ------------------------------------------------------ */
.dash-photo-row { display: flex; gap: var(--space-5); flex-wrap: wrap; align-items: flex-start; }

.dash-photo-current img,
.dash-photo-empty {
  width: 10rem;
  height: 10rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  object-fit: cover;
}

.dash-photo-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--green-wash);
  color: var(--green);
  font-family: var(--font-serif);
  font-size: 2.4rem;
  font-weight: 600;
}

.dash-photo-row form { flex: 1; min-width: 16rem; }

/* --- Locations manager --------------------------------------------------- */
.location-entry {
  border-top: 1px solid var(--line);
  padding: var(--space-5) 0 var(--space-4);
  position: relative;
}

.location-grid { display: grid; gap: 0 var(--space-4); }

@media (min-width: 720px) {
  .location-grid { grid-template-columns: 1fr 1fr; }
}

.location-remove { margin-top: var(--space-3); }

.btn-danger-ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--danger);
}

.btn-danger-ghost:hover { border-color: var(--danger); background: var(--danger-wash); color: var(--danger); }

.location-add { border-top: 1px solid var(--line); padding-top: var(--space-4); }

.location-add summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--green);
  margin-bottom: var(--space-4);
}

/* --- Badge embed --------------------------------------------------------- */
.dash-badge-preview {
  display: inline-block;
  padding: var(--space-4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* Badge size variations: each row shows the badge rendered at its real size
   on a preview panel, beside its dimensions and embed code. */
.badge-size {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
  padding: var(--space-5) 0;
  border-top: 1px solid var(--line);
}

.badge-size:first-of-type { border-top: 0; padding-top: var(--space-2); }

.badge-size-preview {
  flex: none;
  display: grid;
  place-items: center;
  min-width: 17rem;
  min-height: 6.5rem;
  padding: var(--space-4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.badge-size-detail { flex: 1; min-width: 16rem; }

.badge-size-label {
  display: block;
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: var(--space-2);
  font-variant-numeric: tabular-nums;
}

.badge-embed-code {
  font-size: 0.85rem;
  min-height: 4.5rem;
  color: var(--ink-soft);
  background: var(--paper-2);
}

/* --- Embed widget preview page (/embed/preview/*) ------------------------ */
/* The site CSP has no 'unsafe-inline' for styles, so the iframe is sized
   here rather than with a style attribute (which browsers would ignore). */
.embed-preview-frame { display: block; width: 100%; height: 520px; border: 0; }

/* The copyable snippet shows in full, soft-wrapped: copying still yields
   the single unbroken line. */
.embed-snippet {
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  font-size: 0.85rem;
  color: var(--ink-soft);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- Membership certificate ---------------------------------------------- */
.cert-actions { margin-bottom: var(--space-5); }

.certificate {
  max-width: 46rem;
  margin-inline: auto;
  background: var(--surface);
  border: 2px solid var(--green);
  border-radius: var(--radius);
  padding: var(--space-3);
}

.certificate-inner {
  border: 1px solid var(--brass);
  padding: clamp(var(--space-5), 6vw, var(--space-7));
  text-align: center;
}

.certificate-seal { display: flex; justify-content: center; color: var(--green); margin-bottom: var(--space-4); }

/* The short centred lines need max-width cleared, otherwise the base
   p{max-width:70ch} left-aligns their box inside the centred certificate. */
.certificate-register {
  font-family: var(--font-serif);
  font-size: 1.35rem;
  letter-spacing: 0.02em;
  color: var(--green-deep);
  margin-bottom: var(--space-2);
  max-width: none;
}

.certificate-kicker {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brass-deep);
  margin-bottom: var(--space-5);
  max-width: none;
}

.certificate-name {
  font-size: clamp(2rem, 5vw, 2.8rem);
  margin: 0 auto var(--space-3);
  max-width: none;
}

.certificate-line { color: var(--ink-soft); margin-inline: auto; }

.certificate-details {
  max-width: 26rem;
  margin: var(--space-6) auto;
  text-align: left;
}

.certificate-footer-note {
  font-size: 0.85rem;
  color: var(--ink-mute);
  max-width: 36rem;
  margin: var(--space-6) auto var(--space-4);
}

.certificate-entity {
  font-family: var(--font-serif);
  font-size: 0.95rem;
  color: var(--green-deep);
  margin-bottom: 0;
  max-width: none;
}

/* Print: hide the site chrome, let the certificate own the page (A4). */
@media print {
  body.page-certificate .site-header,
  body.page-certificate .site-footer,
  body.page-certificate .skip-link,
  body.page-certificate .dash-menu,
  body.page-certificate .dash-subtabs,
  body.page-certificate .dash-noprint { display: none !important; }

  body.page-certificate { background: var(--surface); }

  body.page-certificate .section { padding-block: 0; }

  body.page-certificate .certificate {
    max-width: none;
    border-width: 2px;
    box-shadow: none;
    page-break-inside: avoid;
  }
}

/* =========================================================================
   pkg-admin-core - admin sign-in, TOTP enrolment, dashboard and settings
   Token-driven additions only; merged into main.css by the orchestrator.
   ========================================================================= */

/* The admin nav partial renders at page top level: keep its band full-bleed
   while its list lines up with .container content. */
.admin-nav ul {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

/* Admin screens breathe a little less than public editorial pages. */
.admin-main { padding-block: var(--space-6) var(--space-8); }

/* Sign-in: a narrow certificate on the desk. */
.admin-auth-panel {
  max-width: 28rem;
  margin-inline: auto;
  padding: var(--space-6);
}

.admin-auth-panel h1 { font-size: clamp(1.7rem, 3vw, 2.1rem); }

.admin-auth-seal { color: var(--green); }
.admin-auth-seal .seal-tick { color: var(--brass); }

/* Registration-index numerals on large seal lockups (seal.php $index):
   always brass, in any context. Dormant until a caller passes $index. */
.seal-index { color: var(--brass); }

/* TOTP enrolment. */
.admin-enrol-panel {
  max-width: 42rem;
  margin-inline: auto;
  padding: var(--space-6);
}

.admin-enrol-panel h1 { font-size: clamp(1.7rem, 3vw, 2.1rem); }

.admin-enrol-subhead {
  font-size: 1.05rem;
  margin-top: var(--space-5);
  margin-bottom: var(--space-2);
}

/* The base32 setup key: large, grouped, unmistakable. */
.totp-key {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--green-deep);
  background: var(--green-wash);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  overflow-wrap: anywhere;
}

/* The otpauth:// URI shown as plain text for apps that accept it. */
.totp-uri {
  font-size: 0.85rem;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  overflow-wrap: anywhere;
}

/* Dashboard stats that double as links into their queue or list. */
a.stat {
  display: block;
  text-decoration: none;
  transition: background-color 160ms var(--ease-out);
}

a.stat:hover { background: var(--verified-wash); }
a.stat:hover .stat-number { color: var(--green); }
a.stat .stat-label { display: block; }

.admin-quick-links {
  list-style: none;
  padding-left: 0;
  margin-bottom: 0;
}

.admin-quick-links li {
  margin: 0;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}

.admin-quick-links li:last-child { border-bottom: 0; padding-bottom: 0; }

.admin-quick-links a { font-weight: 600; }

.admin-quick-links .text-small { display: block; }

/* Settings form: readable measure, panels stacked. */
.admin-form { max-width: 46rem; }

.admin-founding-note { margin-bottom: var(--space-5); }

/* Inline field error (same rule as pkg-legal-contact; harmless duplicate). */
.field-error { color: var(--danger); }

/* --- Package: admin-ops (admin applications queue, member CRUD,
       enquiry log, email log) ---
   Token-driven only: existing custom properties, no new colours or fonts. */

/* Top gap comes from the hoisted .admin-nav band's margin (same as the admin
   dashboard); the container itself only pads the bottom. */
.admin-page { padding-block: 0 var(--space-8); }

.admin-page-head { margin-bottom: var(--space-5); }
.admin-page-head .admin-title { font-size: clamp(1.7rem, 3vw, 2.2rem); margin-bottom: var(--space-2); }
.admin-page-head p { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }

.admin-backlink { font-size: 0.92rem; margin-bottom: var(--space-4); }
.admin-backlink a { color: var(--ink-soft); text-decoration: none; }
.admin-backlink a:hover { color: var(--green-deep); text-decoration: underline; }

/* Queue and log filter tabs */
.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
}

.admin-tabs li { margin: 0; }

.admin-tabs a {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}

.admin-tabs a:hover { border-color: var(--line-strong); color: var(--green-deep); }

.admin-tabs a[aria-current="page"] {
  background: var(--green-wash);
  border-color: var(--green);
  color: var(--green-deep);
}

/* Tables in the admin panels */
.admin-table { width: 100%; font-size: 0.95rem; }
.admin-table td { vertical-align: top; }
.admin-table .status-pill { white-space: nowrap; }

/* Two-column working layout (applicant beside documents, and similar) */
.admin-split { display: grid; gap: var(--space-5); align-items: start; }

@media (min-width: 900px) {
  .admin-split { grid-template-columns: 1fr 1fr; }
}

/* Definition lists on detail pages */
.admin-dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-5); margin: 0 0 var(--space-5); }
.admin-dl dt { color: var(--ink-mute); font-size: 0.9rem; padding-top: 0.1rem; }
.admin-dl dd { margin: 0; }

.admin-plain-list { list-style: none; margin: 0 0 var(--space-5); padding: 0; }
.admin-plain-list li { margin: 0 0 var(--space-3); padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.admin-plain-list li:last-child { border-bottom: 0; }

.admin-prewrap { white-space: pre-wrap; }

/* Side-by-side row actions (nominations queue: update form + delete form) */
.admin-inline-forms { display: flex; flex-wrap: wrap; gap: var(--space-5); align-items: end; }
.admin-inline-forms form:first-child { flex: 1 1 22rem; }

/* Inline document viewer */
.doc-figure { margin: 0 0 var(--space-5); }
.doc-figure figcaption { margin-bottom: var(--space-3); }
.doc-figure figcaption strong { display: block; }

.doc-figure img {
  display: block;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
}

/* The A5 verification checklist (working aid, not stored) */
.check-list { list-style: none; margin: 0; padding: 0; max-width: 52rem; }
.check-list li { margin: 0; border-bottom: 1px solid var(--line); }
.check-list li:last-child { border-bottom: 0; }
.check-list label { display: flex; gap: var(--space-3); align-items: flex-start; padding: var(--space-3) 0; cursor: pointer; }
.check-list input[type="checkbox"] { flex: none; width: 1.15rem; height: 1.15rem; margin-top: 0.2rem; accent-color: var(--green); }

/* Form layouts inside panels */
.admin-form-grid { display: grid; gap: 0 var(--space-5); }

@media (min-width: 700px) {
  .admin-form-grid { grid-template-columns: 1fr 1fr; }
}

/* A fee item's three fields (name / minutes / price) on ONE row from tablet up;
   name gets the most width, minutes and price stay narrow. minmax(0,..) stops a
   long name from blowing the grid out. Shared by the admin concierge builder,
   the member editable preview and the member dashboard fee editors. */
.fee-fields-row { display: grid; gap: 0 var(--space-4); }
@media (min-width: 640px) {
  .fee-fields-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); }
}

.admin-check-grid { display: grid; gap: var(--space-2); margin-bottom: var(--space-5); }

@media (min-width: 700px) {
  .admin-check-grid { grid-template-columns: 1fr 1fr; }
}

.check-label { display: flex; gap: var(--space-2); align-items: flex-start; font-size: 0.97rem; cursor: pointer; }
.check-label input[type="checkbox"] { flex: none; width: 1.05rem; height: 1.05rem; margin-top: 0.25rem; accent-color: var(--green); }

/* Status-change blocks (lapse / reinstate / remove) */
.admin-status-form { padding-bottom: var(--space-4); margin-bottom: var(--space-4); border-bottom: 1px solid var(--line); }
.admin-status-form h3 { font-size: 1.05rem; }
.admin-status-form .btn { margin-top: var(--space-3); }

/* Destructive areas keep the same tokens, flagged with the danger hue */
.danger-panel { border-color: var(--danger); }
.danger-panel > h2 { color: var(--danger); }

.admin-error-text { color: var(--danger); }

/* ---- Admin member page: stage banner + accordion sections ------------------
   The stage banner shows where a member is (a stepper) and the one next action;
   its tone (action/wait/done/warn) tints the accent. The record is then broken
   into collapsible <details> accordion sections. */
.admin-stage {
  --stage-accent: var(--ink-mute);
  border: 1px solid var(--line);
  border-left: 5px solid var(--stage-accent);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
  display: grid;
  gap: var(--space-4);
}
.admin-stage-action { --stage-accent: var(--brass-deep); }
.admin-stage-wait   { --stage-accent: var(--ink-mute); }
.admin-stage-done   { --stage-accent: var(--green); }
.admin-stage-warn   { --stage-accent: var(--danger); }

.admin-stage-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}
.admin-stage-step {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.85rem;
  color: var(--ink-mute);
}
.admin-stage-dot {
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--paper-2);
  color: var(--ink-mute);
  border: 1px solid var(--line);
}
.admin-stage-step.is-done { color: var(--ink-soft); }
.admin-stage-step.is-done .admin-stage-dot { background: var(--green-wash); color: var(--green); border-color: var(--green-wash); }
.admin-stage-step.is-current { color: var(--ink); font-weight: 700; }
.admin-stage-step.is-current .admin-stage-dot { background: var(--stage-accent); color: var(--on-green); border-color: var(--stage-accent); }
.admin-stage-step-label { white-space: nowrap; }

.admin-stage-label { font-size: 1.1rem; }
.admin-stage-badge {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.12em 0.55em;
  border-radius: 999px;
  background: var(--stage-accent);
  color: var(--on-green);
  vertical-align: middle;
  margin-right: var(--space-2);
}
.admin-stage-next { color: var(--ink-soft); margin-top: var(--space-1); }

.admin-section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-4);
}
.admin-section-head {
  list-style: none;
  cursor: pointer;
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  border-radius: var(--radius-lg);
}
.admin-section-head::-webkit-details-marker { display: none; }
.admin-section-head:hover { background: var(--paper-2); }
.admin-section-title { font-family: var(--font-serif); font-size: 1.2rem; font-weight: 600; }
.admin-section-head::after {
  content: "";
  margin-left: auto;
  width: 0.65rem;
  height: 0.65rem;
  border-right: 2px solid var(--ink-mute);
  border-bottom: 2px solid var(--ink-mute);
  transform: rotate(45deg);
  transition: transform 150ms var(--ease-out);
}
.admin-section[open] > .admin-section-head::after { transform: rotate(-135deg); }
.admin-section[open] > .admin-section-head {
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.admin-section-body { padding: var(--space-5); }
.admin-section-body > :first-child { margin-top: 0; }
.admin-section-danger { border-color: var(--danger); }
.admin-section-danger > .admin-section-head .admin-section-title { color: var(--danger); }

/* Filter bar on list pages */
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; margin-bottom: var(--space-5); }
.filter-bar .field { margin-bottom: 0; }
.filter-bar input[type="search"] { min-width: 18rem; }

/* Inline row-level action forms */
.admin-inline-form { display: inline-block; margin: 0 var(--space-2) var(--space-2) 0; }

/* Enquiry excerpts expand in place; content never leaves the page */
.admin-excerpt { max-width: 26rem; }
.admin-excerpt summary { cursor: pointer; color: var(--ink-soft); }
.admin-excerpt summary:hover { color: var(--green-deep); }
.admin-excerpt p { margin-top: var(--space-3); }

/* Pagination on the long logs */
.pagination { display: flex; gap: var(--space-4); align-items: center; margin-top: var(--space-5); }

/* ===========================================================================
   Compare page (/compare) and the profile's experience note
   =========================================================================== */

/* The member's own words about the one term this brand asks about. A quote
   block, because that is what it is: not our finding, theirs. Deliberately in
   About and never in the Verification card, so it can never borrow the
   authority of a fact somebody checked. */
.profile-experience-note {
  margin: var(--space-3) 0 0;
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--line-strong);
  background: var(--paper-2);
  color: var(--ink-soft);
  font-style: normal;
}

/* Wide content scrolls inside its own box. The page body must never scroll
   sideways, and three member columns plus the row labels will exceed a phone
   long before they exceed a desktop. */
.cmp-scroll {
  overflow-x: auto;
  margin-bottom: var(--space-5);
}

.cmp-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 34rem;
}

.cmp-table th,
.cmp-table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
}

/* The row labels stay put while the member columns scroll under them:
   without this, scrolling right on a phone leaves a grid of bare values with
   nothing saying what any of them are. */
.cmp-table tbody th[scope="row"],
.cmp-table tfoot th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--paper);
  font-weight: 600;
  color: var(--ink-soft);
  min-width: 11rem;
}

.cmp-table thead th { border-bottom: 2px solid var(--line-strong); }

/* THE HONEST PART OF THIS TABLE. A grid implies every row was established the
   same way; these headings are what stop it saying that. Styled as loud as a
   section heading precisely because they are load-bearing, not decoration. */
.cmp-group th {
  position: sticky;
  left: 0;
  background: var(--green-wash);
  color: var(--green-deep);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-strong);
}

/* The column heads are inside <th>, and the base th rule uppercases with
   letter-spacing - which is right for a row LABEL and wrong for a person's
   name and town. Reset it here rather than weakening the base rule. */
.cmp-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 10rem;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}

.cmp-head img {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: var(--space-1);
}

.cmp-name { font-weight: 600; }

.cmp-town {
  font-size: 0.85rem;
  color: var(--ink-mute);
}

/* Absence must read as absence, never as a fact. A blank cell in a comparison
   is ambiguous - did nobody ask, or did they say no? - so every empty value
   says which, quietly. */
.cmp-none { color: var(--ink-mute); }

.cmp-sub {
  display: block;
  margin-top: var(--space-1);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

.cmp-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.9rem;
  line-height: 1.6;
}

.cmp-note { max-width: none; }
