/* River Bluff Mental Health — Bootstrap 5.3 theme layer.
   Palette + typography from the RBMH Design Overview brand guide,
   applied by overriding Bootstrap's CSS variables.
   Canonical tokens documented in .claude/skills/river-bluff-design. */

:root {
    /* ---- Brand palette (canonical Core Color Palette) ---- */
    --rbmh-brown: #3b2a1a;               /* primary text & logo text */
    --rbmh-charcoal: #2f3a34;            /* footer & strongest dark  */
    --rbmh-olive: #6b7a4e;               /* PRIMARY brand color      */
    --rbmh-sage: #a5b49a;                /* secondary brand color    */
    --rbmh-terracotta: #c4714d;          /* warm accent              */
    --rbmh-terracotta-dark: #ab6142;     /* terracotta carrying text */
    --rbmh-terracotta-deep: #94543a;     /* its hover shade          */
    --rbmh-gold: #c9a35b;                /* highlight accent (sparing) */
    --rbmh-bg: #f7f5f1;                  /* main background (off white) */
    --rbmh-olive-dark: #58643f;          /* olive carrying text      */
    --rbmh-olive-deep: #454e31;          /* its hover shade          */

    /* ---- Contrast rule for the two brand colours ----
       Both --rbmh-olive and --rbmh-terracotta sit just under WCAG AA against the off-white
       background: olive on --rbmh-bg is 4.27:1 and white on terracotta is 3.61:1, where text
       under 24px (or under 18.66px bold) needs 4.5:1. Neither is wrong as a colour — they are
       under-contrast only when they carry *text*.
       So each has a -dark sibling that clears AA (olive-dark 5.83:1, white on terracotta-dark
       4.65:1) and a -deep sibling for that variant's hover, and the split is by job:
         text, links, button labels, button fills behind a label -> the -dark shade
         fills, borders, rules, icons, decorative marks           -> the base shade
       Non-text needs only 3:1, which the base shades clear comfortably, so the brand reads
       exactly as drawn everywhere its colour isn't being asked to be legible. */

    /* Soft accent washes: each brand colour mixed a tenth-or-so into the off-white background,
       so a panel reads as a tint of its accent rather than as a second neutral. */
    --rbmh-sage-soft: #f0f0ea;           /* soft card / section tint */
    --rbmh-terracotta-soft: #f0e3da;     /* soft terracotta wash     */
    --rbmh-gold-soft: #f0e8d9;           /* soft gold wash           */
    --rbmh-cream: #f2ede2;               /* warm sand disc behind an icon glyph */

    /* RGB channels for rgba() overlays, borders, and focus rings */
    --rbmh-brown-rgb: 59, 42, 26;
    --rbmh-olive-rgb: 107, 122, 78;
    --rbmh-terracotta-rgb: 196, 113, 77;
    --rbmh-gold-rgb: 201, 163, 91;
    --rbmh-bg-rgb: 247, 245, 241;        /* --rbmh-bg, for the hero's fade-to-background */

    /* Shared chrome: the quiet border that cards and panels carry, the hairline that rules
       and dividers are drawn with, the standard card corner, and the 30px button pill. */
    --rbmh-border-soft: rgba(var(--rbmh-brown-rgb), .08);
    --rbmh-hairline: rgba(var(--rbmh-brown-rgb), .12);
    --rbmh-card-radius: 0.85rem;
    --rbmh-pill-radius: 1.875rem;

    /* ---- Typography ---- */
    --rbmh-heading-font: "Playfair Display", Georgia, "Times New Roman", serif;
    --rbmh-body-font: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --rbmh-heading: var(--rbmh-brown);   /* heading text color */

    /* ---- Body / typography ---- */
    --bs-body-font-family: var(--rbmh-body-font);
    --bs-body-bg: var(--rbmh-bg);
    --bs-body-color: var(--rbmh-brown);
    --bs-body-color-rgb: var(--rbmh-brown-rgb);
    --bs-body-line-height: 1.7;

    /* ---- Primary brand = olive green ---- */
    --bs-primary: var(--rbmh-olive);
    --bs-primary-rgb: var(--rbmh-olive-rgb);

    /* ---- Links (olive, darker on hover) ---- */
    --bs-link-color: var(--rbmh-olive-dark);
    --bs-link-color-rgb: 88, 100, 63;
    --bs-link-hover-color: var(--rbmh-olive-deep);
    --bs-link-hover-color-rgb: 69, 78, 49;
}

/* ---- Headings use the serif display face (Playfair Display 600) ---- */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.navbar-brand {
    font-family: var(--rbmh-heading-font);
    color: var(--rbmh-heading);
    font-weight: 600;
}

/* ---- Public reading size ----
   The service detail pages set their copy as Bootstrap `.lead`, which renders as Lato
   regular at 20px/1.7 — `.lead` asks for weight 300 but only 400 and 700 are loaded — and
   that is the reading style the site uses for its public copy, not Bootstrap's 16px.
   Scoped to the public layout's <main> so the admin area, the navbar, and the footer keep
   their own utilitarian sizes; form controls read from --bs-body-font-size and so stay 16px,
   which is what keeps inputs and buttons in proportion beside the larger copy. */
.site-body main { font-size: 1.25rem; }
/* An address has no spaces to break at, and at the reading size the practice's own email is
   wider than a 375px phone. Let those two link types break mid-string rather than push the
   page into a sideways scroll. */
.site-body main a[href^="mailto:"],
.site-body main a[href^="tel:"] { overflow-wrap: anywhere; }

/* Design Overview hierarchy: H1 48/56, H2 32/40, H3 24/32.
   The .hN utility classes are matched to the elements so that a heading demoted for
   semantic reasons (an <h2 class="h3">) is the same size as the level it borrows. */
h1, .h1 { font-size: 3rem; line-height: 3.5rem; }
h2, .h2 { font-size: 2rem; line-height: 2.5rem; }
h3, .h3 { font-size: 1.5rem; line-height: 2rem; }
/* Below H3 the Design Overview stops, and against the public pages' 20px reading size
   Bootstrap's remaining ramp (24/20/16px) runs into and under it — an <h5> would match its
   own body copy and an <h6> would sit below it. On those pages they collapse to one
   small-heading step just above the reading size; the serif face, the weight, and the brown
   carry the rest of the distinction. Admin keeps Bootstrap's ramp, which still works under
   its 16px body. */
.site-body :is(h4, .h4, h5, .h5, h6, .h6) { font-size: 1.375rem; line-height: 1.85rem; }

/* ---- Container width on wide screens ----
   Bootstrap stops widening .container at 1320px, which on a 2K display strands a third of
   the viewport in gutter — and because the bleed heroes fill the right edge, nearly all of
   it reads as left margin. Track the viewport at 92vw instead, capped at 100rem so
   ultra-wide screens keep some breathing room. Header, main, and footer all share
   .container, so the whole public page widens together; the admin and platform layouts
   don't use .container and are untouched. */
@media (min-width: 1400px) {
    .container { max-width: min(100rem, 92vw); }
}

/* ---- Navbar ---- */
.navbar-brand {
    font-size: 1.4rem;
    letter-spacing: 0.03em;
}
/* Header brand lockup: logo mark + stacked wordmark, matching the footer lockup */
.main-navbar .navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.7rem;
    padding-top: 0;
    padding-bottom: 0;
}
.brand-mark { width: 3.4rem; height: 3.4rem; flex-shrink: 0; }
/* An admin-uploaded logo replaces the drawn mark: keep the lockup's height and let the width follow
   the file's aspect ratio (capped) so a wide logo isn't squashed into the square. */
img.brand-mark { width: auto; max-width: 10rem; object-fit: contain; }
.brand-wordmark { display: block; line-height: 1.1; }
.brand-wordmark__name {
    display: block;
    font-family: var(--rbmh-heading-font);
    font-weight: 600;
    font-size: 1.8rem;
    color: var(--rbmh-brown);
}
.brand-wordmark__sub {
    display: block;
    text-transform: uppercase;
    letter-spacing: 0.2em;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--rbmh-olive-dark);
    margin-top: 0.15rem;
}

/* Main site header sits on off-white, ~90px tall, sticky (per sitemap) */
.main-navbar {
    background-color: var(--rbmh-bg);
    position: sticky;
    top: 0;
    z-index: 1030;
}
/* Nav links: Lato title-case in brown, olive on hover/active (per mockup) */
.navbar .nav-link {
    font-size: 1rem;
    font-weight: 500;
    color: var(--bs-body-color);
}
.navbar .nav-link:hover,
.navbar .nav-link:focus,
.navbar .nav-link.show {
    color: var(--rbmh-olive);
}
/* Active item carries a short olive underline in the main header. (No !important needed: this loads
   after Bootstrap, so equal specificity wins by order.) */
.main-navbar .nav-link.active {
    color: var(--rbmh-olive);
    box-shadow: inset 0 -2px 0 0 var(--rbmh-olive);
}
.dropdown-item.active,
.dropdown-item:active {
    background-color: var(--bs-primary);
}
/* The header's Services menu. Bootstrap's default panel is a white box with a grey hairline; this one
   sits on the site's off-white and carries the same soft hairline and card radius as every other
   surface, so it reads as part of the header rather than as a browser control dropped on top of it. */
.main-navbar .dropdown-menu {
    background-color: var(--rbmh-bg);
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    box-shadow: 0 0.5rem 1.5rem rgba(var(--rbmh-brown-rgb), .1);
    padding: 0.4rem;
}
.main-navbar .dropdown-item {
    border-radius: calc(var(--rbmh-card-radius) - 0.35rem);
    color: var(--bs-body-color);
    font-weight: 500;
    padding: 0.4rem 0.75rem;
}
.main-navbar .dropdown-item:hover,
.main-navbar .dropdown-item:focus {
    background-color: var(--rbmh-sage-soft);
    color: var(--rbmh-olive);
}
/* Collapsed (mobile) the menu isn't a floating panel — it's the list continuing indented under
   Services, so the panel chrome would be a box inside the open nav. */
@media (max-width: 991.98px) {
    .main-navbar .dropdown-menu {
        background-color: transparent;
        border: 0;
        box-shadow: none;
        padding: 0 0 0 0.75rem;
    }
}

/* ---- Focus ring (site-wide) ----
   Bootstrap's `.btn:focus-visible` clears the browser's own outline and redraws the ring as a
   box-shadow built from --bs-btn-focus-shadow-rgb. It sets that variable inside each of ITS
   variants, so the brand's own button classes below (.btn-olive, .btn-outline-soft,
   .btn-footer-portal, .btn-footer-staff) inherited the cleared outline with no variable to
   rebuild from: var() resolved invalid, the shadow computed to `none`, and those controls —
   "View profile" on every therapist card, the footer's portal pair, the mobile menu toggle —
   showed no focus indication at all. The variants that did keep a ring drew Bootstrap's default
   blue at 25-50% alpha, 1.4-1.8:1 against the off-white, under the 3:1 an indicator needs.
   One ring for all of it settles both.
   :is(), not :where(): the rule has to outrank `.btn:focus-visible`, and :where() contributes
   nothing to specificity, which would leave this selector at (0,1,0) — losing to Bootstrap's
   (0,2,0) however late the file loads. :is() takes the specificity of its most specific
   argument (.btn, a class), so this lands at (0,2,0) too and wins on source order instead. */
:is(a, button, .btn, .nav-link, .navbar-toggler, [tabindex]):focus-visible {
    outline: 3px solid var(--rbmh-olive-deep);
    outline-offset: 2px;
    box-shadow: none;
}
/* outline-offset draws the ring just outside the control, so what it has to contrast with is
   the surface BEHIND the control, not the control itself — olive-deep reads 8.1:1 on the page
   background and 7.7:1 on the sage panels, but vanishes on the footer's charcoal. */
.site-footer :is(a, button, .btn):focus-visible { outline-color: #fff; }

/* ---- Buttons (Bootstrap 5.3 uses per-component vars) ---- */
/* Every brand button shares the pill signature: 30px radius, uppercase label, wide
   tracking, bold. The variants below only supply their colours. */
.btn-primary,
.btn-outline-primary,
.btn-outline-soft,
.btn-olive,
.btn-footer-portal {
    --bs-btn-border-radius: var(--rbmh-pill-radius);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
}
/* An arrow riding inside a button label ("View profile →"); em-sized so it scales with
   whatever button size it sits in. */
.btn .btn-arrow {
    width: 1em;
    height: 1em;
    margin-left: 0.3rem;
    vertical-align: -0.15em;
}
/* Primary CTA — filled terracotta pill, white uppercase label
   (the "Request Appointment" button in the sitemap).
   The fill is terracotta-dark, not the base terracotta: this label is white at 16px bold, which
   is not "large text", so it needs 4.5:1 — the base shade gives 3.61:1 and the dark one 4.65:1.
   Hover then goes to terracotta-deep, keeping the darken-on-hover direction the design has. */
.btn-primary {
    --bs-btn-bg: var(--rbmh-terracotta-dark);
    --bs-btn-border-color: var(--rbmh-terracotta-dark);
    --bs-btn-hover-bg: var(--rbmh-terracotta-deep);
    --bs-btn-hover-border-color: var(--rbmh-terracotta-deep);
    --bs-btn-active-bg: var(--rbmh-terracotta-deep);
    --bs-btn-active-border-color: var(--rbmh-terracotta-deep);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
    --bs-btn-disabled-bg: var(--rbmh-terracotta-dark);
    --bs-btn-disabled-border-color: var(--rbmh-terracotta-dark);
}
/* Secondary — outlined olive pill, fills olive on hover
   (the "Client Portal" button in the sitemap). Label and border take the -dark shade so the
   resting label clears AA; the hover fill stays base olive, where white already reads 4.65:1. */
.btn-outline-primary {
    --bs-btn-color: var(--rbmh-olive-dark);
    --bs-btn-border-color: var(--rbmh-olive-dark);
    --bs-btn-hover-bg: var(--rbmh-olive);
    --bs-btn-hover-border-color: var(--rbmh-olive);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--rbmh-olive);
    --bs-btn-active-border-color: var(--rbmh-olive);
    --bs-btn-active-color: #fff;
}
/* Quiet tertiary — hairline pill with a dark-brown label (the therapist cards' "View
   profile" in the design); fills olive on hover like the secondary. */
.btn-outline-soft {
    --bs-btn-color: var(--rbmh-brown);
    --bs-btn-border-color: var(--rbmh-hairline);
    --bs-btn-hover-bg: var(--rbmh-olive);
    --bs-btn-hover-border-color: var(--rbmh-olive);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--rbmh-olive);
    --bs-btn-active-border-color: var(--rbmh-olive);
    --bs-btn-active-color: #fff;
}
/* Filled olive pill — the in-page action that isn't the appointment CTA (the Paying page's
   "Learn More" banners); the terracotta pill stays reserved for booking. */
.btn-olive {
    --bs-btn-bg: var(--rbmh-olive);
    --bs-btn-border-color: var(--rbmh-olive);
    --bs-btn-hover-bg: var(--rbmh-olive-dark);
    --bs-btn-hover-border-color: var(--rbmh-olive-dark);
    --bs-btn-active-bg: var(--rbmh-olive-dark);
    --bs-btn-active-border-color: var(--rbmh-olive-dark);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
}

/* ---- Hero / soft sections ---- */
.hero,
.bg-cream {
    background-color: var(--rbmh-sage-soft);
}

/* ---- Footer: charcoal green base with muted-gold accents (per sitemap) ---- */
.site-footer {
    background-color: var(--rbmh-charcoal);
    border-top-color: var(--rbmh-charcoal) !important;
    color: rgba(255,255,255,.82);
    font-size: 0.95rem;
}
/* Scoped to :not(.btn) so the footer's link colour never outranks the buttons' own
   --bs-btn-* colours (`.site-footer a` used to beat `.btn`'s variables on specificity,
   which forced restated literal colours on every footer button). */
.site-footer a:not(.btn) { color: rgba(255,255,255,.82); }
.site-footer a:not(.btn):hover { color: var(--rbmh-gold); }
/* Column labels / emphasized lines pick up the gold accent */
.site-footer strong,
.site-footer .footer-heading {
    color: var(--rbmh-gold);
    font-weight: 700;
}
/* Brand lockup: stacked wordmark, mirroring the printed logo */
.footer-brand-link {
    display: inline-flex;
    align-items: center;
    margin-bottom: 1.25rem;
}
.footer-brand-link:hover { text-decoration: none; }
.footer-wordmark { display: block; line-height: 1.1; }
.footer-wordmark__name {
    display: block;
    font-family: var(--rbmh-heading-font);
    font-weight: 600;
    font-size: 1.65rem;
    color: #fff;
}
.footer-wordmark__sub {
    display: block;
    text-transform: uppercase;
    letter-spacing: 0.22em;
    font-size: 0.7rem;
    font-weight: 700;
    color: rgba(255,255,255,.72);
    margin-top: 0.2rem;
}
.footer-blurb { max-width: 34ch; }

/* Column headings: small uppercase gold labels (the footer's eyebrow) */
.site-footer .footer-heading {
    font-family: var(--rbmh-body-font);
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    margin-bottom: 1.1rem;
}

/* Link columns */
.footer-links {
    list-style: none;
    margin: 0;
    padding: 0;
}
.footer-links li + li { margin-top: 0.55rem; }

/* Contact list: line icon beside each address / phone, hairline between entries */
.footer-contact {
    list-style: none;
    margin: 0;
    padding: 0;
}
.footer-contact li {
    display: flex;
    gap: 0.7rem;
    line-height: 1.55;
}
.footer-contact li + li {
    margin-top: 0.85rem;
    padding-top: 0.85rem;
    border-top: 1px solid rgba(255,255,255,.14);
}
.footer-icon {
    width: 1.15rem;
    height: 1.15rem;
    flex-shrink: 0;
    margin-top: 0.2rem;
    color: var(--rbmh-terracotta);
}
.footer-contact__note {
    display: block;
    font-size: 0.82rem;
    color: rgba(255,255,255,.6);
}

/* Stacked CTAs. The olive outline is too dark on charcoal, so the portal button
   takes the footer's gold accent instead. */
.footer-cta {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
/* Slightly tighter than the header CTAs so the labels fit a narrow footer column.
   They still wrap rather than overflow the pill once the column is narrower than
   "Request Appointment" on one line. */
.footer-cta .btn {
    font-size: 0.72rem;
    padding: 0.8rem 0.6rem;
    letter-spacing: 0.04em;
    white-space: normal;
}
.btn-footer-portal {
    --bs-btn-color: var(--rbmh-gold);
    --bs-btn-border-color: var(--rbmh-gold);
    --bs-btn-hover-bg: var(--rbmh-gold);
    --bs-btn-hover-border-color: var(--rbmh-gold);
    --bs-btn-hover-color: var(--rbmh-charcoal);
    --bs-btn-active-bg: var(--rbmh-gold);
    --bs-btn-active-border-color: var(--rbmh-gold);
    --bs-btn-active-color: var(--rbmh-charcoal);
    border: 1px solid var(--rbmh-gold);
}

/* Staff sign-in. Same pill as the portal button above it — including its gold hairline, which the
   .btn-footer-portal shorthand keeps — but filled rather than left as an outline: two identical gold
   outlines stacked read as one control split in half. The fill is the footer's own link white
   (rgba(255,255,255,.82)), so it is the same tone as the Quick Links beside it rather than a brighter
   white the palette doesn't use anywhere else. */
.btn-footer-staff {
    --bs-btn-bg: rgba(255,255,255,.82);
    --bs-btn-color: var(--rbmh-charcoal);
}
.site-footer .btn:hover { text-decoration: none; }

/* Copyright bar */
.footer-bottom {
    border-top: 1px solid rgba(255,255,255,.14);
    padding: 1.25rem 0;
    text-align: center;
    font-size: 0.88rem;
    color: rgba(255,255,255,.65);
}

/* ---- Misc ---- */
.text-primary { color: var(--bs-primary) !important; }
.text-prewrap { white-space: pre-wrap; }
/* The muted "Active" account state (_AccountStatusBadge). rem-based on purpose: Bootstrap's .small is
   em-based and compounds when rows nest it, so this stays 14px in any host. */
.status-active { font-size: 0.875rem; color: var(--bs-secondary-color); }
a { text-decoration: none; }
a:hover { text-decoration: underline; }
.navbar-brand:hover, .nav-link:hover { text-decoration: none; }

/* ============================================================
   Brand components — from the RBMH Design Overview
   ============================================================ */

/* ---- Soft accent washes (pale tints for panels, cards, quotes) ---- */
.bg-sage-soft       { background-color: var(--rbmh-sage-soft); }
.bg-terracotta-soft { background-color: var(--rbmh-terracotta-soft); }
.bg-gold-soft       { background-color: var(--rbmh-gold-soft); }

/* ---- Eyebrow: small uppercase label above a heading ---- */
.eyebrow {
    display: inline-block;
    font-family: var(--rbmh-body-font);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--rbmh-olive-dark);
    margin-bottom: 0.5rem;
}

/* ---- Accent panel: calm block with quiet border + generous padding ---- */
.accent-panel {
    border-radius: 1rem;
    padding: 2rem;
    border: 1px solid var(--rbmh-border-soft);
}
@media (min-width: 768px) {
    .accent-panel { padding: 2.75rem; }
}

/* ---- Pull quote: brand/mission line, per the guide's quote card ----
   Documented brand component (river-bluff-design skill); no view uses it today.
   Kept deliberately as part of the brand kit rather than deleted as dead. */
.pull-quote {
    position: relative;
    border-radius: 1rem;
    padding: 2.25rem 2rem 2rem;
    text-align: center;
    background-color: var(--rbmh-terracotta-soft);
    color: var(--rbmh-brown);
}
.pull-quote::before {
    content: "\201C";                   /* opening curly quote */
    display: block;
    font-family: var(--rbmh-heading-font);
    font-size: 3.25rem;
    line-height: 0.6;
    color: var(--rbmh-terracotta);
    margin-bottom: 0.5rem;
}
.pull-quote p {
    font-family: var(--rbmh-heading-font);
    font-size: 1.35rem;
    line-height: 1.5;
    margin-bottom: 0.75rem;
}
.pull-quote cite {
    font-style: normal;
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--rbmh-terracotta);
}

/* ---- Cards: brand polish (quiet border, soft radius, optional hover lift) ---- */
.card {
    --bs-card-border-color: var(--rbmh-border-soft);
    --bs-card-border-radius: var(--rbmh-card-radius);
}
.card-hover { transition: transform .18s ease, box-shadow .18s ease; }
.card-hover:hover {
    transform: translateY(-3px);
    box-shadow: 0 .75rem 1.5rem rgba(var(--rbmh-brown-rgb),.10) !important;
}

/* ---- Icon medallion: soft circular fill with a centered glyph/SVG ---- */
.icon-circle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    flex-shrink: 0;
}
.icon-circle svg { width: 1.25rem; height: 1.25rem; }
/* The editorial size: a disc about two lines of body copy tall, so it holds its own beside a
   paragraph rather than reading as a bullet. The glyph fills a little over half the disc — the
   base .icon-circle ratio leaves too much air once the disc is this big. */
.icon-circle--lg { width: 4.25rem; height: 4.25rem; }
/* The glyphs are drawn at the 1.5 hairline the small discs use, which thins out at this size.
   The stroke is set here rather than on each <svg> so the weight travels with the size that
   needs it — the markup's stroke-width is a presentation attribute, so this rule wins. */
.icon-circle--lg svg { width: 2.5rem; height: 2.5rem; stroke-width: 2; }
.icon-circle--olive      { background: rgba(var(--rbmh-olive-rgb),.14); color: var(--rbmh-olive); }
/* Warm sand disc with a dark-brown glyph — the editorial treatment, as opposed to the
   tinted-to-match discs above that colour-code what they sit beside. */
.icon-circle--cream      { background: var(--rbmh-cream); color: var(--rbmh-brown); }
.icon-circle--terracotta { background: rgba(var(--rbmh-terracotta-rgb),.16); color: var(--rbmh-terracotta); }
.icon-circle--gold       { background: rgba(var(--rbmh-gold-rgb),.16); color: var(--rbmh-gold); }
/* Solid olive disc with a white glyph — the strong medallion for cards and banners where the
   soft tints above would read too quiet (the Paying page's option cards and notice panels). */
.icon-circle--olive-fill { background: var(--rbmh-olive); color: #fff; }

/* ---- Editorial media frame: fixed-shape photo in a content row ----
   Documented brand component (river-bluff-design skill); no view uses it today.
   Kept deliberately as part of the brand kit rather than deleted as dead.
   Photos in content rows are admin-swappable through /Admin/Website, so their
   intrinsic size and aspect ratio are unknown at build time. The frame pins the
   shape and crops with object-fit, so every photo on a page reads as the same
   size and proportion no matter what gets uploaded. The aspect-ratio also
   reserves the layout box before the image loads, so nothing shifts.
   The sage fill is what shows during that load. */
.media-frame {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    object-position: center;
    background-color: var(--rbmh-sage-soft);
}
/* Taller crop when the row is stacked — a wide letterbox reads as a banner on phones. */
@media (max-width: 767.98px) {
    .media-frame { aspect-ratio: 3 / 2; }
}

/* ---- Therapist head-shot frame ----
   The photos come from the therapists themselves, so they arrive as phone portraits at whatever shape the
   camera gave — 0.56 to 1.0 wide-over-tall across the current roster. Any card grid has to crop them to one
   uniform shape, and the two defaults both work against a head-shot:

   * object-position defaults to centre, but nobody photographs with their face in the middle of the frame —
     it sits in the upper third. A centred crop of a tall portrait therefore eats the top of the head first.
   * A fixed pixel height means the crop gets more brutal the wider the card, so the worst case is a phone,
     where one card spans the whole row and a 300px band reduces a portrait to a horizontal slice of a face.

   So: a square box, which holds a constant amount of a portrait at every breakpoint, and a crop window
   pulled up to 20% so hair and forehead stay inside it. The sage fill is what shows while the image loads. */
.headshot-frame {
    display: block;
    width: 100%;
    object-fit: cover;
    object-position: 50% 20%;
    background-color: var(--rbmh-sage-soft);
}
/* The card-grid variant. aspect-ratio also reserves the box before the image arrives, so nothing shifts. */
.headshot-frame--card {
    aspect-ratio: 1 / 1;
}

/* ---- Therapist card: the design's tile anatomy on top of the Bootstrap card ----
   A charcoal medallion straddles the photo's bottom edge, the credentials read as a small
   olive kicker over a pale gold rule, and the CTA is the quiet hairline pill. */
.therapist-card__media { position: relative; }
.therapist-card__badge {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translate(-50%, 50%);
    width: 3rem;
    height: 3rem;
    background: var(--rbmh-charcoal);
    color: var(--rbmh-gold);
    /* Ring in the card's own surface so the disc reads as lifted off the photo. */
    border: 3px solid var(--bs-card-bg, #fff);
}
.therapist-card__creds {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--rbmh-olive-dark);
    padding-bottom: 0.7rem;
    border-bottom: 1px solid rgba(var(--rbmh-gold-rgb), .45);
}

/* ---- Hero polish ---- */
.hero { border: 1px solid var(--rbmh-border-soft); }

/* ---- Bleed hero: copy on the left, photo bleeding off the right edge ----
   Shared construction for the home and About heroes. The photo has no visible frame — it
   runs to the top, right, and bottom of the band and dissolves into the page background on
   its left, so the two halves read as one surface. The dissolve is an overlay painted in
   the page background colour rather than a mask, so it matches --rbmh-bg exactly whatever
   that is set to. The two pages differ only in the custom properties their modifier blocks
   set below (media height, desktop dissolve, copy width, crop focus) and their inner
   paddings. */
.bleed-hero {
    position: relative;
    background-color: var(--rbmh-bg);
    overflow: hidden;
}
.bleed-hero__media {
    position: relative;
    width: 100%;
    height: var(--bleed-hero-media-h);
}
.bleed-hero__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--bleed-hero-focus, center);
}
/* Small screens stack: the photo sits above the copy and fades out downward into it. */
.bleed-hero__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom,
        rgba(var(--rbmh-bg-rgb), 0) 45%,
        rgba(var(--rbmh-bg-rgb), .75) 82%,
        rgb(var(--rbmh-bg-rgb)) 100%);
}
.bleed-hero__inner {
    position: relative;
}

@media (min-width: 992px) {
    .bleed-hero__media {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: auto;
        width: 55%;
        height: auto;
    }
    /* Left-to-right dissolve: solid background at the photo's left edge, clearing at the
       pace each page's modifier sets. */
    .bleed-hero__media::after {
        background: var(--bleed-hero-dissolve);
    }
    .bleed-hero__copy { width: var(--bleed-hero-copy-w); }
}

/* -- Home modifier -- */
.home-hero {
    --bleed-hero-media-h: clamp(15rem, 52vw, 22rem);
    /* The media band runs well under the copy (72% wide vs the copy's 50%), so the photo
       reveals gradually: near-solid background through ~33% of the band — where the copy's
       right edge consistently lands across breakpoints — then clearing by ~58%. */
    --bleed-hero-dissolve: linear-gradient(to right,
        rgb(var(--rbmh-bg-rgb)) 0%,
        rgba(var(--rbmh-bg-rgb), .95) 18%,
        rgba(var(--rbmh-bg-rgb), .9) 33%,
        rgba(var(--rbmh-bg-rgb), .35) 46%,
        rgba(var(--rbmh-bg-rgb), 0) 58%);
    /* Capped so the copy only ever reaches the near-solid first third of the dissolve,
       whatever the viewport width. */
    --bleed-hero-copy-w: 50%;
}
.home-hero .bleed-hero__inner {
    padding-top: 2.5rem;
    padding-bottom: 3rem;
}

@media (min-width: 992px) {
    /* The home page is the only section in <main>, which the layout stretches to fill any
       viewport height the header and footer leave over. Passing that stretch down to the
       hero — and on to its inner row — keeps the photo running the full content height on
       tall screens instead of stopping at the 33rem floor. */
    main:has(> .home-hero) { display: flex; flex-direction: column; }
    .home-hero { display: flex; flex-direction: column; flex: 1 1 auto; }
    .home-hero .bleed-hero__inner {
        display: flex;
        align-items: center;
        flex: 1 1 auto;
        min-height: 33rem;
        padding-top: 3.5rem;
        padding-bottom: 3.5rem;
    }
    .home-hero .bleed-hero__copy { max-width: 40rem; }
    /* The uploaded hero photo is a small landscape (634×376); covering the band's full
       height blows it up ~1.6×, and at the shared 55% width that crops a third of the
       scene away. Widening the band keeps the full-height bleed but reveals nearly the
       whole photo, the extra width emerging from under the dissolve. */
    .home-hero .bleed-hero__media { width: 72%; }
}

/* xxl hero heading: 64–72px desktop, scaling down on smaller viewports */
.home-hero__title {
    font-size: clamp(2.4rem, 5.2vw, 4.25rem);
    line-height: 1.08;
    color: var(--rbmh-brown);
    margin-bottom: 1rem;
}
/* lg subheading in Lato */
.home-hero__subtitle {
    font-family: var(--rbmh-body-font);
    font-size: 1.35rem;
    line-height: 1.55;
    color: var(--rbmh-brown);
    max-width: 42ch;
}
/* Three info facts: olive line icon + dark-brown label, divided into columns */
.hero-facts__icon {
    width: 1.9rem;
    height: 1.9rem;
    color: var(--rbmh-olive);
    flex-shrink: 0;
}
.hero-facts__label {
    font-size: 0.88rem;
    line-height: 1.35;
    color: var(--rbmh-brown);
}
@media (min-width: 576px) {
    /* quiet vertical dividers between the three facts, as in the mockup */
    .hero-facts > li + li { border-left: 1px solid var(--rbmh-hairline); }
}

/* -- Team modifier: the photo bleeds in from the LEFT edge instead and the copy is centered,
   so the header reads as a symmetric title block with the river dissolving in beside it. -- */
.team-hero {
    --bleed-hero-media-h: clamp(11rem, 40vw, 15rem);
    /* Mirrored dissolve ("to left" — the base's ::after just paints whatever gradient this
       holds): solid page background at the photo's right edge, clearing toward the viewport's
       left corner so only that corner reads as picture. */
    --bleed-hero-dissolve: linear-gradient(to left,
        rgb(var(--rbmh-bg-rgb)) 0%,
        rgb(var(--rbmh-bg-rgb)) 18%,
        rgba(var(--rbmh-bg-rgb), .55) 55%,
        rgba(var(--rbmh-bg-rgb), 0) 100%);
    --bleed-hero-copy-w: 100%;
}
.team-hero .bleed-hero__inner {
    padding-top: 2.5rem;
    padding-bottom: 1.5rem;
    text-align: center;
}
@media (min-width: 992px) {
    /* Flip the base's right-anchored media to the left edge; the centered copy spans the
       full container and floats over the dissolved tail of the photo. */
    .team-hero .bleed-hero__media {
        right: auto;
        left: 0;
        width: 38%;
    }
    .team-hero .bleed-hero__inner {
        padding-top: 3rem;
        padding-bottom: 2rem;
    }
}
.team-hero__title {
    font-size: clamp(2.4rem, 5vw, 3.6rem);
    line-height: 1.08;
    margin-bottom: 0.75rem;
}

/* ---- Dot rule: short centered hairline with a terracotta dot at its middle, dividing a
   heading from its lead (the Team header design). Inline-block so text-align centers it. ---- */
.dot-rule {
    position: relative;
    display: inline-block;
    width: 9rem;
    height: 1px;
    background-color: rgba(var(--rbmh-gold-rgb), .7);
    vertical-align: middle;
    margin-bottom: 1rem;
}
.dot-rule::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: var(--rbmh-terracotta);
}

/* -- About modifier -- */
.about-hero {
    --bleed-hero-media-h: clamp(13rem, 46vw, 19rem);
    /* The hero photo is a 3:2 portrait with the founder's head filling the top of the
       frame. Once the media box runs wider than 3:2 (tablets, and desktops past ~1300px)
       cover starts cropping vertically, and centred it takes the head first — so keep the
       top edge and let any overflow crop from the bottom. */
    --bleed-hero-focus: center top;
    /* Clear by ~25% across. It stays solid through the first 7%, which is as far as the
       copy column ever reaches, so the softening happens over picture rather than under
       text. */
    --bleed-hero-dissolve: linear-gradient(to right,
        rgb(var(--rbmh-bg-rgb)) 0%,
        rgba(var(--rbmh-bg-rgb), .9) 7%,
        rgba(var(--rbmh-bg-rgb), .4) 15%,
        rgba(var(--rbmh-bg-rgb), 0) 25%);
    /* Reaches a little past the photo's left edge — into the near-solid first tenth of the
       dissolve, never the picture itself — which is the width the intro needs to break as
       drawn: "…evidence-based" has to finish line two, and that wants 516px of measure. */
    --bleed-hero-copy-w: 47%;
}
.about-hero .bleed-hero__inner {
    padding-top: 2rem;
    padding-bottom: 2rem;
}

@media (min-width: 992px) {
    /* The design draws the photo as a ~1.83:1 box — 55% of the page wide, ~30% tall.
       Narrow desktops need more height than that for the copy and grow past the floor;
       on wide screens, where the copy stops governing, the floor keeps the band at the
       drawn proportion instead of letting it flatten into a letterbox strip that zooms
       the photo well past the design's framing. The copy holds to the top of the band;
       any slack the floor opens up runs out below it. */
    .about-hero .bleed-hero__inner {
        display: flex;
        align-items: flex-start;
        min-height: 30vw;
        padding-top: 2.5rem;
        padding-bottom: 2rem;
    }
}

.about-hero__title {
    font-size: clamp(2.6rem, 5.5vw, 4rem);
    line-height: 1.05;
    margin-bottom: 1rem;
}
.about-hero__subtitle {
    font-family: var(--rbmh-heading-font);
    font-size: clamp(1.35rem, 2.6vw, 1.75rem);
    line-height: 1.35;
    color: var(--rbmh-brown);
    /* Capped inside the copy column so the three lines land where the design puts them.
       At the 28px ceiling the break points sit in a 25px window: "…Accessibility," measures
       439px and has to fit, while "…Better Mental Health" measures 464px and must not. */
    max-width: 28rem;
    margin-bottom: 1.5rem;
}
/* Short terracotta rule between the subtitle and the opening paragraph, as in the design. */
.about-rule {
    display: block;
    width: 3.5rem;
    height: 2px;
    background-color: var(--rbmh-terracotta);
    margin-bottom: 1.5rem;
}
.about-hero__intro {
    font-size: 1.2rem;
}
/* This page's kickers read taupe in the design, not the site's olive. (.75, not the .65 that
   matches the drawing: below .75 the taupe drops under 4.5:1 on the off-white.) */
.about-hero .eyebrow,
.about-journey .eyebrow { color: rgba(var(--rbmh-brown-rgb), .75); }
/* The design breathes more between the mid-page blocks than Bootstrap's mb-5 allows. */
.about-block { margin-bottom: 4.5rem; }
/* The opening story/specialties block runs tighter than the rest of the page. */
.about-block--tight { margin-bottom: 3rem; }
.about-founder {
    color: var(--rbmh-olive);
    font-weight: 700;
}

/* ---- About story: one icon medallion per paragraph ---- */
.about-story__item {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
}
.about-story__item + .about-story__item { margin-top: 1.25rem; }
.about-story__item p { font-size: 1.2rem; }

/* ---- About specialties: feather-marked list inside the panel ----
   The header is the medallion and the heading side by side. The heading is not a display
   heading — the design sets it in the body face, bold and olive, only a step up from the
   list under it. Its measure is capped so it breaks into the drawn three lines rather than
   running the panel's full width. */
/* The panel sits tighter vertically than the stock accent panel. */
.about-specialties {
    padding-top: 1.25rem;
    padding-bottom: 1.25rem;
}
@media (min-width: 768px) {
    .about-specialties { padding-top: 1.75rem; padding-bottom: 1.75rem; }
}
.about-specialties__header {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.25rem;
    /* The header hangs a little left of the list below it in the design: the medallion sits
       about half the panel padding out, with the leaf marks indented back at the padding edge. */
    margin-left: -0.75rem;
}
/* This one medallion carries an olive feather, not the brown glyph the cream disc defaults
   to — in the design it echoes the olive feather marks on the list below it. */
.about-specialties__header .icon-circle {
    flex-shrink: 0;
    color: var(--rbmh-olive);
}
.about-specialties__heading {
    font-family: var(--rbmh-body-font);
    font-weight: 700;
    font-size: 1.45rem;
    line-height: 1.45;
    color: var(--rbmh-olive);
    max-width: 19rem;
}
.about-checklist li {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    /* The design sets every specialty bold, a touch smaller than body copy. */
    font-weight: 700;
    font-size: 1.2rem;
}
.about-checklist li + li { margin-top: 0.5rem; }
.about-checklist__mark {
    width: 1.05rem;
    height: 1.05rem;
    flex-shrink: 0;
    margin-top: 0.25rem;
    color: var(--rbmh-olive);
}

/* ---- About vision: an oversized medallion beside the copy, pull quote alongside ---- */
.about-vision__medallion {
    width: 6.25rem;
    height: 6.25rem;
    color: var(--rbmh-olive);
}
.about-vision__medallion svg { width: 3.5rem; height: 3.5rem; }
.about-vision__copy p:last-child { margin-bottom: 0; }
/* Not the terracotta card of .pull-quote — here the quote shares the panel with the copy
   beside it, divided by clean space alone. */
.about-quote {
    position: relative;
    padding-top: 3.25rem;
}
/* The rule sits under the quote rather than above it, so it closes the block. */
.about-rule--quote { margin-top: 1.25rem; margin-bottom: 0; }
.about-quote::before {
    content: "\201C";                   /* opening curly quote */
    position: absolute;
    top: 0;
    left: 0;
    font-family: var(--rbmh-heading-font);
    /* Playfair's quote ink fills less than half its em box, so the em has to run well past
       the drawn mark: 6rem of em yields the design's mark of about a line and a half. */
    font-size: 6rem;
    line-height: 1;
    color: var(--rbmh-terracotta);
}
.about-quote p {
    font-family: var(--rbmh-heading-font);
    font-size: 1.3rem;
    line-height: 1.45;
    /* The whole quote block is terracotta in the design — marks, text, and closing rule. */
    color: var(--rbmh-terracotta);
}
@media (min-width: 992px) {
    .about-quote { padding-left: 1.75rem; }
    .about-quote::before { left: 1.75rem; }
}

/* ---- About journey: a milestone timeline ----
   The connector is drawn per item rather than as one line across the row, so the timeline
   holds its shape whatever number of milestones the editor leaves behind. Columns carry
   their own padding instead of a grid gap, so each connector reaches exactly from one
   marker's centre to the next. */
.about-journey__list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.about-journey__item {
    position: relative;
    padding: 0 0.75rem;
    text-align: center;
}
.about-journey__item + .about-journey__item::before {
    content: "";
    position: absolute;
    top: 2rem;                          /* half the marker's height */
    right: 50%;
    left: -50%;
    height: 1px;
    background-color: rgba(var(--rbmh-brown-rgb), .18);
}
.about-journey__marker {
    position: relative;                 /* above the connector line */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    /* Deeper pine than olive-dark alone — the design's discs sit nearer the charcoal family. */
    background-color: color-mix(in srgb, var(--rbmh-olive-dark) 60%, var(--rbmh-charcoal));
    color: #fff;
    margin-bottom: 1rem;
}
.about-journey__marker svg { width: 1.75rem; height: 1.75rem; }
.about-journey__when {
    font-family: var(--rbmh-heading-font);
    font-size: 1.5rem;
    color: var(--rbmh-brown);
    margin-bottom: 0.4rem;
}
/* The milestone name is set in the body face, not the display serif — it is a label under
   the year, and the year is the serif moment in this block. */
.about-journey__title {
    font-family: var(--rbmh-body-font);
    font-weight: 700;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--rbmh-brown);
    /* Capped so the names wrap as drawn ("River Bluff Mental Health" / "Founded") — a
       generic measure, not a width tuned to any one name. */
    max-width: 12rem;
    margin: 0 auto 0.9rem;
}
.about-journey__note {
    font-size: 0.82rem;
    line-height: 1.6;
    color: rgba(var(--rbmh-brown-rgb), .78);
}
/* Stacked: the connector turns vertical and runs up into the previous milestone. */
@media (max-width: 575.98px) {
    .about-journey__list { grid-template-columns: 1fr; }
    .about-journey__item + .about-journey__item { margin-top: 2.5rem; }
    .about-journey__item + .about-journey__item::before {
        top: -1.75rem;
        left: 50%;
        right: auto;
        width: 1px;
        height: 1.75rem;
        transform: translateX(-50%);
    }
}

/* ---- "Why choose" strip (_WhyChoose partial, on About and Services) ----
   A divided strip of reasons. The hairlines fall between columns, so the rule that clears
   them keys off the column count at each breakpoint (2, then 4, then the design's 7)
   rather than the item count — an added or removed reason still lines up. */
.why-strip {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    row-gap: 1.75rem;
}
.why-strip__item {
    padding: 0 0.75rem;
    text-align: center;
    border-left: 1px solid var(--rbmh-hairline);
}
.why-strip__item:nth-child(2n+1) { border-left: 0; }
.why-strip__icon {
    display: block;
    width: 1.9rem;
    height: 1.9rem;
    margin: 0 auto 0.75rem;
    /* Olive in the design, the same green as the audience-card icons. */
    color: var(--rbmh-olive-dark);
}
.why-strip__label {
    display: block;
    font-size: 0.82rem;
    font-weight: 700;
    line-height: 1.5;
    color: var(--rbmh-brown);
}
@media (min-width: 576px) {
    .why-strip { grid-template-columns: repeat(4, 1fr); }
    .why-strip__item:nth-child(2n+1) { border-left: 1px solid var(--rbmh-hairline); }
    .why-strip__item:nth-child(4n+1) { border-left: 0; }
}
@media (min-width: 992px) {
    .why-strip { grid-template-columns: repeat(7, 1fr); }
    .why-strip__item:nth-child(4n+1) { border-left: 1px solid var(--rbmh-hairline); }
    .why-strip__item:nth-child(7n+1) { border-left: 0; }
}

/* ---- Type hero (shared: Services, Paying for Therapy): centered kicker, display title,
   lead, CTA ---- No photo here — the page opens on type alone, closed by a hairline that
   hands off to the band below. Each page caps its own title and intro widths (the
   .svc-hero__* / .pay-hero__* modifiers) so the display lines break where its design
   draws them. */
.page-hero {
    /* No padding of its own on top — the layout's py-5 already sets the page's standard gap. */
    padding: 0 0 3.25rem;
    border-bottom: 1px solid var(--rbmh-hairline);
    margin-bottom: 3.25rem;
}
.page-hero__title {
    font-size: clamp(2.6rem, 5.5vw, 4rem);
    line-height: 1.1;
    margin: 0 auto 1.25rem;
}
/* Capped so the title breaks as drawn: "Mental Health Care" / "for Every Stage of Life".
   13em was wide enough to pull "for" up onto the first line and 9.5em too narrow to hold
   "for Every Stage of Life" on one; 10.2em sits between the two, and being in em it holds
   the same break as the title scales down. */
.svc-hero__title { max-width: 10.2em; }
.page-hero__intro {
    /* Narrow enough to fall into the design's four centred lines rather than three. */
    max-width: 30rem;
    font-size: 1.2rem;
    margin-bottom: 1.75rem;
}
/* -- Wash modifier: the page opens on the same soft sage panel the accent panels further down
   sit on, so the washes bookend the page. The tint is what separates the hero from the band
   now, so the closing hairline gives way to the panel's own padding. */
.page-hero--wash {
    background-color: var(--rbmh-sage-soft);
    border-bottom: 0;
    border-radius: 1rem;
    padding: 3rem 1.5rem;
    /* The layout's py-5 opens every page 3rem below the header — right for a page that starts
       on bare type, too big a gap above a filled panel. Pulling back all but 0.75rem of it sets
       the wash just under the header without the section having to opt out of the container. */
    margin-top: -2.25rem;
}
@media (min-width: 768px) {
    .page-hero--wash { padding: 3.5rem 2.75rem; }
}

/* The kickers read green in the design, a shade darker than the site's olive. */
.page-hero .eyebrow,
.rule-kicker .eyebrow {
    color: var(--rbmh-olive-dark);
    font-size: 1rem;
}

.svc-band { margin-bottom: 3rem; }
.svc-meet {
    max-width: 50rem;
    font-size: 1.2rem;
}

/* ---- Section kicker (shared): a label set into a rule that spans the band — an uppercase
   eyebrow on Services, a serif heading on Paying for Therapy ---- */
.rule-kicker {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    margin-bottom: 1.1rem;
}
.rule-kicker .eyebrow {
    margin-bottom: 0;
    letter-spacing: 0.18em;
}
.rule-kicker::before,
.rule-kicker::after {
    content: "";
    flex: 1;
    height: 1px;
    background-color: var(--rbmh-hairline);
}

/* ---- Who we help: a rail of icon cards, the design's six across on wide screens ---- */
.svc-audiences {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}
@media (min-width: 768px)  { .svc-audiences { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .svc-audiences { grid-template-columns: repeat(6, 1fr); } }
.svc-card {
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    padding: 1.5rem 1rem;
    text-align: center;
}
.svc-card__icon {
    width: 2.4rem;
    height: 2.4rem;
    color: var(--rbmh-olive);
    margin-bottom: 0.9rem;
}
/* The card titles are set in the body face in the design, not the serif the page's own
   headings use — they read as labels on the cards rather than headings of their own.
   The Paying page's option cards and expect columns share the treatment. */
.svc-card__title,
.svc-treatment__title,
.pay-option__title,
.pay-expect__title {
    font-family: var(--rbmh-body-font);
    font-weight: 700;
}
.svc-card__title {
    font-size: 1.15rem;
    line-height: 1.3;
    margin-bottom: 0.6rem;
}
.svc-card__blurb {
    font-size: 0.9rem;
    line-height: 1.55;
    color: rgba(var(--rbmh-brown-rgb), .8);
}

/* ---- Specialized treatments: photo-and-copy cards, three across on wide screens ---- */
.svc-treatments {
    display: grid;
    gap: 1.25rem;
    margin-bottom: 0.9rem;
}
@media (min-width: 992px) { .svc-treatments { grid-template-columns: repeat(3, 1fr); } }
.svc-treatment {
    display: grid;
    /* The design gives the photo a shade less than half the card, 46:54 against the copy. */
    grid-template-columns: 0.86fr 1fr;
    gap: 1.25rem;
    /* Stretch, not start: in the design the photo is a tall panel running the card's full
       height, and the three cards share the tallest card's height, so the short ones keep
       their photo as tall as the long one's rather than leaving space under a square. */
    align-items: stretch;
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    padding: 0.85rem;
}
/* Same discipline as .media-frame: the photos are admin-swappable, so the crop keeps the three
   cards even whatever gets uploaded. The min-height holds the drawn portrait shape when the
   copy is short enough that the row would otherwise collapse. The sage fill shows during load. */
.svc-treatment__img {
    width: 100%;
    height: 100%;
    min-height: 11rem;
    object-fit: cover;
    border-radius: 0.6rem;
    background-color: var(--rbmh-sage-soft);
}
.svc-treatment__title {
    font-size: 1.15rem;
    line-height: 1.35;
    margin-bottom: 0.6rem;
}
.svc-treatment__blurb {
    font-size: 0.95rem;
    line-height: 1.55;
    color: rgba(var(--rbmh-brown-rgb), .8);
}

/* ---- Approaches strip: the specialty list divided by quiet bars, on a sage wash ---- */
.svc-approaches {
    padding: 1.5rem 2rem;
}
.svc-approaches__heading {
    font-family: var(--rbmh-body-font);
    font-weight: 700;
    font-size: 1.05rem;
    margin-bottom: 0.75rem;
}
.svc-approaches__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 0.4rem;
}
.svc-approaches__list li + li::before {
    content: "|";
    margin: 0 0.85rem;
    color: rgba(var(--rbmh-brown-rgb), .3);
}
/* Quiet links: brown at rest like the design's strip, olive underline on hover to say "link". */
.svc-approaches__list a { color: var(--rbmh-brown); }
.svc-approaches__list a:hover { color: var(--rbmh-olive-dark); }

/* ---- Condition chips: every non-approach specialty as a soft pill link ---- */
.svc-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.75rem 1rem;
}
/* Tags, not buttons: the design draws these as low, softly squared-off rectangles with wide
   side padding rather than the brand's 30px button pill. */
.svc-chip {
    display: inline-block;
    padding: 0.25rem 1.9rem;
    border-radius: 0.35rem;
    background-color: var(--rbmh-sage-soft);
    color: var(--rbmh-brown);
    font-size: 0.95rem;
    font-weight: 600;
    transition: background-color .15s ease, color .15s ease;
}
.svc-chip:hover {
    background-color: var(--rbmh-olive);
    color: #fff;
    text-decoration: none;
}

/* ============================================================
   Paying for Therapy page
   ============================================================ */

/* ---- Hero: the title breaks as drawn ("Accessible Care." / "Transparent Information.")
   and the intro runs wider than the Services hero's, into three centred lines. ----
   "Transparent Information." measures 11.74em in Playfair 600, so 12em holds it on one
   line while still pushing "Accessible Care." up onto its own. */
.pay-hero__title { max-width: 12em; }
.pay-hero__intro { max-width: 38rem; }

/* ---- Insurance rail: white logo tiles, up to seven across; a line without a logo
   ("and many more") renders as a text tile. ---- */
.pay-lead {
    max-width: 36rem;
    font-size: 1.2rem;
}
.pay-insurers {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin: 2rem 0 1.5rem;
}
@media (min-width: 768px)  { .pay-insurers { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .pay-insurers { grid-template-columns: repeat(7, 1fr); } }
.pay-insurer {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    /* White, not the page's off-white: the logo art sits on white, so a tinted tile would
       draw a visible white box around each logo. */
    background-color: #fff;
    padding: 0.9rem 1rem;
    min-height: 6rem;
}
.pay-insurer__logo {
    max-width: 100%;
    max-height: 4.4rem;
    object-fit: contain;
}
.pay-insurer__label {
    font-size: 0.95rem;
    color: rgba(var(--rbmh-brown-rgb), .8);
}
.pay-note {
    font-size: 0.95rem;
    color: rgba(var(--rbmh-brown-rgb), .75);
}

/* ---- Option cards: solid olive medallion beside a label title and blurb ---- */
.pay-options {
    display: grid;
    gap: 1.25rem;
}
@media (min-width: 992px) { .pay-options { grid-template-columns: repeat(3, 1fr); } }
.pay-option {
    display: flex;
    gap: 1.1rem;
    align-items: flex-start;
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    padding: 1.6rem 1.4rem;
}
.pay-option__title {
    font-size: 1.15rem;
    line-height: 1.3;
    margin-bottom: 0.5rem;
}
.pay-option__blurb {
    font-size: 0.95rem;
    line-height: 1.6;
    color: rgba(var(--rbmh-brown-rgb), .8);
}

/* ---- Notice panels (Good Faith Estimate, No Surprises Act, the closing questions call):
   a wash banner with a medallion or sprig, the copy, and the action pinned right on wide
   screens; everything stacks as the panel narrows. Shallower than the accent-panel default
   — these read as banners, not sections. ---- */
.pay-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem 1.75rem;
    padding: 1.75rem 2rem;
}
.pay-notice__copy { flex: 1 1 24rem; }
.pay-notice__body { font-size: 1.05rem; }
/* The sprig beside the closing call — ink-drawn, so it keeps the site's darkest color. */
.pay-questions__art {
    width: 6.25rem;
    height: 6.25rem;
    color: var(--rbmh-charcoal);
    flex-shrink: 0;
}

/* ---- What to expect: four quiet columns split by hairlines, like the why-strip ---- */
.pay-expect {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: 2rem;
    text-align: center;
}
@media (min-width: 768px) {
    .pay-expect { grid-template-columns: repeat(2, 1fr); }
    .pay-expect__item { padding: 0 1.75rem; border-left: 1px solid var(--rbmh-hairline); }
    .pay-expect__item:nth-child(2n+1) { border-left: 0; }
}
@media (min-width: 1200px) {
    .pay-expect { grid-template-columns: repeat(4, 1fr); }
    .pay-expect__item:nth-child(2n+1) { border-left: 1px solid var(--rbmh-hairline); }
    .pay-expect__item:nth-child(4n+1) { border-left: 0; }
}
.pay-expect__icon {
    width: 2.6rem;
    height: 2.6rem;
    color: var(--rbmh-terracotta);
    margin-bottom: 0.9rem;
}
.pay-expect__title {
    font-size: 1.15rem;
    margin-bottom: 0.5rem;
}
.pay-expect__blurb {
    font-size: 0.95rem;
    line-height: 1.6;
    color: rgba(var(--rbmh-brown-rgb), .8);
    margin-bottom: 0;
}

/* ============================================================
   Careers page
   ============================================================ */

/* ---- Hero modifier: the lake photo bleeds off the right edge (the base .bleed-hero
   construction, the home page's direction) behind a left-hand title block. ---- */
.careers-hero {
    --bleed-hero-media-h: clamp(13rem, 46vw, 18rem);
    /* The copy runs to ~45% of the container, so the background stays near-solid through the
       first third of the band and clears by ~58% — the photo's sunburst then falls in the open
       right half rather than behind the lead lines. */
    --bleed-hero-dissolve: linear-gradient(to right,
        rgb(var(--rbmh-bg-rgb)) 0%,
        rgba(var(--rbmh-bg-rgb), .94) 20%,
        rgba(var(--rbmh-bg-rgb), .8) 34%,
        rgba(var(--rbmh-bg-rgb), .3) 47%,
        rgba(var(--rbmh-bg-rgb), 0) 58%);
    --bleed-hero-copy-w: 48%;
    /* The horizon sits high in the frame and the interest is the sun above it, so keep the top
       edge and let a wide crop take from the bottom. */
    --bleed-hero-focus: center top;
}
.careers-hero .bleed-hero__inner {
    padding-top: 2.5rem;
    padding-bottom: 3rem;
}
@media (min-width: 992px) {
    .careers-hero .bleed-hero__media { width: 62%; }
    .careers-hero .bleed-hero__inner {
        padding-top: 3.5rem;
        padding-bottom: 4rem;
    }
}
.careers-hero__title {
    font-size: clamp(2.6rem, 6vw, 4.5rem);
    line-height: 1.05;
    margin-bottom: 1rem;
}
/* The two display lines under the title: serif, a step under an h3, set tight so they read as
   one two-line statement rather than two paragraphs. */
.careers-hero__lead {
    font-family: var(--rbmh-heading-font);
    font-size: clamp(1.25rem, 2.2vw, 1.6rem);
    line-height: 1.35;
    color: var(--rbmh-brown);
    margin-bottom: 0.25rem;
}
.careers-hero__intro {
    max-width: 32rem;
    font-size: 1.05rem;
    line-height: 1.75;
}

/* ---- Values: the three reasons in a rail, beside the culture panel ---- */
.careers-values {
    display: grid;
    gap: 2rem;
}
@media (min-width: 992px) {
    .careers-values {
        grid-template-columns: 1fr 1fr;
        gap: 3.5rem;
        align-items: start;
    }
}
.careers-value {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
    padding: 1.75rem 0;
    border-top: 1px solid var(--rbmh-hairline);
}
/* The first one opens the rail, so it needs no rule above it. */
.careers-value:first-child {
    border-top: 0;
    padding-top: 0;
}
.careers-value:last-child { padding-bottom: 0; }
.careers-value__title { margin-bottom: 0.4rem; }
.careers-value__blurb {
    font-size: 0.95rem;
    line-height: 1.6;
    color: rgba(var(--rbmh-brown-rgb), .8);
}

/* ---- Culture panel: the same warm sand as the Contact page's message panel, so the two
   pages' one-big-block sections read as the same surface ---- */
.careers-culture {
    background-color: var(--rbmh-cream);
    border-radius: 1rem;
    padding: 2rem 1.5rem;
}
@media (min-width: 768px) {
    .careers-culture { padding: 2.75rem; }
}
.careers-culture__head {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-bottom: 1.5rem;
}
.careers-culture p {
    font-size: 1rem;
    line-height: 1.75;
}
.careers-culture__quote {
    font-style: italic;
    color: rgba(var(--rbmh-brown-rgb), .85);
}

/* ---- Openings + form: two columns split by a hairline, as drawn ---- */
.careers-connect {
    display: grid;
    gap: 2.5rem;
}
@media (min-width: 992px) {
    .careers-connect {
        grid-template-columns: 1fr 1fr;
        gap: 3.5rem;
    }
    .careers-apply {
        border-left: 1px solid var(--rbmh-hairline);
        padding-left: 3.5rem;
    }
}
.careers-connect__title {
    font-size: clamp(1.9rem, 3.2vw, 2.4rem);
    margin-bottom: 1rem;
}
.careers-connect p {
    font-size: 1rem;
    line-height: 1.75;
}
/* Short gold underscore between the openings intro and the first posting — the design's one
   gold accent on the page, kept to the guide's 2–3%. */
.careers-rule {
    display: block;
    width: 3.5rem;
    height: 2px;
    background-color: var(--rbmh-gold);
    margin: 1.75rem 0;
}
.careers-openings__empty { color: rgba(var(--rbmh-brown-rgb), .8); }

/* ---- One posting ---- */
.careers-job {
    background-color: var(--rbmh-sage-soft);
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    padding: 1.75rem;
}
.careers-job + .careers-job { margin-top: 1.25rem; }
.careers-job__head {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
}
.careers-job__title {
    font-size: 1.25rem;
    margin-bottom: 0.6rem;
}
/* Where the position works: an icon-and-label pair per setting, wrapping to its own line on a
   phone and sitting side by side once there is room. */
.careers-job__settings {
    list-style: none;
    padding: 0;
    margin: 0 0 0.6rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.25rem;
    font-size: 0.9rem;
    color: rgba(var(--rbmh-brown-rgb), .8);
}
.careers-job__settings li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.careers-job__icon {
    width: 1.1rem;
    height: 1.1rem;
    color: var(--rbmh-olive);
    flex-shrink: 0;
}
.careers-job__type {
    font-size: 0.9rem;
    color: rgba(var(--rbmh-brown-rgb), .8);
}
.careers-job__rule {
    border-color: var(--rbmh-hairline);
    opacity: 1;
    margin: 1.25rem 0;
}
.careers-job__population,
.careers-job__body {
    font-size: 0.95rem;
    line-height: 1.65;
}
.careers-job__population { margin-bottom: 0.75rem; }
.careers-job__population strong { color: var(--rbmh-charcoal); }

/* "(optional)" beside the résumé label — quieter than the label it qualifies, and the inverse of
   the terracotta asterisk the required fields carry. */
.careers-apply__optional {
    font-weight: 400;
    color: rgba(var(--rbmh-brown-rgb), .75);
}

/* The sign-off under the submit button, centred on the button's width. */
.careers-apply__note {
    margin-top: 0.75rem;
    text-align: center;
    font-size: 0.95rem;
    color: rgba(var(--rbmh-brown-rgb), .75);
}

/* ============================================================
   Contact page
   ============================================================ */

/* ---- Hero: intro at the Paying hero's centred measure ---- */
.contact-hero__intro { max-width: 38rem; }

/* ---- Message panel: one warm-sand card holding the form and the response/hours rail,
   split by a hairline on wide screens; everything stacks as it narrows. ---- */
.contact-panel {
    display: grid;
    gap: 2rem;
    background-color: var(--rbmh-cream);
    border-radius: 1rem;
    padding: 2rem 1.5rem;
}
@media (min-width: 992px) {
    .contact-panel {
        grid-template-columns: 1.7fr 1fr;
        gap: 2.75rem;
        padding: 2.75rem;
    }
    .contact-panel__aside {
        border-left: 1px solid var(--rbmh-hairline);
        padding-left: 2.75rem;
    }
}
.contact-panel__rule {
    border-color: var(--rbmh-hairline);
    opacity: 1;
    margin: 1.75rem 0;
}
.contact-aside-block__heading {
    margin: 1rem 0 0.75rem;
}
.contact-aside-block__link {
    font-size: 0.95rem;
    overflow-wrap: anywhere;
}

/* The required-field mark beside a label — terracotta, like the drawn design's asterisks. */
.contact-form__req { color: var(--rbmh-terracotta); }

/* The inputs sit on the panel's sand wash, so they stay plain white to read as fields. */
.contact-form .form-control { background-color: #fff; }

/* The honeypot ("Website") field: parked off-screen rather than display:none, because some
   bots skip fields the layout engine says are invisible. People never see or tab into it. */
.contact-form__alt {
    position: absolute !important;
    left: -9999px !important;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* The thank-you card that replaces the submitted form, centred in the same space. */
.contact-thanks {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    height: 100%;
    min-height: 18rem;
    padding: 1rem;
}
.contact-thanks p { max-width: 26rem; }

/* ---- Office hours: label over value, one pair per line of Business.Hours ---- */
.contact-hours dt {
    font-weight: 600;
    color: var(--rbmh-charcoal);
}
.contact-hours dd {
    margin-bottom: 0.6rem;
    color: rgba(var(--rbmh-brown-rgb), .8);
}
.contact-hours dd:last-child { margin-bottom: 0; }

/* ---- Help strip: four quiet columns in one bordered card, split by hairlines —
   the pay-expect treatment moved inside a card, as drawn. ---- */
.contact-help {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: 2rem;
    text-align: center;
    border: 1px solid var(--rbmh-border-soft);
    border-radius: var(--rbmh-card-radius);
    padding: 2rem 1rem;
}
@media (min-width: 768px) {
    .contact-help { grid-template-columns: repeat(2, 1fr); }
    .contact-help__item { padding: 0 1.75rem; border-left: 1px solid var(--rbmh-hairline); }
    .contact-help__item:nth-child(2n+1) { border-left: 0; }
}
@media (min-width: 1200px) {
    .contact-help { grid-template-columns: repeat(4, 1fr); }
    .contact-help__item:nth-child(2n+1) { border-left: 1px solid var(--rbmh-hairline); }
    .contact-help__item:nth-child(4n+1) { border-left: 0; }
}
.contact-help__icon {
    width: 2.6rem;
    height: 2.6rem;
    color: var(--rbmh-olive);
    margin-bottom: 0.9rem;
}
.contact-help__title {
    font-size: 1.15rem;
    margin-bottom: 0.5rem;
}
.contact-help__blurb {
    font-size: 0.95rem;
    line-height: 1.6;
    color: rgba(var(--rbmh-brown-rgb), .8);
}

/* ---- Closing banner: the river photo beside the farewell copy, on the same sand wash
   as the message panel ---- */
.contact-closing {
    display: grid;
    gap: 1.5rem;
    align-items: center;
    background-color: var(--rbmh-cream);
}
@media (min-width: 768px) {
    .contact-closing { grid-template-columns: 2fr 3fr; gap: 2.5rem; }
}
.contact-closing__img {
    width: 100%;
    height: 100%;
    max-height: 11rem;
    object-fit: cover;
    border-radius: var(--rbmh-card-radius);
}

/* ---- Forms: brand labels + focus ---- */
:root { --bs-focus-ring-color: rgba(var(--rbmh-olive-rgb),.35); }
.form-label {
    font-weight: 600;
    color: var(--rbmh-charcoal);
    font-size: 0.9rem;
}
.form-control:focus,
.form-select:focus {
    border-color: var(--rbmh-olive);
    box-shadow: 0 0 0 0.2rem rgba(var(--rbmh-olive-rgb),.20);
}
.form-check-input:checked {
    background-color: var(--rbmh-olive);
    border-color: var(--rbmh-olive);
}
/* The form-level error block (_ValidationSummary). Bootstrap's .alert-danger carries the colour;
   these are the public pages' reading size, which would otherwise render the list at the 20px
   body size and make a failed submit shout. */
.form-error-summary {
    font-size: 1rem;
    border-radius: var(--rbmh-card-radius);
}
.form-error-summary__lead { font-weight: 700; margin-bottom: 0.35rem; }
.form-error-summary__list { margin-bottom: 0; padding-left: 1.15rem; }
.form-error-summary__list a { color: inherit; }
/* The summary takes focus on load (site.js), which is the point of it — but it is a container,
   not a control, so the ring reads as "start reading here", not "activate this". */
.form-error-summary:focus-visible {
    outline: 3px solid currentColor;
    outline-offset: 3px;
}

/* ---- Interactive list groups ---- */
.list-group-item-action:hover { background-color: var(--rbmh-sage-soft); }

/* ---- Text selection ---- */
::selection { background: rgba(var(--rbmh-olive-rgb),.20); }

/* ---- Card headers: subtle branded panel ---- */
.card-header {
    background-color: var(--rbmh-sage-soft);
    border-bottom-color: var(--rbmh-border-soft);
    font-family: var(--rbmh-heading-font);
}

/* ============================================================
   Admin / backend
   ============================================================ */
.admin-topbar {
    border-top: 3px solid var(--rbmh-olive);
}
.admin-topbar .navbar-brand {
    color: var(--rbmh-olive);
    letter-spacing: 0.01em;
}
/* Active admin nav item in brand olive. Scoped to the admin/platform top bar — the bare `.navbar`
   selector used to tie with the public header's rule above and leak font-weight onto it. */
.admin-topbar .nav-link.active {
    color: var(--bs-primary);
    font-weight: 600;
}
/* Bootstrap compiles the active pill to literal #0d6efd, ignoring the :root --bs-primary
   remap above — point it back at the brand color (sidebar rail, Website section list). */
.nav-pills {
    --bs-nav-pills-link-active-bg: var(--bs-primary);
}
/* Left nav rail — the offcanvas-md <aside> _AdminLayout puts in _PortalShell's Sidebar slot.
   Below md it is a stock Bootstrap drawer. From md up Bootstrap strips the offcanvas chrome
   with !important width/background/border rules on the <aside> itself, so the rail's size,
   fill, and divider have to live on the inner .offcanvas-body instead. */
.portal-main {
    min-width: 0; /* let wide tables scroll inside the page, not stretch past the rail */
}
@media (min-width: 768px) {
    .admin-sidebar {
        flex-grow: 0; /* Bootstrap sets flex-grow:1 on expanded offcanvas-md */
        flex-shrink: 0;
    }
    .admin-sidebar .offcanvas-body {
        display: block; /* Bootstrap makes the expanded body a flex row */
        width: 230px;
        height: 100%;
        padding: 1.5rem 1rem;
        background-color: var(--bs-body-bg);
        border-right: var(--bs-border-width) solid var(--bs-border-color);
    }
}
@media (max-width: 767.98px) {
    /* Below md the main rail is an offcanvas drawer (out of flow), so the body stacks. */
    .portal-body { flex-direction: column; }
}
/* Levels below the top of the rail: a section's own pages, nested under its link while that
   section is open (_PracticeNav, _JobsNav, _WebsiteNav). Stepped in behind a
   hairline so the level reads at a glance, and a shade quieter than the top-level links. The rule
   nests — a section inside Practice hangs its own list one step further in again. */
.admin-subnav-list {
    margin: 0.15rem 0 0.35rem 0.75rem;
    padding-left: 0.5rem;
    border-left: var(--bs-border-width) solid var(--bs-border-color);
}
.admin-subnav-list .nav-link {
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
    font-size: 0.9rem;
}

/* ---- Overview calendar: a rolling 30 days, today first ----
   Seven equal columns; each cell keeps a square-ish shape so the grid still reads as a calendar on a quiet
   month. The window starts on whatever weekday today is, so there is no standing Sun–Sat header and every
   cell names its own day. Today is the only accent — an olive medallion on the date. */
.admin-calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}
/* min-height rather than aspect-ratio: the cell keeps its calendar shape when the day is empty, and a
   busy day is allowed to grow instead of clipping what it is carrying. */
.admin-calendar-day {
    min-height: 5.5rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0.35rem;
    background-color: var(--rbmh-sage-soft);
    border-radius: 0.25rem;
    font-variant-numeric: tabular-nums;
}
/* Weekday left, date right, on one line — the weekday has to be per-cell now, and putting it opposite the
   number keeps the number where the eye already expects it. */
.admin-calendar-day > time {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
    line-height: 1.75rem;
}
.admin-calendar-dow {
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--rbmh-olive);
}
/* The month name on the 1st. It reads as a heading rather than a date part — serif, uppercase, terracotta
   — because it is the one label on the grid that changes the meaning of every number after it, and at date
   size in body brown it disappeared into the number beside it. One cell in thirty carries it, so the
   accent stays well inside its share of the palette. */
.admin-calendar-mon {
    font-family: var(--rbmh-heading-font);
    font-size: 0.9rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--rbmh-terracotta);
    margin-right: 0.3rem;
}
/* A hairline down the left of the cell, so the turn of the month is visible when scanning the grid rather
   than only when reading that one cell. */
.admin-calendar-day.is-month-start {
    box-shadow: inset 3px 0 0 0 var(--rbmh-terracotta);
}
.admin-calendar-day.is-today .admin-calendar-dom {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.75rem;
    height: 1.75rem;
    padding: 0 0.4rem;
    border-radius: 0.875rem;
    background-color: var(--rbmh-olive);
    color: #fff;
    font-weight: 600;
}

/* What a day is carrying. One line per thing, truncated — the person is what you scan a month grid for,
   and the full wording is on the title/aria-label. The tinted fill and the bar down the left are the same
   colours the roster tints its rows with, so the two screens agree without a palette of their own. */
.admin-calendar-event {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.7rem;
    line-height: 1.35;
    padding: 0.05rem 0.25rem;
    border-radius: 0.2rem;
    border-left: 3px solid transparent;
    text-decoration: none;
    color: inherit;
}
.admin-calendar-event:hover,
.admin-calendar-event:focus-visible {
    text-decoration: underline;
    filter: brightness(0.96);
}
/* The marker colours, shared with the notifications panel beside the grid so the same thing can't end up
   two different colours on one screen. */
.admin-calendar-event.is-pending,
.admin-calendar-event.is-expiring,
.admin-notice.is-pending,
.admin-notice.is-expiring {
    background-color: var(--bs-warning-bg-subtle);
    border-left-color: var(--bs-warning);
}
.admin-calendar-event.is-expired,
.admin-notice.is-expired {
    background-color: var(--bs-danger-bg-subtle);
    border-left-color: var(--bs-danger);
}
.admin-calendar-event.is-scheduled,
.admin-notice.is-scheduled {
    background-color: var(--bs-secondary-bg-subtle);
    border-left-color: var(--bs-secondary);
}
/* Somebody's own Google calendar (migration 084), on the grid only — an appointment is not a thing falling
   due, so it never reaches the notifications panel. Off the urgency scale like the ticket colour below, and
   quieter still: a dashed edge and the muted foreground say "context around the practice's dates" without
   competing with the three states above for attention. It is also the one marker on the screen that is
   personal to whoever is reading, which is a reason to make it look less official, not more. */
.admin-calendar-event.is-google {
    background-color: var(--bs-tertiary-bg);
    border-left-style: dashed;
    border-left-color: var(--bs-secondary-border-subtle);
    color: var(--bs-secondary-color);
}
/* The occurrences Google gave no link to are rendered as spans, so they must not offer the affordances of
   the anchors beside them. */
span.admin-calendar-event {
    cursor: default;
}
span.admin-calendar-event:hover {
    text-decoration: none;
    filter: none;
}
/* Ticket news, in the panel only — nothing here falls due, so it never reaches the grid. Brand sage rather
   than another of Bootstrap's states: the three above are a scale of urgency, and this is not on it. */
.admin-notice.is-ticket {
    background-color: var(--rbmh-sage-soft);
    border-left-color: var(--rbmh-olive);
}
/* Seven columns don't get narrower on a phone, so the markers do. */
@media (max-width: 34rem) {
    .admin-calendar-day {
        min-height: 4rem;
        padding: 0.2rem;
    }
    .admin-calendar-event {
        font-size: 0.6rem;
        border-left-width: 2px;
    }
}

/* ---- Overview: notifications panel beside the calendar ----
   Three tenths to the panel, seven to the grid. The old calendar was capped at 60rem and still is in
   effect — 70% of 86rem — so adding the panel widens the page rather than squeezing the month.
   align-items: start keeps the panel its own height instead of stretching to the grid's. */
.admin-overview {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 7fr);
    align-items: start;
    gap: 1rem;
    max-width: 86rem;
}
/* A 30% column is unreadable on a narrow screen, so the two stack — panel first, since a list survives
   being narrow better than a seven-column grid does. */
@media (max-width: 62rem) {
    .admin-overview {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Tall months scroll inside the panel rather than dragging the page down past the calendar. The scroller
   wraps both groups, so past due and coming up share one scrollbar and the second can't hide below a first
   that scrolls on its own. */
.admin-notice-groups {
    max-height: 32rem;
    overflow-y: auto;
}
.admin-notice-list {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

/* ---- Past due, and the rest ----
   Two headed groups off one list (see IndexModel.PastDue). The heading sticks to the top of the scroller
   because a row on its own doesn't say which half it is in; the card's own background sits behind it so
   entries pass underneath rather than through it. */
.admin-notice-group + .admin-notice-group {
    margin-top: 0.85rem;
}
/* The applications line above the dated groups: an inbox count, not a calendar marker, so it sits
   apart from them behind a rule rather than joining the list. */
.admin-notice-inbox {
    color: var(--bs-body-color);
    font-size: 0.85rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--rbmh-hairline);
}
.admin-notice-inbox:hover { color: var(--rbmh-olive-dark); }
/* Each inbox line keeps its own hairline, so a stack of them reads as a short list and the last rule
   still separates the block from the dated groups below. Only the gap above a follower is new. */
.admin-notice-inboxes .admin-notice-inbox + .admin-notice-inbox { padding-top: 0.75rem; }

.admin-notice-group-head {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.4rem;
    padding: 0.15rem 0 0.3rem;
    background-color: var(--bs-card-bg, #fff);
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
/* The one place on this screen allowed to shout, and only when there is something to shout about. */
.admin-notice-group.is-past-due .admin-notice-group-head {
    color: var(--bs-danger-text-emphasis);
}
.admin-notice-group-head .badge {
    font-size: 0.65rem;
    letter-spacing: 0;
}
/* How late, on the end of the date line: quieter than the person's name, loud enough to rank by. */
.admin-notice-late {
    color: var(--bs-danger-text-emphasis);
    font-weight: 700;
}
.admin-notice-late::before {
    content: "· ";
}
/* Same tint and left bar as the grid's markers (colours above), with the room a list has and the grid
   hasn't: the date, the person, and what it is, on three lines instead of a tooltip. */
.admin-notice {
    display: block;
    padding: 0.4rem 0.55rem;
    border-radius: 0.25rem;
    border-left: 3px solid transparent;
    text-decoration: none;
    color: inherit;
}
.admin-notice:hover,
.admin-notice:focus-visible {
    filter: brightness(0.96);
}
.admin-notice-when {
    display: block;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--rbmh-olive);
    font-variant-numeric: tabular-nums;
}
.admin-notice-who {
    display: block;
    font-weight: 600;
    color: var(--rbmh-brown);
}
.admin-notice:hover .admin-notice-who,
.admin-notice:focus-visible .admin-notice-who {
    text-decoration: underline;
}
/* The one line allowed to wrap — a document's category and file name is the long part, and clipping it
   would leave two entries on the same day looking identical. */
.admin-notice-detail {
    display: block;
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--bs-secondary-color);
    overflow-wrap: anywhere;
}

/* ---- Snoozing an entry (see IndexModel.OnPostSnoozeAsync) ----
   The "not now" sits in the entry's own top-right corner rather than in a column beside it, so the entry
   still spans the whole panel — a 30% column has no width to give away, and the file name on the detail
   line is what needs it.

   It has to be positioned rather than laid out: the entry is a single <a>, and a form cannot be nested
   inside a link. So the row is the positioning context and the control is placed over the corner of the
   card. Room is reserved for it on the two lines it can reach (see below) instead of on the anchor, which
   would indent the wrapping detail line for no reason. */
.admin-notice-row {
    position: relative;
}
.admin-notice-row > form {
    position: absolute;
    top: 0.3rem;
    right: 0.4rem;
    /* Above the entry it sits on, or the link swallows the click meant for the menu. */
    z-index: 1;
    margin: 0;
}
/* The two lines the control's corner can reach. The detail line below it keeps the full width. */
.admin-notice-row > .admin-notice .admin-notice-when,
.admin-notice-row > .admin-notice .admin-notice-who {
    padding-right: 5.25rem;
}
/* Quiet until wanted. A select per row would otherwise be the loudest thing on a panel whose whole job is
   ranking what is urgent, so it sits back in the secondary colour with no fill and comes forward on hover
   or focus. Sized to its content rather than left to fill. */
.admin-notice-snooze .form-select {
    width: auto;
    padding: 0.05rem 1.3rem 0.05rem 0.35rem;
    background-position: right 0.25rem center;
    background-size: 0.65rem;
    font-size: 0.7rem;
    line-height: 1.3;
    color: var(--bs-secondary-color);
    background-color: transparent;
    border-color: transparent;
}
.admin-notice-snooze .form-select:hover,
.admin-notice-snooze .form-select:focus {
    color: var(--rbmh-brown);
    background-color: var(--bs-body-bg);
    border-color: var(--rbmh-hairline);
}

/* The closed group at the foot of the panel. Separated by a rule rather than a heading: it is not a third
   priority below "coming up", it is the same list with the sound turned off. */
.admin-notice-snoozed {
    margin-top: 0.85rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--rbmh-hairline);
}
.admin-notice-snoozed > summary {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.admin-notice-snoozed > summary .badge {
    font-size: 0.65rem;
    letter-spacing: 0;
}
.admin-notice-snoozed[open] > summary {
    margin-bottom: 0.5rem;
}
/* Wake sits in the same corner the snooze menu came from, and is drawn to the same weight — it is the one
   control that undoes the other, so it should not arrive as a heavier button than the one that got here. */
.admin-notice-snoozed .admin-notice-row > form .btn {
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    line-height: 1.3;
    color: var(--bs-secondary-color);
    border-color: transparent;
}
.admin-notice-snoozed .admin-notice-row > form .btn:hover,
.admin-notice-snoozed .admin-notice-row > form .btn:focus-visible {
    color: var(--rbmh-brown);
    background-color: var(--bs-body-bg);
    border-color: var(--rbmh-hairline);
}
/* Wake is a narrower word than the snooze menu, and the date line here is carrying a wake-up time as well
   as a date — so it gets its width back rather than keeping a gutter sized for something else. */
.admin-notice-snoozed .admin-notice-row > .admin-notice .admin-notice-when,
.admin-notice-snoozed .admin-notice-row > .admin-notice .admin-notice-who {
    padding-right: 3.5rem;
}
/* Asleep, and reading as it. The tint and left bar an entry carries are about how urgent it is, and it is
   not urgent while it is snoozed — the colour comes back with the entry. */
.admin-notice-snoozed .admin-notice {
    opacity: 0.65;
    filter: grayscale(1);
}
.admin-notice-snoozed .admin-notice:hover,
.admin-notice-snoozed .admin-notice:focus-visible {
    opacity: 1;
}
/* When it comes back, and — on a ticket — who changed it: the end of the date line, same slot as "how
   late", deliberately not the same voice. Nothing here is shouting. */
.admin-notice-wakes,
.admin-notice-by {
    color: var(--bs-secondary-color);
    font-weight: 600;
}
.admin-notice-wakes::before,
.admin-notice-by::before {
    content: "· ";
}

/* ---- Website editor: a framed run of fields (see Admin/Website.cshtml) ----
   A run of copy fields that makes up one piece of the live page — the Contact page's message form,
   say — is drawn as a sage-tinted panel behind an olive edge, so it stands out from the loose SEO,
   hero and closing fields around it. There is no wrapper element: the head and the rows carry the
   same tint and edge and no gap between them, so they abut into one panel while the editor's flow
   stays exactly as the catalog orders it. */
.admin-field-group__head,
.admin-field-group__row {
    background-color: var(--rbmh-sage-soft);
    border-left: 3px solid var(--rbmh-olive);
    padding: 0.9rem 1.15rem;
}
.admin-field-group__head {
    padding-top: 1rem;
    border-top-left-radius: var(--rbmh-card-radius);
    border-top-right-radius: var(--rbmh-card-radius);
}
/* Same quiet uppercase label the dashboard's group heads use. */
.admin-field-group__title {
    display: block;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--rbmh-olive-dark);
}
.admin-field-group__note {
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}
/* The last row closes the panel and carries the bottom margin (.mb-4) the loose fields have. */
.admin-field-group__row--last {
    padding-bottom: 1.15rem;
    margin-bottom: 1.5rem;
    border-bottom-left-radius: var(--rbmh-card-radius);
    border-bottom-right-radius: var(--rbmh-card-radius);
}

/* The website editor's "Edit on page" tab: the same /Admin/Preview render the button opens, framed
   in the pane. It is a whole page in there, so it takes the height the viewport allows and scrolls
   inside its own frame rather than stretching this one to the page's length. */
.admin-preview-frame {
    display: block;
    width: 100%;
    height: calc(100vh - 15rem);
    min-height: 30rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--rbmh-card-radius);
    background: var(--bs-body-bg);
}

/* ---- The Website landing screen's tiles (_WebsiteHome) ----
   Bootstrap cards with a stretched-link heading; all this adds is the lift on hover that says the whole
   card is the target, and the disc the leading glyph sits on. */
.admin-tile {
    border-color: var(--rbmh-border-soft);
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.admin-tile:hover,
.admin-tile:focus-within {
    border-color: rgba(var(--rbmh-olive-rgb), .45);
    box-shadow: 0 .25rem .75rem rgba(var(--rbmh-brown-rgb), .07);
}
.admin-tile__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--rbmh-sage-soft);
    color: var(--rbmh-olive-dark);
    font-size: .9rem;
    line-height: 1;
}

/* ---- The colour-theme picker (/Admin/Website/Theme) ----
   Every card carries that theme's palette as custom properties on itself (style="…"), so the swatches and
   the little page fragment inside it are painted by the same properties the live site is — the card IS the
   theme rather than a picture of one. Which is why nothing below names a colour: it all reads through
   --rbmh-*, and only the card's own chrome (the border, the radio, the name) uses the admin's colours. */
.theme-picker {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
}
.theme-card {
    display: block;
    padding: 1rem 1.1rem 1.15rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--rbmh-card-radius);
    background: var(--bs-body-bg);
    cursor: pointer;
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.theme-card:hover { border-color: rgba(var(--rbmh-brown-rgb), .35); }
/* The chosen card is marked by a ring rather than by a colour of its own, which any theme could clash
   with — the ring is drawn in that card's own primary. */
.theme-card.is-chosen {
    border-color: var(--rbmh-olive);
    box-shadow: 0 0 0 .15rem rgba(var(--rbmh-olive-rgb), .35);
}
.theme-card:focus-within { box-shadow: 0 0 0 .25rem rgba(var(--rbmh-olive-rgb), .25); }
.theme-card__choice {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: .35rem;
}
.theme-card__name { font-weight: 600; }
.theme-card__note {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}
.theme-card__description {
    display: block;
    font-size: .875rem;
    color: var(--bs-secondary-color);
    margin-bottom: .75rem;
}

/* The palette itself. Also used on the landing screen, under the tiles. */
.theme-swatches {
    display: inline-flex;
    border-radius: 999px;
    overflow: hidden;
    border: 1px solid var(--rbmh-hairline);
}
.theme-swatch {
    display: block;
    width: 2rem;
    height: 1.1rem;
}

/* A page in miniature: heading, copy, the call-to-action, a link, a soft panel. */
.theme-preview {
    display: block;
    margin-top: .75rem;
    padding: .9rem 1rem 1rem;
    border-radius: calc(var(--rbmh-card-radius) - .2rem);
    background: var(--rbmh-bg);
    border: 1px solid var(--rbmh-hairline);
}
.theme-preview__title {
    display: block;
    font-family: var(--rbmh-heading-font);
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1.3;
    color: var(--rbmh-brown);
}
.theme-preview__copy {
    display: block;
    margin-top: .3rem;
    font-size: .8rem;
    color: rgba(var(--rbmh-brown-rgb), .8);
}
.theme-preview__row {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-top: .7rem;
}
.theme-preview__cta {
    display: inline-block;
    padding: .3rem .8rem;
    border-radius: var(--rbmh-pill-radius);
    background: var(--rbmh-terracotta-dark);
    color: #fff;
    font-size: .7rem;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.theme-preview__link {
    font-size: .8rem;
    color: var(--rbmh-olive-dark);
    text-decoration: underline;
}
.theme-preview__panel {
    display: block;
    margin-top: .7rem;
    padding: .5rem .7rem;
    border-radius: calc(var(--rbmh-card-radius) - .35rem);
    border-left: 3px solid var(--rbmh-olive);
    background: var(--rbmh-sage-soft);
    font-size: .78rem;
    color: rgba(var(--rbmh-brown-rgb), .85);
}

/* ---- A modal that frames another admin page (see _AdminModalLayout) ----
   The framed page is as tall as it is, so the dialog takes the height the viewport allows and lets the
   frame scroll inside it — modal-dialog-scrollable can't, since it scrolls the body around the frame. */
/* The modal is the frame; the page inside it only needs breathing room. */
.admin-modal-body { background: var(--bs-body-bg); }
.modal-frame .modal-dialog {
    height: calc(100% - var(--bs-modal-margin) * 2);
}
.modal-frame .modal-content {
    height: 100%;
}
.modal-frame .modal-body {
    padding: 0;
    overflow: hidden;
}
.modal-frame iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}
/* A second frame modal opened from inside the first (the login editor over the therapist editor). It is the
   same size and carries no backdrop of its own, so it lands exactly on the one below and reads as the same
   modal showing something else. Bootstrap gives every modal the same z-index, which would leave the two
   depending on markup order alone. */
.modal-stacked {
    --bs-modal-zindex: 1065;
}
/* A modal opened by a framed page — the statement the pay-run grid's PDF button shows, and the same one on
   a therapist's Payroll tab. It lives inside the iframe, whose viewport is only as wide as the modal doing
   the framing, so Bootstrap's modal-xl never reaches its widest step and draws a narrow box floating in the
   middle of the modal that opened it. Filling the frame instead lands it on the modal below at the same
   width, the way .modal-stacked does for a second framed page. */
.admin-modal-body #payroll-statement-modal .modal-dialog {
    max-width: none;
    width: 100%;
    height: 100%;
    margin: 0;
}
.admin-modal-body #payroll-statement-modal .modal-content {
    height: 100%;
    border: 0;
    border-radius: 0;
}

/* ---- Ticket board (_TicketBoard + tickets-board.js, both trackers) ---- */
.ticket-board { display: flex; gap: .75rem; overflow-x: auto; padding-bottom: .5rem; }
/* Columns share the full width equally, but never shrink below a readable card width
   (the board scrolls horizontally instead on narrow screens). */
.ticket-col { flex: 1 1 0; min-width: 16rem; }
.col-cards { min-height: 4rem; border-radius: .5rem; padding: .15rem; transition: background-color .15s; }
.ticket-col.drop-target .col-cards { background-color: var(--bs-primary-bg-subtle); outline: 2px dashed var(--bs-primary-border-subtle); }
.ticket-card { cursor: grab; }
.ticket-card.dragging { opacity: .45; }
.ticket-card .drag-dots { cursor: grab; color: var(--bs-secondary-color); letter-spacing: -1px; }
