:root {
    --color-bg: #121212;
    --color-bg-alt: color-mix(in srgb, var(--color-bg) 87%, white);
    --color-accent: #0d6efd;
    --color-accent-hover: color-mix(in srgb, var(--color-accent) 80%, black);
    --color-text: #f5f5f5;
    --color-text-muted: #adb5bd;
    --color-heading: #ffffff;
    --color-nav-bg: #212529;
    --color-nav-text: #f8f9fa;
    --color-card-bg: color-mix(in srgb, var(--color-bg) 90%, white);
    --color-border: color-mix(in srgb, var(--color-bg) 72%, white);
    --font-heading: 'Bebas Neue', sans-serif;
    --font-body: 'Lato', sans-serif;

    /* The accent, pulled far enough toward the palette's own heading colour to
       be legible as TEXT. --color-accent alone is not safe for type: an accent
       chosen as a button fill can be anything, and HolyLOL's #ffd028 on its
       #f6f4ef paper is 1.34:1.

       Blending toward --color-heading works at any palette because the heading
       colour is by definition the far end from the background — on a dark site
       it lightens the accent, on a light site it darkens it, and either way it
       moves away from the ground. 45% keeps the hue clearly recognisable while
       clearing 4.5:1 on every design style we ship (measured: 4.8 on HolyLOL's
       paper, 9.8 dark_studio, 11.8 clean_light).

       Use this for accent-coloured text, and for accent FILLS pair it with
       color: var(--color-bg) — the fill has moved away from the background, so
       background-coloured text on it contrasts by construction. */
    --color-accent-readable: color-mix(in srgb, var(--color-accent) 45%, var(--color-heading));
}

body {
    font-family: var(--font-body);
    background-color: var(--color-bg);
    color: var(--color-text);
    padding-top: 56px;
}

/* Landing Page Options: header style "hidden" — no fixed navbar to offset. */
body.no-fixed-nav {
    padding-top: 0;
}

h1,
h2,
h3,
h4,
h5,
h6,
.navbar-brand {
    font-family: var(--font-heading);
    color: var(--color-heading);
    letter-spacing: 1px;
}

/* Full-height section background ("hero style") — a general per-section
   option (see site/page_builder_render.php's renderSectionBackgroundWrap()),
   not tied to any specific image. The background itself (color/gradient/
   image) is applied as an inline style by the renderer, not by this class. */
.pb-hero {
    height: 100vh;
    background-position: top center;
    background-repeat: no-repeat;
    background-size: cover;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
}

/* Headings inside a hero must follow .pb-hero's forced white, not the design
   style's heading colour. Every light design style (clean_light, bold_editorial,
   professional) emits a bare `h1,h2,...{color:var(--color-heading)}` rule from
   getThemeStyleBlock(), which beats the inherited colour on specificity and left
   every full-height hero headline near-black on a dark gradient. */
.pb-hero h1,
.pb-hero h2,
.pb-hero h3,
.pb-hero h4,
.pb-hero h5,
.pb-hero h6 {
    color: #fff;
}

.pb-hero-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    /* Default 40% overlay for legacy sections (no inline style) — new-shape
       sections always set their own overlay opacity via inline style, which
       overrides this. */
    background-color: rgba(0, 0, 0, 0.4);
    z-index: 1;
}

.pb-hero-inner {
    text-align: center;
    position: relative;
    z-index: 2;
    padding: 20px;
}


.pb-hero-inner h1 {
    /* Fluid rather than the old two-step (4rem, dropping to 2.8rem under
       768px). 2.8rem is 44.8px, which on a 393px phone is wide enough that a
       single long word in a headline -- "[Neighbourhood]," in the Service+City
       template, a real city name in a tenant's own -- spilled outside its box.
       The clamp caps at the same 4rem, so desktop is unchanged; break-word is
       the backstop for a word too long for any size. */
    font-size: clamp(2.1rem, 7.5vw, 4rem);
    overflow-wrap: break-word;
    font-weight: 700;
    /* Ensure boldness if needed */
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
    /* Text shadow for readability */
}

.pb-hero-inner p {
    font-size: 1.5rem;
    /* Responsive font size */
    font-family: var(--font-body);
    font-weight: 300;
    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
}

/* Navbar */
.navbar {
    transition: background-color 0.3s ease;
}

.navbar-brand {
    font-size: 1.5rem;
    /* Adjust brand size if needed */
}

.nav-link {
    font-family: var(--font-body);
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.9rem;
    letter-spacing: 0.5px;
}


/* Sections */
section {
    scroll-margin-top: 56px;
    /* Offset scroll position for fixed navbar */
}

.lead {
    font-weight: 300;
    /* Lighter lead paragraph */
    font-size: 1.1rem;
}

/* About Me Section Images */
#about img {
    transition: transform 0.3s ease;
}

#about img:hover {
    transform: scale(1.05);
}

/* Digital Strategy Services Section */
#services {
    background-color: var(--color-bg);
}

#services h4 {
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 1.2rem;
    color: var(--color-text);
}

#services p.text-white-50 { /* Adjust if section ID changed */
    font-size: 0.95rem;
}

/* Projects Section */
#projects {
    background-color: var(--color-bg-alt);
}

.projects-item {
    opacity: 0;
    transform: scale(1);
    transition: opacity 0.4s ease-in-out;
    pointer-events: none;
    display: none;
}

.projects-item.is-visible {
    opacity: 1;
    pointer-events: auto;
    display: block;
}

.projects-item.is-hiding {
    opacity: 0;
    pointer-events: none;
    display: block;
}


/* Projects Filter Buttons */
#projects-filter-buttons .btn {
    font-family: var(--font-body);
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.85rem;
    letter-spacing: 0.5px;
    transition: background-color 0.3s ease, color 0.3s ease;
}


/* Projects Cards */
.card {
    border: 1px solid var(--color-border);
    background-color: var(--color-card-bg);
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    overflow: hidden;
}

.card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
}

/* Bootstrap components bound to the site palette.
   .card was already themed above, but its header and any list-group inside it
   were not — so they kept Bootstrap's own light-grey defaults regardless of
   the chosen design style. Templates worked around that by hardcoding
   `bg-dark text-white`, which looked passable on the dark_studio baseline and
   broke on every light palette. These rules are what let those templates drop
   the hardcoded colours; do not reintroduce them. */
.card-header {
    background-color: var(--color-bg-alt);
    color: var(--color-heading);
    border-bottom: 1px solid var(--color-border);
}

.list-group-item {
    background-color: transparent;
    color: var(--color-text);
    border-color: var(--color-border);
}

.list-group-item-action:hover,
.list-group-item-action:focus {
    background-color: var(--color-bg-alt);
    color: var(--color-heading);
}

/* An outline button that follows the accent colour instead of assuming a dark
   background the way .btn-outline-light does.

   The accent is the BORDER, never the label. My first version made the label
   --color-accent, on the reasoning that a palette author must already have got
   the accent readable for links. That is not true of an accent meant to be a
   button *fill*: HolyLOL's #ffd028 on its #f6f4ef paper is 1.34:1, and the
   Tickets button came out all but invisible. --color-heading against
   --color-bg is the one pair a palette can be relied on to get right, so the
   text uses that and the accent carries the colour on the border.

   Hover tints the ground rather than filling with the accent, for the same
   reason: a fill needs a label colour that contrasts with the accent, which
   CSS cannot work out. A 15% tint barely moves the luminance, so the heading
   colour stays readable on it at any palette. */
.btn-theme-outline {
    --bs-btn-color: var(--color-heading);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-hover-bg: color-mix(in srgb, var(--color-accent) 15%, var(--color-bg));
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-hover-color: var(--color-heading);
    --bs-btn-active-bg: color-mix(in srgb, var(--color-accent) 25%, var(--color-bg));
    --bs-btn-active-border-color: var(--color-accent);
    --bs-btn-active-color: var(--color-heading);
}

/* The primary call to action — a filled accent button, the way the vertical
   templates draw their own CTAs. The label comes from --color-accent-contrast,
   which site/settings.php computes by actually measuring contrast against the
   accent and picking the palette's readable end; CSS cannot do that, which is
   why .btn-theme-outline settles for a border instead.

   Hover dims the whole button rather than swapping in --color-accent-hover:
   that colour is chosen to read against the *page*, not to carry the label. On
   HolyLOL it is a dark gold, and the ink label sits at 2.4:1 on it. Dimming
   moves background and text together, so whatever contrast was computed
   survives the hover at any palette. */
.btn-theme-fill {
    --bs-btn-bg: var(--color-accent);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-color: var(--color-accent-contrast);
    --bs-btn-hover-bg: var(--color-accent);
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-hover-color: var(--color-accent-contrast);
    --bs-btn-active-bg: var(--color-accent);
    --bs-btn-active-border-color: var(--color-accent);
    --bs-btn-active-color: var(--color-accent-contrast);
    font-weight: 600;
    transition: filter .15s ease;
}

.btn-theme-fill:hover,
.btn-theme-fill:focus-visible {
    filter: brightness(0.92);
}

/* Solid counterpart, for secondary navigation like prev/next. */
.btn-theme {
    --bs-btn-bg: var(--color-bg-alt);
    --bs-btn-border-color: var(--color-border);
    --bs-btn-color: var(--color-text);
    /* Same reasoning as .btn-theme-outline above — tint, don't fill. */
    --bs-btn-hover-bg: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg-alt));
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-hover-color: var(--color-heading);
}

/* Themed stand-ins for text-white / text-white-50, which are only correct on
   a dark palette. */
.text-theme-muted { color: var(--color-text-muted) !important; }
.text-theme        { color: var(--color-text) !important; }
.text-theme-heading { color: var(--color-heading) !important; }

/* Placeholder block shown when a gig has no poster image. */
.gig-image-placeholder {
    background-color: var(--color-bg-alt);
    border: 1px solid var(--color-border);
    min-height: 300px;
}

.projects-card-img {
    height: 250px;
    object-fit: cover;
    width: 100%;
}

/* Modal Styling */
.modal-content {
    border: none;
}

.modal-header,
.modal-footer {
    border-color: rgba(255, 255, 255, 0.2) !important;
}

.modal-link:hover {
    color: var(--color-accent-hover) !important;
    text-decoration: underline !important;
}

.modal-link-button:hover {
    /* Optional hover for modal buttons */
}

/* Contact Section */
#contact label {
    font-family: var(--font-body);
    color: var(--color-text);
}

.contact-link:hover {
    color: var(--color-accent-hover) !important;
}

/* Themed navbar */
.navbar.bg-dark {
    background-color: var(--color-nav-bg) !important;
}
.navbar-dark .navbar-nav .nav-link,
.navbar-dark .navbar-brand {
    color: var(--color-nav-text) !important;
}
.navbar-dark .navbar-nav .nav-link:hover,
.navbar-dark .navbar-nav .nav-link:focus {
    color: var(--color-accent-hover) !important;
}

/* Footer */
/* Site footer. Was `footer { background-color: #000000 }` plus a hardcoded
   `bg-black text-white` on the element itself, which is why every light design
   style had to carry a `footer{...!important}` workaround in its own css. It
   now follows the palette, pairing with the nav so the two ends of the page
   match. Those per-style overrides are left in place deliberately: they still
   win, and several were tuned by hand. */
.site-footer {
    background-color: var(--color-nav-bg);
    color: var(--color-nav-text);
}

.site-footer a {
    color: var(--color-nav-text);
}
.site-footer-links .list-inline-item:not(:last-child) { margin-right: 1.1rem; }

.social-icon { /* Global social icon style */
    font-size: 1.8rem;
    color: var(--color-text-muted);
    margin: 0 0.5rem;
    transition: color 0.3s ease, transform 0.3s ease;
    display: inline-block;
}

.social-icon:hover {
    color: var(--color-accent-hover);
    transform: scale(1.2);
}


/* --- Thank You Page Styles (adjustments for content within .pb-hero-inner) --- */
body.thank-you-page .pb-hero-inner .thank-you-heading { /* Targets the H2 */
    font-size: 3.5rem; /* Or your preferred size, smaller than main hero H1 */
    /* text-shadow: 2px 2px 4px rgba(0,0,0,0.5); */ /* Inherits from .hero-text h1 if that style is broad */
    margin-bottom: 1.5rem;
}

body.thank-you-page .pb-hero-inner .thank-you-paragraph {
    font-size: 1.2rem;
    font-family: var(--font-body);
    max-width: 670px; /* Keep text from being too wide */
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 1.5rem; /* Spacing for paragraphs */
    /* text-shadow: 1px 1px 3px rgba(0,0,0,0.5); */ /* Inherits from .hero-text p if that style is broad */
}

body.thank-you-page .pb-hero-inner .social-icon { /* Adjust if needed */
    font-size: 2rem;
    margin: 0 0.75rem; /* Horizontal spacing */
    /* Bottom margin handled by parent div's mb-4 */
}

body.thank-you-page .pb-hero-inner .btn { /* For "Back to Homepage" button */
    margin-top: 1rem; /* Add some space above the button */
}

/* Media Queries */
@media (max-width: 767.98px) {
    /* .pb-hero-inner h1 is deliberately absent here: it is fluid above, and a
       fixed override at this breakpoint would beat the clamp and bring back
       the overflow it exists to prevent. */
    .pb-hero-inner p {
        font-size: 1.2rem;
    }

    .navbar-brand { /* Fix for navbar brand on mobile */
        font-size: 1.2rem;
    }

    /* Mobile stacking rules for projects-filter-buttons .btn-group were removed, which is correct for the flex-wrap solution */
}

/* Page Builder — public section backgrounds */
.pb-section {
    width: 100%;
    position: relative;
}
/* Overlay for a non-full-height section's color/gradient/image background
   (new per-section 'background' shape) — positioned behind the content, which
   sits in the plain .container that always follows it in the DOM. */
.pb-section-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
}
.pb-section > .container {
    position: relative;
    z-index: 2;
}
/* Legacy 'dark'/'black' section backgrounds — theme-aware: each theme in
   site/settings.php's getThemeStyleBlock() overrides these two class names
   with theme-appropriate colors. Kept permanently for already-published
   sections still on the old bg enum; new sections use an explicit inline
   color instead (see renderSectionBackgroundWrap() in page_builder_render.php). */
.pb-bg-dark  { background-color: #212529; }
.pb-bg-black { background-color: #000; }

/* ── Parallax image backgrounds ──────────────────────────────────────────────
   A section with background.parallax set renders its image on .pb-parallax-layer
   instead of on the section itself (renderSectionBackgroundWrap() in
   site/page_builder_render.php). z-index 0 keeps the layer under
   .pb-section-overlay (1) and the content (2), and under .pb-hero's own overlay,
   which follows it in the DOM.

   Travel budget: the layer is 50% taller than its section and overhangs it by
   25% of the section's height at each end. The drift below is ±15% of the layer's
   own height (percentage translations resolve against the element, not its
   parent) = ±22.5% of the section height, so the image travels just under half a
   section-height end to end — enough to read clearly as parallax — and still
   keeps 2.5% of overhang in hand at each extreme rather than spending the budget
   exactly, which would leave a hairline gap to sub-pixel rounding.

   Three tiers, best first:
     1. scroll-driven animation, where the browser has it (Chromium 115+,
        Safari 26+), including on phones;
     2. background-attachment: fixed for browsers that don't, but only where a
        fine pointer says it isn't a touch device — iOS and Android ignore or
        mangle fixed attachment, which is the whole reason for tier 1;
     3. a plain static cover image, for reduced-motion visitors and anything else.
   Every tier shows the same picture; only the motion differs. */
.pb-parallax {
    overflow: hidden;
}
.pb-parallax-layer {
    position: absolute;
    left: 0;
    right: 0;
    top: -25%;
    bottom: -25%;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    z-index: 0;
    will-change: transform;
}

@keyframes pb-parallax-drift {
    from { transform: translate3d(0, -15%, 0); }
    to   { transform: translate3d(0, 15%, 0); }
}

/* The drift is driven off the section's progress through the viewport, so it
   runs on the compositor — no scroll listener, and it works on mobile Safari and
   Chrome, which both ignore background-attachment: fixed.

   The timeline is *named on the section* rather than taken from the layer's own
   view(), because .pb-parallax's overflow:hidden makes the section a scroll
   container: an anonymous view() on the layer would measure it against that
   never-scrolling box and sit at 50% progress forever. Naming it on the section
   measures the section against the page instead, which is what we want. Each
   section defines the same name on itself, and a layer resolves it to its own
   ancestor, so sections don't interfere with each other. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .pb-parallax {
            view-timeline-name: --pb-parallax-section;
        }
        .pb-parallax-layer {
            animation: pb-parallax-drift linear both;
            animation-timeline: --pb-parallax-section;
            animation-range: cover 0% cover 100%;
        }
    }
}

/* Tier 2. Firefox has no animation-timeline yet, and neither does Safari before
   26, so those desktop visitors would otherwise get a static image. Pinning the
   layer's background to the viewport gives them the classic fixed-attachment
   parallax instead. Gated on a fine pointer because that technique is exactly
   what breaks on touch: iOS Safari mis-scales it and it judders against the
   collapsing URL bar. */
@supports not (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) and (pointer: fine) {
        .pb-parallax-layer {
            background-attachment: fixed;
        }
    }
}

/* Page Builder — YouTube element, portrait aspect ratio (Shorts/vertical video).
   Bootstrap's own .ratio-* set only ships 1x1/4x3/16x9/21x9 (see
   assets/vendor/bootstrap/bootstrap.min.css) — same --bs-aspect-ratio formula
   (height/width, as a percentage) as those, just inverted: 16/9 instead of 9/16. */
.ratio-9x16 { --bs-aspect-ratio: 177.7778%; }
/* Left at full column width, a portrait video would blow up to ~1.8x as tall
   as it is wide — cap it to a sane on-screen size, like a phone-preview box,
   instead of stretching edge-to-edge in a wide single-column section. */
.pb-ratio-portrait { max-width: 400px; margin-left: auto; margin-right: auto; }

/* Blog category sidebar tree (blog.php) */
.blog-cat-tree ul {
    padding-left: 1rem;
    margin-top: .25rem;
}
.blog-cat-tree li {
    margin-bottom: .15rem;
}
/* Theme-token colours for the category tree renderCategorySidebarTree draws
   in the blog sidebar. (The docs sidebar is site/docs.php's renderDocsNav.) */
.blog-cat-tree a           { color: var(--color-text-muted); }
.blog-cat-tree a:hover     { color: var(--color-accent-readable); }
.blog-cat-tree a.is-active { color: var(--color-heading); }
.blog-cat-tree .badge {
    background-color: var(--color-bg-alt);
    color: var(--color-text-muted);
    font-weight: 500;
}

/* Page Builder — code block element (public render) */
.pb-code-block {
    margin-bottom: 1rem;
    overflow-x: auto;
    border-radius: .375rem;
}

/* Page Builder — pricing table element (public render). Built entirely from
   the theme custom properties above (--color-*, set per-tenant by
   site/settings.php's generated :root block) rather than hardcoded colors,
   so it matches whatever palette a tenant has actually chosen. */
.pb-pricing-card {
    height: 100%;
    padding: 2rem 1.5rem;
    border-radius: .5rem;
    background-color: var(--color-card-bg);
    border: 1px solid var(--color-border);
    display: flex;
    flex-direction: column;
}
.pb-pricing-card-highlighted {
    border-color: var(--color-accent);
    border-width: 2px;
    box-shadow: 0 0 0 1px var(--color-accent);
}
.pb-pricing-name {
    font-size: 1.25rem;
    margin-bottom: .5rem;
}
.pb-pricing-price {
    font-size: 2rem;
    font-weight: 700;
    color: var(--color-heading);
    margin-bottom: .5rem;
}
.pb-pricing-period {
    font-size: 1rem;
    font-weight: 400;
    color: var(--color-text-muted);
    margin-left: .15rem;
}
.pb-pricing-description {
    color: var(--color-text-muted);
    margin-bottom: 1rem;
}
.pb-pricing-features {
    list-style: none;
    padding: 0;
    margin: 0 0 1.5rem;
    flex-grow: 1;
}
.pb-pricing-features li {
    padding: .35rem 0;
    border-bottom: 1px solid var(--color-border);
}
.pb-pricing-features li:last-child {
    border-bottom: none;
}
.pb-pricing-cta {
    width: 100%;
}

/* Page Builder — FAQ accordion element (public render). Bootstrap's own
   accordion classes handle the collapse behavior (already vendored, see
   assets/vendor/bootstrap/); these overrides just make it match the theme
   instead of Bootstrap's default light styling. */
.pb-faq-accordion .accordion-item {
    background-color: var(--color-card-bg);
    border: 1px solid var(--color-border);
}
.pb-faq-accordion .accordion-button {
    background-color: var(--color-card-bg);
    color: var(--color-heading);
}
.pb-faq-accordion .accordion-button:not(.collapsed) {
    background-color: var(--color-card-bg);
    /* Not a hover — this is an OPEN question, sitting there to be read. */
    color: var(--color-accent-readable);
    box-shadow: none;
}
.pb-faq-accordion .accordion-button::after {
    filter: invert(1) grayscale(1);
}
.pb-faq-accordion .accordion-body {
    color: var(--color-text-muted);
}

/* ============================================================================
   Nav (menu) styles
   ============================================================================
   Two independent axes, chosen site-wide in Settings → Design and applied by
   site/navigation.php: a desktop layout/treatment (.sr-nav-d-*) and a mobile
   disclosure pattern (.sr-nav-m-*). Both class sets land on TWO elements —
   the <nav> (which also carries .sr-nav) and <body> (via navBodyClass()).

   So every rule here is anchored: nav rules start `.sr-nav`, page-offset
   rules start `body.`. Without that anchoring a rule like the floating bar's
   transparent background would also strip the page background.

   The breakpoint is navbar-expand-md (768px) and must stay in step with it.
   ------------------------------------------------------------------------ */

/* ── Desktop styles (≥768px) ───────────────────────────────────────────── */
@media (min-width: 768px) {

    /* Default link placement, overridable per desktop style below (each of
       those is one class more specific, so source order doesn't matter).
       Replaces the hard-coded `ms-auto` the markup used to carry — and is
       scoped to desktop deliberately: below the breakpoint the panel is a
       block, where the auto margin was always a no-op, except in the
       fullscreen overlay's column flex box, where it would shove the whole
       list to the right edge. */
    .sr-nav .sr-nav-links {
        margin-left: auto;
    }

    /* Left Aligned — links ride next to the brand instead of across the bar. */
    .sr-nav.sr-nav-d-left .sr-nav-links {
        margin-left: 1.5rem;
        margin-right: auto;
    }

    /* Centered Links — brand left, links centered in the bar. */
    .sr-nav.sr-nav-d-center_links .sr-nav-links {
        margin-left: auto;
        margin-right: auto;
    }

    /* Centered Brand — brand on its own row above centered links. */
    .sr-nav.sr-nav-d-center_brand .sr-nav-inner {
        flex-direction: column;
        padding-top: 0.6rem;
        padding-bottom: 0.35rem;
    }
    .sr-nav.sr-nav-d-center_brand .navbar-brand {
        margin-right: 0;
        margin-bottom: 0.2rem;
    }
    .sr-nav.sr-nav-d-center_brand .sr-nav-links {
        margin-left: auto;
        margin-right: auto;
    }

    /* Split Menu — the two half-lists sit either side of a centered brand.
       The halves are equal-width flex tracks so the brand stays optically
       centered even when one half has more items than the other. */
    .sr-nav.sr-nav-d-split .sr-nav-panel {
        display: flex;
        align-items: center;
        gap: 1.5rem;
    }
    .sr-nav.sr-nav-d-split .sr-nav-half {
        flex: 1 1 0;
        margin: 0;
    }
    .sr-nav.sr-nav-d-split .sr-nav-half-a {
        justify-content: flex-end;
    }
    .sr-nav.sr-nav-d-split .sr-nav-half-b {
        justify-content: flex-start;
    }
    .sr-nav.sr-nav-d-split .sr-nav-center-brand {
        flex: 0 0 auto;
        margin: 0;
        white-space: nowrap;
    }

    /* Underline — accent rule that draws in from the left on hover. */
    .sr-nav.sr-nav-d-underline .navbar-nav .nav-link {
        position: relative;
        margin: 0 0.6rem;
        padding-left: 0.15rem;
        padding-right: 0.15rem;
    }
    .sr-nav.sr-nav-d-underline .navbar-nav .nav-link::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0.1rem;
        height: 2px;
        background-color: var(--color-accent);
        transform: scaleX(0);
        transform-origin: left center;
        transition: transform 0.25s ease;
    }
    .sr-nav.sr-nav-d-underline .navbar-nav .nav-link:hover::after,
    .sr-nav.sr-nav-d-underline .navbar-nav .nav-link:focus-visible::after {
        transform: scaleX(1);
    }

    /* Pills — rounded accent fill on hover. The !important matches the
       themed-navbar rule above, which sets nav-link colour the same way. */
    .sr-nav.sr-nav-d-pills .navbar-nav .nav-link {
        border-radius: 999px;
        padding: 0.35rem 0.9rem;
        margin: 0 0.15rem;
        transition: background-color 0.2s ease, color 0.2s ease;
    }
    .sr-nav.sr-nav-d-pills .navbar-nav .nav-link:hover,
    .sr-nav.sr-nav-d-pills .navbar-nav .nav-link:focus-visible {
        background-color: var(--color-accent-readable);
        color: var(--color-bg) !important;
    }

    /* Floating Bar — the <nav> itself goes transparent and the inner
       container becomes the visible detached bar. */
    .sr-nav.sr-nav-d-floating {
        background-color: transparent !important;
        box-shadow: none !important;
        padding-top: 0.85rem;
    }
    .sr-nav.sr-nav-d-floating .sr-nav-inner {
        background-color: var(--color-nav-bg);
        border-radius: 999px;
        padding: 0.35rem 1.5rem;
        box-shadow: 0 8px 26px rgba(0, 0, 0, 0.28);
    }
    body.sr-nav-d-floating {
        padding-top: 86px;
    }

    /* Transparent — see-through until scrolled, then fills in. assets/nav.js
       adds .sr-nav-stuck. Body padding is dropped so hero content sits under
       the bar, which is the whole point of the style. */
    .sr-nav.sr-nav-d-transparent {
        transition: background-color 0.3s ease, box-shadow 0.3s ease;
    }
    .sr-nav.sr-nav-d-transparent:not(.sr-nav-stuck) {
        background-color: transparent !important;
        box-shadow: none !important;
    }
    body.sr-nav-d-transparent {
        padding-top: 0;
    }

    /* Shrink on Scroll — tall at rest, compact once .sr-nav-stuck is set. */
    .sr-nav.sr-nav-d-shrink .sr-nav-inner {
        padding-top: 0.9rem;
        padding-bottom: 0.9rem;
        transition: padding 0.25s ease;
    }
    .sr-nav.sr-nav-d-shrink .navbar-brand {
        font-size: 1.9rem;
        transition: font-size 0.25s ease;
    }
    .sr-nav.sr-nav-d-shrink.sr-nav-stuck .sr-nav-inner {
        padding-top: 0.2rem;
        padding-bottom: 0.2rem;
    }
    .sr-nav.sr-nav-d-shrink.sr-nav-stuck .navbar-brand {
        font-size: 1.4rem;
    }
    /* Both of these are taller than the 56px default the base rule assumes —
       measured against their at-rest height, which for 'shrink' is the tall
       state at scroll position 0, not the compacted one. */
    body.sr-nav-d-center_brand {
        padding-top: 120px;
    }
    body.sr-nav-d-shrink {
        padding-top: 102px;
    }
}

/* ── Mobile styles (<768px) ────────────────────────────────────────────── */
@media (max-width: 767.98px) {

    /* Shared off-canvas theming for every drawer/overlay/sheet variant.
       Bootstrap's own .offcanvas defaults are light, so the panel has to be
       repainted from the nav palette to match the bar it opens from. */
    .sr-nav .offcanvas {
        background-color: var(--color-nav-bg);
        color: var(--color-nav-text);
        --bs-offcanvas-width: min(78vw, 320px);
    }
    .sr-nav .offcanvas-header {
        border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    }
    .sr-nav .offcanvas-title {
        font-family: var(--font-heading);
        color: var(--color-nav-text);
        letter-spacing: 1px;
        margin: 0;
    }
    .sr-nav .offcanvas .nav-link {
        padding: 0.65rem 0.25rem;
        font-size: 1.05rem;
    }
    .sr-nav .offcanvas .dropdown-menu {
        border: 0;
        background-color: transparent;
        padding-left: 0.75rem;
    }

    /* Centered Dropdown — the plain collapse panel with bigger centred links. */
    .sr-nav.sr-nav-m-collapse_center .navbar-nav {
        text-align: center;
        padding: 0.5rem 0;
    }
    .sr-nav.sr-nav-m-collapse_center .nav-link {
        font-size: 1.15rem;
        padding: 0.6rem 0;
    }

    /* Fullscreen Overlay — an edge drawer widened to the whole viewport, with
       the links optically centred in what's left below the header. */
    .sr-nav.sr-nav-m-fullscreen .offcanvas {
        --bs-offcanvas-width: 100vw;
    }
    .sr-nav.sr-nav-m-fullscreen .offcanvas-body {
        display: flex;
        flex-direction: column;
        justify-content: center;
        text-align: center;
    }
    .sr-nav.sr-nav-m-fullscreen .offcanvas .nav-link {
        font-family: var(--font-heading);
        font-size: 1.7rem;
        padding: 0.7rem 0;
        letter-spacing: 1px;
    }

    /* Bottom Sheet — rises from the bottom edge, sized to its content, with a
       grab handle so it reads as draggable even though it isn't. */
    .sr-nav.sr-nav-m-sheet .offcanvas {
        --bs-offcanvas-height: auto;
        max-height: 85vh;
        border-top-left-radius: 18px;
        border-top-right-radius: 18px;
    }
    .sr-nav.sr-nav-m-sheet .offcanvas-header {
        justify-content: center;
        padding-top: 1.1rem;
    }
    .sr-nav.sr-nav-m-sheet .offcanvas-header::before {
        content: "";
        position: absolute;
        top: 0.5rem;
        left: 50%;
        transform: translateX(-50%);
        width: 38px;
        height: 4px;
        border-radius: 2px;
        background-color: rgba(255, 255, 255, 0.35);
    }
    .sr-nav.sr-nav-m-sheet .offcanvas .nav-link {
        text-align: center;
        font-size: 1.1rem;
    }
    .sr-nav.sr-nav-m-sheet .offcanvas-body {
        padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
    }

    /* Bottom Tab Bar — always visible, so the bar's own toggler is removed
       and the desktop link row stays collapsed (no .show is ever added). */
    .sr-nav.sr-nav-m-tabbar .navbar-toggler {
        display: none;
    }
    body.sr-nav-m-tabbar {
        padding-bottom: calc(58px + env(safe-area-inset-bottom));
    }
}

.sr-tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    display: flex;
    background-color: var(--color-nav-bg);
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    padding-bottom: env(safe-area-inset-bottom);
}

.sr-tabbar a {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    padding: 0.45rem 0.25rem;
    color: var(--color-nav-text);
    text-decoration: none;
    font-family: var(--font-body);
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    transition: color 0.2s ease;
}

.sr-tabbar a i {
    font-size: 1.15rem;
}

.sr-tabbar a span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sr-tabbar a:hover,
.sr-tabbar a:focus-visible {
    color: var(--color-accent-readable);
}

@media (min-width: 768px) {
    .sr-tabbar {
        display: none;
    }
}

/* ===========================================================
   Pattern-layer components (opt-in, tenant-themed)
   -----------------------------------------------------------
   Layout mechanics borrowed from SignalPage's own style guide,
   expressed entirely through a TENANT's --color-* tokens so
   they render correctly under all five design presets — not
   just "instrument".

   HARD RULE: nothing below may reference a brand token
   (--cobalt, --amber, --ink, --paper, --line, --stone). Those
   live in assets/brand.css and belong to SignalPage's own
   surfaces — the admin panel, the portal, the signup funnel.
   A tenant's public site never loads brand.css, so a reference
   to one here would silently resolve to nothing. Enforced by
   `php admin/tools/check-brand-layering.php`.

   Deliberately no webfont: --pb-mono is a system stack, so
   adding a readout to a page costs a tenant no extra request.
   =========================================================== */

:root {
    --pb-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---- Diagnostic readout panel ----
   A bordered panel with a chrome header and mono key:value rows. The
   alternative to an annotated screenshot with floating callout bubbles,
   and a genuinely useful module in its own right for any "specs",
   "what's included" or "at a glance" block. */
.pb-readout {
    border: 1px solid var(--color-border);
    border-radius: 5px;
    background: var(--color-card-bg);
    overflow: hidden;
}
.pb-readout-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .6rem .85rem;
    border-bottom: 1px solid var(--color-border);
    background: var(--color-bg-alt);
    font-family: var(--pb-mono);
    font-size: .78rem;
    font-weight: 600;
    color: var(--color-heading);
}
.pb-readout-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .5rem .85rem;
    border-bottom: 1px solid var(--color-border);
    font-family: var(--pb-mono);
    font-size: .78rem;
}
.pb-readout-row:last-child { border-bottom: 0; }
.pb-readout-key {
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--color-text-muted);
    font-weight: 600;
}
.pb-readout-val {
    color: var(--color-text);
    text-align: right;
}

/* ---- Status row ----
   A dot plus a mono label. The dot takes the tenant's accent rather than
   a fixed amber: on a tenant site "accent" is simply the colour that
   carries meaning, and there is no second colour to reserve. */
.pb-status-row {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    font-family: var(--pb-mono);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}
.pb-status-item { display: inline-flex; align-items: center; gap: .45em; }
.pb-status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--color-accent);
    flex-shrink: 0;
}

/* ---- Spec list ----
   Left label / right detail rows on hairlines — the replacement for a grid
   of icon-in-a-rounded-square feature cards. The label names the thing,
   the detail states one specific fact about it. */
.pb-spec-list { border-top: 1px solid var(--color-border); }
.pb-spec-row {
    display: flex;
    gap: 1.5rem;
    padding: .9rem 0;
    border-bottom: 1px solid var(--color-border);
}
.pb-spec-label {
    flex: 0 0 34%;
    font-weight: 700;
    color: var(--color-heading);
}
.pb-spec-detail { flex: 1; max-width: 70ch; color: var(--color-text-muted); }
@media (max-width: 575.98px) {
    .pb-spec-row { flex-direction: column; gap: .25rem; }
    .pb-spec-label { flex: none; }
}

/* ---- Mono eyebrow ----
   A kicker label above a heading. Neutral by rule — it is a label, not a
   status and not a link, so it does not take the accent. */
.pb-eyebrow {
    font-family: var(--pb-mono);
    font-weight: 600;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--color-text-muted);
}

/* ---- Inverted band ----
   Wrap the contents of a section whose background is DARK. Needed because the
   page builder writes a section background as an inline style
   (background-color:#1a1b1d), and an inline style cannot be overridden by a
   class — so "dark section, light text" cannot be expressed by the theme
   alone. This is the opt-in hook for it.

   Uses the tenant's own tokens inverted, so it works under any palette: on a
   light theme --color-text is the dark ink and --color-bg the light paper. */
.pb-invert,
.pb-invert p,
.pb-invert li { color: var(--color-bg); }
.pb-invert h1, .pb-invert h2, .pb-invert h3,
.pb-invert h4, .pb-invert h5, .pb-invert h6 { color: var(--color-bg); }
.pb-invert .pb-eyebrow,
.pb-invert .text-muted,
.pb-invert .pb-spec-detail,
.pb-invert .pb-readout-key { color: color-mix(in srgb, var(--color-bg) 70%, var(--color-text)); }
/* :not(.btn): a filled .btn-primary is an <a> too, and this light link
   colour on the accent fill measured 3.1:1. */
.pb-invert a:not(.btn) { color: color-mix(in srgb, var(--color-accent) 50%, white); }
.pb-invert .pb-spec-list,
.pb-invert .pb-spec-row,
.pb-invert .pb-readout,
.pb-invert .pb-readout-row,
.pb-invert .pb-readout-head { border-color: color-mix(in srgb, var(--color-bg) 30%, var(--color-text)); }
.pb-invert .pb-spec-label,
.pb-invert .pb-readout-val { color: var(--color-bg); }
.pb-invert .pb-readout-head { background: color-mix(in srgb, var(--color-bg) 8%, var(--color-text)); color: var(--color-bg); }
.pb-invert .btn-outline-secondary {
    --bs-btn-color: var(--color-bg);
    --bs-btn-border-color: color-mix(in srgb, var(--color-bg) 35%, var(--color-text));
    --bs-btn-hover-bg: color-mix(in srgb, var(--color-bg) 12%, var(--color-text));
    --bs-btn-hover-border-color: var(--color-bg);
    --bs-btn-hover-color: var(--color-bg);
}

/* ── Documentation section (/support/docs/) ────────────────────────────────
   docs.php, templates/docs/article.php and site/docs.php. Built from the
   --color-* theme tokens, for the same reason the .pb-* components are:
   Bootstrap's .bg-dark / .text-white / .border-secondary hardcode a dark
   palette, and the design-style shims that remap them only reach inside a
   .card. Tokens work on any palette without needing to be rescued.

   Layout: sidebar | article (capped at a reading measure) | "On this page".
   The article column is capped at 44rem (~70 characters of body text) no
   matter how wide the screen is; the spare width goes to the two rails. */
.docs-skip {
    position: absolute; left: 1rem; top: -200px; z-index: 2000;
    padding: .6rem 1rem; border-radius: .375rem;
    background: var(--color-bg); color: var(--color-heading);
    border: 2px solid var(--color-accent); text-decoration: none; font-weight: 600;
}
.docs-skip:focus { top: 1rem; }

.docs-main  { padding: 6.5rem 0 4.5rem; min-height: calc(100vh - 200px); }
/* .docs-shell rides on Bootstrap's .container so the content lines up with
   the header at every breakpoint; phones get a slightly wider gutter. */
@media (max-width: 575.98px) { .docs-shell { padding-left: 1rem; padding-right: 1rem; } }

.docs-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.75rem; align-items: start; }
@media (min-width: 992px) {
    .docs-layout { grid-template-columns: 15rem minmax(0, 1fr); column-gap: 3rem; }
}
@media (min-width: 1200px) {
    .docs-layout.has-toc { grid-template-columns: 15rem minmax(0, 1fr) 12.5rem; }
}
.docs-article-body:focus, .docs-index:focus { outline: none; }

/* Sidebar. Below lg it folds behind one button; from lg it is always open and
   sticks beside the article. */
.docs-nav a { text-decoration: none; }
.docs-nav-toggle {
    display: flex; align-items: center; gap: .75rem; width: 100%;
    padding: .75rem 1rem; border: 1px solid var(--color-border); border-radius: .5rem;
    background: var(--color-bg-alt); color: var(--color-heading); font: inherit; font-weight: 600; text-align: left;
}
.docs-nav-toggle-current {
    margin-left: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--color-text-muted); font-weight: 400;
}
.docs-nav-toggle .fa-chevron-down { margin-left: auto; font-size: .8em; transition: transform .2s ease; }
.docs-nav-toggle-current + .fa-chevron-down { margin-left: 0; }
.docs-nav-toggle[aria-expanded="true"] .fa-chevron-down { transform: rotate(180deg); }
.docs-nav-list { padding-top: 1rem; }
@media (min-width: 992px) {
    .docs-nav {
        position: sticky; top: 6rem; max-height: calc(100vh - 7rem); overflow-y: auto;
        margin-left: -.6rem; padding-right: .5rem; scrollbar-width: thin;
    }
    .docs-nav-toggle { display: none; }
    .docs-nav-list.collapse { display: block; height: auto !important; padding-top: 0; }
}
.docs-nav-home,
.docs-nav-articles a {
    display: block; padding: .32rem .6rem; border-radius: .375rem;
    color: var(--color-text-muted); font-size: .9375rem; line-height: 1.4;
}
.docs-nav-home { margin-bottom: 1rem; }
.docs-nav-section {
    display: block; padding: .32rem .6rem; border-radius: .375rem;
    color: var(--color-heading); font-size: .875rem; font-weight: 600; line-height: 1.4;
}
.docs-nav-group + .docs-nav-group { margin-top: 1.1rem; }
.docs-nav-sub { margin-left: .75rem; margin-top: .5rem !important; }
.docs-nav-articles { list-style: none; margin: .15rem 0 0; padding: 0; }
.docs-nav a:hover { color: var(--color-heading); background: var(--color-bg-alt); }
.docs-nav a[aria-current="page"] {
    color: var(--color-accent-readable); font-weight: 600;
    background: color-mix(in srgb, var(--color-accent) 10%, var(--color-bg));
}

.docs-breadcrumb { font-size: .875rem; margin-bottom: 1.25rem; }
.docs-breadcrumb .breadcrumb-item,
.docs-breadcrumb .breadcrumb-item a       { color: var(--color-text-muted); }
.docs-breadcrumb .breadcrumb-item a:hover { color: var(--color-accent-readable); }
.docs-breadcrumb .breadcrumb-item.active  { color: var(--color-heading); }

.docs-head  { margin-bottom: 2rem; }
.docs-title { font-size: clamp(1.9rem, 1.35rem + 1.6vw, 2.6rem); line-height: 1.15; margin: 0 0 .75rem; text-wrap: balance; }
.docs-lead  { max-width: 42rem; margin: 0; color: var(--color-text-muted); font-size: 1.15rem; line-height: 1.55; }

/* Article text: one measure, one rhythm, more space above a heading than
   below it. */
.docs-prose { max-width: 44rem; line-height: 1.7; }
.docs-prose > :first-child { margin-top: 0; }
.docs-prose p, .docs-prose ul, .docs-prose ol { margin: 0 0 1.15rem; }
.docs-prose li { margin-bottom: .4rem; }
.docs-prose li > ul, .docs-prose li > ol { margin: .4rem 0 0; }
.docs-prose h2 { font-size: 1.55rem; line-height: 1.25; margin: 2.75rem 0 .85rem; }
.docs-prose h3 { font-size: 1.2rem; line-height: 1.3; margin: 2.1rem 0 .6rem; }
.docs-prose h2, .docs-prose h3 { scroll-margin-top: 6.5rem; }
.docs-prose a { color: var(--color-accent-readable); text-decoration: underline; text-underline-offset: .18em; text-decoration-thickness: 1px; }
.docs-prose a:hover { color: var(--color-heading); }
.docs-prose strong { color: var(--color-heading); font-weight: 600; }
.docs-prose code {
    padding: .12em .4em; border: 1px solid var(--color-border); border-radius: .3rem;
    background: var(--color-bg-alt); color: var(--color-heading); font-size: .85em; overflow-wrap: anywhere;
}
.docs-prose h2 code, .docs-prose h3 code { font-size: .88em; padding: .04em .32em; }
.docs-prose pre {
    margin: 0 0 1.5rem; padding: 1rem 1.15rem; overflow-x: auto;
    border: 1px solid var(--color-border); border-radius: .5rem; background: var(--color-bg-alt);
    color: var(--color-heading); font-size: .85rem; line-height: 1.6;
}
.docs-prose pre code { padding: 0; border: 0; background: none; font-size: inherit; overflow-wrap: normal; }

/* Heading link: appears on hover or keyboard focus, so a section can be
   linked to directly. */
.docs-prose .docs-anchor {
    margin-left: .45rem; font-size: .62em; vertical-align: .15em;
    color: var(--color-text-muted); text-decoration: none; opacity: 0; transition: opacity .15s ease;
}
.docs-prose h2:hover .docs-anchor, .docs-prose h3:hover .docs-anchor, .docs-prose .docs-anchor:focus-visible { opacity: 1; }
.docs-prose .docs-anchor:hover { color: var(--color-accent-readable); }

.docs-table { margin: 0 0 1.5rem; overflow-x: auto; border: 1px solid var(--color-border); border-radius: .5rem; }
.docs-table table { width: 100%; margin: 0; border-collapse: collapse; font-size: .9375rem; line-height: 1.5; }
.docs-table th, .docs-table td { padding: .6rem .85rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--color-border); }
.docs-table th { background: var(--color-bg-alt); color: var(--color-heading); font-weight: 600; white-space: nowrap; }
.docs-table tr:last-child td { border-bottom: 0; }
.docs-table code { white-space: nowrap; overflow-wrap: normal; }

/* "On this page": a disclosure above the article until there is room for a
   rail beside it. */
.docs-toc-inline { max-width: 44rem; margin: 0 0 2rem; border: 1px solid var(--color-border); border-radius: .5rem; }
.docs-toc-inline summary { padding: .75rem 1rem; color: var(--color-heading); font-weight: 600; cursor: pointer; }
.docs-toc-inline ul { list-style: none; margin: 0; padding: 0 1rem .85rem; }
.docs-toc { display: none; }
@media (min-width: 1200px) {
    .docs-toc-inline { display: none; }
    .docs-toc { display: block; position: sticky; top: 6rem; max-height: calc(100vh - 7rem); overflow-y: auto; scrollbar-width: thin; }
}
.docs-toc-title { margin: 0 0 .6rem; color: var(--color-heading); font-size: .875rem; font-weight: 600; }
.docs-toc ul { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--color-border); }
.docs-toc a, .docs-toc-inline a {
    display: block; padding: .26rem 0 .26rem .85rem;
    color: var(--color-text-muted); font-size: .875rem; line-height: 1.4; text-decoration: none;
}
.docs-toc-inline a { padding-left: 0; }
.docs-toc .docs-toc-l3 a { padding-left: 1.6rem; }
.docs-toc-inline .docs-toc-l3 a { padding-left: .85rem; }
.docs-toc a:hover, .docs-toc-inline a:hover { color: var(--color-heading); }
.docs-toc a[aria-current] { color: var(--color-accent-readable); font-weight: 600; }

/* End of an article: the next step in the section, then where to get help. */
.docs-pager {
    display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; max-width: 44rem;
    margin: 3rem 0 0; padding-top: 2rem; border-top: 1px solid var(--color-border);
}
.docs-pager-link {
    display: flex; flex-direction: column; gap: .2rem; padding: .9rem 1.1rem;
    border: 1px solid var(--color-border); border-radius: .5rem; text-decoration: none;
    transition: border-color .15s ease;
}
.docs-pager-next { grid-column: 2; text-align: right; }
.docs-pager-dir { color: var(--color-text-muted); font-size: .8125rem; }
.docs-pager-title { color: var(--color-heading); font-weight: 600; line-height: 1.35; }
.docs-pager-link:hover { border-color: var(--color-accent); }
.docs-pager-link:hover .docs-pager-title { color: var(--color-accent-readable); }
@media (max-width: 575.98px) {
    .docs-pager { grid-template-columns: 1fr; }
    .docs-pager-next { grid-column: auto; }
}
.docs-help {
    display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.5rem; max-width: 44rem;
    margin-top: 2.5rem; padding: 1.5rem; border-radius: .75rem; background: var(--color-bg-alt);
}
.docs-help-title { flex-basis: 100%; margin: 0; font-size: 1.15rem; }
.docs-help p { flex: 1 1 18rem; margin: 0; color: var(--color-text); }

/* Index and section pages. Sections are ruled lists, not cards. */
.docs-index-head { max-width: 46rem; margin-bottom: 2.75rem; }
.docs-filter { position: relative; max-width: 30rem; margin-top: 1.75rem; }
.docs-filter .fa-magnifying-glass {
    position: absolute; left: .95rem; top: 50%; transform: translateY(-50%);
    color: var(--color-text-muted); pointer-events: none;
}
.docs-filter input {
    width: 100%; padding: .75rem 1rem .75rem 2.6rem; font: inherit;
    border: 1px solid color-mix(in srgb, var(--color-text-muted) 75%, var(--color-bg)); border-radius: .5rem;
    background: var(--color-card-bg); color: var(--color-text);
}
.docs-filter input::placeholder { color: var(--color-text-muted); opacity: 1; }
.docs-filter input:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; border-color: var(--color-accent); }
.docs-empty {
    display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.5rem;
    margin: -1rem 0 2.5rem; padding: 1.25rem 1.5rem; border-radius: .75rem; background: var(--color-bg-alt);
}
.docs-empty[hidden] { display: none; }
.docs-empty p { flex: 1 1 18rem; margin: 0; }
.docs-index-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.75rem 4rem; align-items: start; }
@media (min-width: 992px) { .docs-index-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.docs-index-section[hidden] { display: none; }
.docs-article-body .docs-index-section { margin-top: 2.5rem; }
.docs-article-body .docs-index-list { max-width: 44rem; }
.docs-index-section-title { margin: 0 0 .35rem; font-size: 1.25rem; }
.docs-index-section-title a { color: var(--color-heading); text-decoration: none; }
.docs-index-section-title a:hover { color: var(--color-accent-readable); }
.docs-index-section-desc { margin: 0 0 .9rem; color: var(--color-text-muted); font-size: .9375rem; }
.docs-index-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--color-border); }
.docs-index-list li { border-bottom: 1px solid var(--color-border); }
.docs-index-list li[hidden] { display: none; }
.docs-index-list a { display: block; padding: .85rem 0; text-decoration: none; }
.docs-index-item-title { display: block; color: var(--color-heading); font-weight: 600; }
.docs-index-item-excerpt { display: block; margin-top: .15rem; color: var(--color-text-muted); font-size: .9375rem; line-height: 1.5; }
.docs-index-list a:hover .docs-index-item-title { color: var(--color-accent-readable); }
