/* River Bluff Mental Health — Bootstrap 5.3 theme layer: the SHARED half.
   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.

   This file is loaded by every layout — the public site, both signed-in portals, and the framed
   modal layout — and holds only what all of them use: the tokens, the type ramp, the focus ring,
   the button variants, the footer, the form chrome, and the card/medallion polish.

   The two halves that are NOT shared live beside it and are loaded by whoever needs them:
     public-pages.css   the marketing site's page-specific blocks (heroes, Team, Services, Paying,
                        Careers, Contact) — _Layout only
     portal.css         the admin/platform backend — _PortalShell and _AdminModalLayout only

   Why it is split: this file was one 99 KB stylesheet, and roughly half of it was public marketing
   CSS that every admin page downloaded and never used. Order is preserved exactly as it was within
   each half, and the shared half loads first, so the cascade is unchanged. Before moving a rule
   between the three, check it isn't relied on by the other side. */

: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. */

    /* The foreground that sits ON a filled brand surface — a button's label, a glyph inside a
       filled disc, a focus ring drawn against the dark footer. It is the other half of every
       ratio the rule above quotes ("white on terracotta-dark 4.65:1"), and it was the one value
       in the palette still written as a literal #fff in ~20 places across the two brands.
       Named for its job rather than its colour, so a scheme whose accent goes pale can flip it
       to a dark ink in one declaration instead of hunting white through four files. */
    --rbmh-on-accent: #fff;

    /* 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, the larger corner the full-width
       panels share, 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-panel-radius: 1rem;
    --rbmh-pill-radius: 1.875rem;

    /* Muted body text: brown pulled back to four-fifths. This was restated as a literal rgba()
       in ~15 places across public-pages.css, with the alpha drifting .75-.85 by accident along
       the way — one token holds the one decision. Follows a theme automatically, since the
       channels above are re-declared per scheme (SitePalettes). */
    --rbmh-text-muted: rgba(var(--rbmh-brown-rgb), .8);

    /* The cookie notice's tint (css/cookie-banner.css reads these): the footer's charcoal so the
       strip reads as chrome, sage for its link and button edge. All three reference brand tokens,
       so a chosen palette repaints the banner with everything else. */
    --cookie-bg: var(--rbmh-charcoal);
    --cookie-ink: var(--rbmh-on-accent);
    --cookie-link: var(--rbmh-sage);

    /* The password field's show/hide control (css/password-reveal.css reads these): muted brown
       like the body text it sits beside, warming to terracotta on hover and focus. */
    --pw-reveal-ink: var(--rbmh-text-muted);
    --pw-reveal-ink-active: var(--rbmh-terracotta);
    --pw-reveal-hover-bg: rgba(var(--rbmh-brown-rgb), .06);
    --pw-reveal-focus-ring: rgba(var(--rbmh-terracotta-rgb), .35);

    /* ---- 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 portals reach it too — _PortalShell
   wraps a non-FullWidth page in .container — which is why this lives in the shared half rather
   than in public-pages.css. (An earlier note here claimed the admin layouts don't use .container;
   they do, and have since the shared shell landed.) */
@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;
    }
}

/* ---- Skip link ----
   The first tab stop on every page, so a keyboard-only user can reach the content without walking
   the header. The public header alone is nine stops (brand, seven nav links, the portal button) and
   it repeats on every page; the portals put the nav rail in the same position.

   Only the *appearance* is here. The hide-until-focused mechanism is Bootstrap's own
   .visually-hidden-focusable, which the markup carries alongside this class — it clips the link to
   1px with !important while it is neither focused nor focus-within, and stops applying the moment it
   takes focus, at which point the rules below are what is left. Reusing it rather than restating the
   clip means there is no second copy of that technique to keep right.

   z-index clears .main-navbar's 1030, which is sticky and would otherwise be painted over the link
   on a scrolled page. _AdminModalLayout deliberately has no skip link: its <main> is the first thing
   in the body, so there is nothing to skip. */
.skip-link {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1040;
    margin: 0.5rem;
    padding: 0.7rem 1.15rem;
    background-color: var(--rbmh-bg);
    color: var(--rbmh-olive-dark);
    font-weight: 700;
    border-radius: var(--rbmh-pill-radius);
    box-shadow: 0 0.5rem 1.5rem rgba(var(--rbmh-brown-rgb), .18);
}

/* ---- 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: var(--rbmh-on-accent); }

/* The skip link's landing site. <main> carries tabindex="-1" so that following "#main" actually
   MOVES focus rather than only scrolling — without it the browser leaves document.activeElement on
   <body>, and the next Tab is left to the sequential-focus-starting-point rules, which screen
   readers have never handled consistently. It is the same reason _ValidationSummary is tabindex="-1"
   (see site.js).
   That attribute makes it match the [tabindex] arm of the ring above, which would then draw a 3px
   outline around the entire content area of the page. Suppressed here rather than by narrowing the
   ring's selector, because every OTHER [tabindex] element should keep it. Losing the indicator is
   safe in this one case and nowhere else: <main> is never in the tab order, so it can only be
   focused by following the skip link — an action whose result the user just asked for and can see,
   because the page scrolled to it. */
main[tabindex="-1"]:focus,
main[tabindex="-1"]:focus-visible { outline: none; }

/* ---- 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: var(--rbmh-on-accent);
    --bs-btn-hover-color: var(--rbmh-on-accent);
    --bs-btn-active-color: var(--rbmh-on-accent);
    --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: var(--rbmh-on-accent);
    --bs-btn-active-bg: var(--rbmh-olive);
    --bs-btn-active-border-color: var(--rbmh-olive);
    --bs-btn-active-color: var(--rbmh-on-accent);
}
/* 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: var(--rbmh-on-accent);
    --bs-btn-active-bg: var(--rbmh-olive);
    --bs-btn-active-border-color: var(--rbmh-olive);
    --bs-btn-active-color: var(--rbmh-on-accent);
}
/* 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: var(--rbmh-on-accent);
    --bs-btn-hover-color: var(--rbmh-on-accent);
    --bs-btn-active-color: var(--rbmh-on-accent);
}

/* ---- 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: var(--rbmh-on-accent);
}
.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; }

/* Social marks under the blurb. Icon-only, so each link carries its own aria-label and gets a
   44px target; the tile inherits the footer's link colour and goes gold on hover like every
   other link down here. */
.footer-social {
    list-style: none;
    display: flex;
    gap: 0.35rem;
    /* The negative left margin pulls the first glyph's tap target back so the mark itself lines
       up with the blurb above it rather than sitting indented by its own padding. */
    margin: 0.85rem 0 0 -0.7rem;
    padding: 0;
}
.footer-social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
}
.footer-social a:hover { text-decoration: none; }
.footer-social__icon {
    width: 1.35rem;
    height: 1.35rem;
}

/* 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; }
/* Text a person typed into a public form, shown back in the portal (a contact message, a job
   application). pre-line, not pre-wrap: their paragraph breaks are worth keeping, but the leading
   whitespace of a pasted-in message is not, and neither is markup — the value is HTML-encoded on the
   way out either way. Beside .text-prewrap because the two are one decision apart. */
.text-preline { white-space: pre-line; }
/* 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; }

/* ---- 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: var(--rbmh-on-accent); }

/* ---- 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);
}

/* ---- Reduced motion ----
   Bootstrap guards its own components; this covers ours. To be accurate about what it is doing
   today: the only actual *movement* in this stylesheet is .card-hover's 3px lift, which every
   therapist and service card carries. The rest of the transitions in the shared and portal sheets
   are colour fades, which this rule also stills but which were never the concern.

   So this is written as a blanket rather than as one rule about .card-hover on purpose: it costs the
   same, and it means the next transition added anywhere the portals or the practice site load is
   covered without whoever adds it having to know this exists. Transition and animation are set to a
   near-zero duration rather than `none` so that anything relying on a transitionend/animationend
   event still fires. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    /* The lift itself, which a duration alone would only make instant rather than absent. */
    .card-hover:hover { transform: none; }
}
