: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;
}

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);
}

.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 */
footer { /* This is the main site footer, not the thank-you page footer */
    background-color: #000000;
}

.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, templates/blog/docs.php) */
.blog-cat-tree ul {
    padding-left: 1rem;
    margin-top: .25rem;
}
.blog-cat-tree li {
    margin-bottom: .15rem;
}
/* Theme-token colours for the shared category tree (blog sidebar and docs
   sidebar both render it via renderCategorySidebarTree). */
.blog-cat-tree a           { color: var(--color-text-muted); }
.blog-cat-tree a:hover     { color: var(--color-accent); }
.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);
    color: var(--color-accent);
    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);
        color: #fff !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);
}

@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; 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)); }
.pb-invert a { 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/) ────────────────────────────────
   Built from the --color-* theme tokens above, for the same reason the .pb-*
   components are: Bootstrap's .bg-dark / .text-white / .border-secondary
   hardcode a dark palette. The design styles do ship shims that remap those
   utilities onto the theme, but the shims are scoped to `.card` — so any dark
   utility used OUTSIDE a card (a section heading, a bare list-group row, a
   breadcrumb) rendered white-on-white on a light-palette tenant. Tokens work on
   any palette without needing to be rescued. */
.docs-muted { color: var(--color-text-muted); }

.docs-section-title a       { color: var(--color-heading); }
.docs-section-title a:hover { color: var(--color-accent); }

.docs-article {
    background-color: var(--color-card-bg);
    border-color: var(--color-border);
}
.docs-article:hover,
.docs-article:focus {
    background-color: var(--color-bg-alt);
    border-color: var(--color-accent);
}
.docs-article-title   { color: var(--color-heading); font-weight: 600; }
.docs-article-excerpt { color: var(--color-text-muted); }

.docs-sidebar .list-group-item {
    background-color: transparent;
    border-color: var(--color-border);
    color: var(--color-text);
}
.docs-sidebar .list-group-item.active {
    background-color: var(--color-accent);
    border-color: var(--color-accent);
    color: #fff;
}

.docs-breadcrumb .breadcrumb-item,
.docs-breadcrumb .breadcrumb-item a       { color: var(--color-text-muted); }
.docs-breadcrumb .breadcrumb-item a:hover { color: var(--color-accent); }
.docs-breadcrumb .breadcrumb-item.active  { color: var(--color-heading); }

.docs-rule { border-color: var(--color-border); opacity: 1; }
