/*

shell.css -  site chrome and template layout styles (NOT AI-assembled content)

================================================================================
CSS ARCHITECTURE (READ THIS FIRST)
================================================================================

NAMING CONVENTIONS
- l-   = Layout / structural containers (grid, flow, wrappers, regions)
- c-   = Reusable components (cards, buttons, nav items, forms, media objects)
- u-   = Utilities (single-purpose overrides: spacing, display, text, alignment)
- is-/has- = State classes (applied by JS/template): is-open, has-error, etc.

FILE ARCHITECTURE
1) base.css  — FOUNDATION
    - Design tokens (CSS variables): color, type, spacing, radius, shadows, z-index
    - Resets/normalization + base element styles (html/body/a/p/img/button/form)
    - Global utilities + low-level layout primitives used everywhere
    - A11y/motion rules (focus styles, reduced motion, visually-hidden patterns)
    - MUST NOT contain page/template-specific styling

2) shell.css — SITE CHROME + TEMPLATE LAYOUTS (NOT AI-ASSEMBLED CONTENT)
    - Persistent site frame: header, nav, footer, mobile menu, breadcrumbs, etc.
    - Site wrappers: page shells, global grid scaffolds, sidebars, mastheads
    - Template layouts for content types: articles/blog, portfolio/case studies, team
    - System pages: archives, search/results, taxonomy listings
    - OK to rely on WordPress/template context (post meta, archive structure, etc.)
    - SHOULD NOT contain modular “sales/landing” sections intended for assembly

3) blocks.css — MODULAR PAGE SECTIONS (AI/PAGE-BUILDER ASSEMBLABLE)
    - Portable content sections (“blocks”): heroes, feature grids, pricing, FAQ,
        steps/process, testimonials, logo bands, comparison tables, CTA bands, etc.
    - Contact page sections are BLOCKS if they are modular (form section, map, etc.)
    - Blocks must be drop-in reusable and not depend on shell template context
    - Blocks should not style header/footer/nav or other persistent site chrome

DECISION RULES (QUICK TRIAGE)
- If it’s a universal default/token/utility → base.css
- If it’s persistent site frame OR editorial/system templates → shell.css
- If it’s a portable content section an LLM could choose + assemble → blocks.css

DEPENDENCY RULES (KEEP IT CLEAN)
- base.css may be used by everything.
- shell.css may use base utilities/tokens; should not reach into block internals.
- blocks.css may use base utilities/tokens; should not style shell chrome.

*/

/* ========== Layout Shell ========== */

.l-site {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* ========== Page Wrapper ========== */

.page-wrapper {
    position: relative;
    min-height: 100vh;
}

/* When menu is open: prevent body scrolling */
body.has-menu-open {
    overflow: hidden;
    position: fixed;
    width: 100%;
}

/* When menu is open: prevent scrolling via touch-action and pointer-events on wrapper */
body.has-menu-open .page-wrapper {
    touch-action: none;
    pointer-events: none; /* Prevents mouse wheel scrolling */
}

/* Re-enable pointer events on header and menu portal */
body.has-menu-open .l-header,
body.has-menu-open .c-menu-portal {
    pointer-events: auto;
}

.l-main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* ========== Secondary Header Bar ========== */

.l-header-secondary {
    background: var(--color-surface-alt);
    border-bottom: 1px solid var(--color-card-border);
    font-size: 0.875rem;
}

.l-header-secondary__inner {
    /* `margin: 0 auto` was here on its own, with no max-width — so it centred
       nothing and the strip ran the full viewport, pinning its two clusters to
       the far edges: 505px of dead middle at 1440 and 985px at 1920. The band
       itself stays full-bleed; only its CONTENT is capped, the same way the
       mega dropdown does it, so the strip lines up with the page below. */
    max-width: var(--wrap-content);
    margin: 0 auto;
    padding: 0.6em var(--header-gutter);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.c-header-contact {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    flex-wrap: wrap;
}

.c-header-contact__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2rem;
    gap: 0.35rem;
    padding: 0.25rem;
    color: var(--color-text-muted);
    text-decoration: none;
    border-radius: 0.375rem;
    transition: color var(--t-fast), background-color var(--t-fast);
}

/* ⚠ This filled with --color-card-bg, and the strip's own ground is
   --color-surface-alt. Both resolve to #161c25, so the fill was a NO-OP: the
   only feedback these controls gave was a small muted-to-white text step, which
   is why the strip read as non-interactive. Exactly the defect PROGRESS.md
   records for the services card ("pointed --color-card-bg and
   --color-surface-alt at the same Midnight value, which silently killed the
   fill step"), still live here.
   audit_dead_hover could not see it: it compares a :hover value against the
   element's OWN base value, and the base declares no background at all, so
   transparent -> #161c25 looks like a real change. It is the GROUND that makes
   it dead. --hover is the site's translucent hover fill and steps visibly over
   anything. */
.c-header-contact__link:hover {
    color: var(--color-text);
    background-color: var(--hover);
}

.c-header-contact__link i {
    font-size: 1rem;
}

.c-header-contact__link--phone {
    width: auto;
    padding: 0.25rem 0.5rem;
}

.c-header-contact__link--phone span {
    font-weight: 500;
}

.c-header-tools {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
    align-items: center;
}

.c-header-external {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.c-header-external__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.9rem;
    font-size: 0.813rem;
    font-weight: 500;
    color: var(--color-text);
    text-decoration: none;
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: 0.375rem;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast), transform var(--t);
}

.c-header-external__btn i {
    font-size: 0.75rem;
}

/* Hide secondary header on mobile */
@media (max-width: 899px) {
    .l-header-secondary {
        display: none;
    }
}

/* ========== Primary Header ========== */

.l-header {
    position: sticky;
    top: 0;
    z-index: 100;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    background-color: var(--color-header-bg);
}

.l-header__inner {
    /* Named, because the desktop nav cancels it with a negative margin to make
       its triggers span the FULL bar height. Two places, one value. Was `1.5em`;
       rem so the child that negates it resolves the same number (the nav link
       runs at 0.95rem, and an em there would not match). */
    --header-pad-y: 1.5rem;

    /* Same defect as the strip above: `margin: 0 auto` with nothing to centre.
       The bar measured brand at x=32 while the page column starts at 120 (1440)
       and 360 (1920), so the wordmark lined up with nothing below it, and the
       gap between the brand and the nav was 681px / 1161px of dead bar.
       The glass bar stays full-bleed — only the content is capped. */
    max-width: var(--wrap-content);
    margin: 0 auto;
    padding: var(--header-pad-y) var(--header-gutter);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    flex-wrap: nowrap;
}

.l-header__actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem 1.5rem;
}

/* Brand Component */
.c-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    text-decoration: none;
    transition: color var(--t-fast);
}

/* The brand is a link to "/" and had NO visible hover response at all —
   rest and hover screenshots were identical. That breaks the hover-honesty
   rule from the other side: the rule says never put a hover on something that
   is not a link, and its corollary is that a link has to answer.
   The mark itself is drawn with `fill: var(--color-text)`, so tinting the
   anchor's colour moves the wordmark and the logo together as one object,
   which is what it is. */
/* Only the SPROUT answers, not the whole lockup. Tinting the wordmark too was
   tried and recoloured the entire brand on a mouse-over, which is far too loud
   for a mark — the response should be a precise accent, not a repaint.
   The mark now carries its real brand colours (silver crescent, green sprout —
   set from --brand-silver / --brand-green in header.php's inline <style>), so
   hover only LIFTS the sprout to the on-dark green instead of repainting both
   paths from monochrome. Owner request, 2026-08-31: "logo should be in colour". */
.c-brand__logo path {
    transition: fill var(--t-fast);
}
.c-brand:hover .sscom-simple-logo-2 {
    fill: var(--accent-text);
}

.c-brand__logo {
    height: 48px;
    margin-top: -15px;
    width: auto;
    display: block;
}

.c-brand__title {
    font-family: var(--font-sans);
    color: var(--color-header-text);
    font-size: var(--fs-brand);
    letter-spacing: 0.01em;
    font-weight: 360;
}
/* Header CTA + icon-link / text-link styles deleted 2026-04-28 — pre-megamenu chrome leftovers
   (c-header-social, c-header-buttons, c-icon-link, c-text-link, c-header-button*).
   Active header chrome uses c-header-contact, c-header-tools, c-header-external. */

/* The .c-theme-toggle lightbulb lived here. Removed 2026-07-31 with the style
   cutover — Midnight is the only theme, so there is nothing to toggle. */

/* ========== Footer Components ========== */

/* ========== Component: Back to Top ========== */

/* ========== Layout: Hero ========== */

/* =========================================
    Stable glow (wrapper-based)
    NOTE: pseudo-elements do NOT reliably work on input/textarea/select.
    This will correctly glow the .c-search-bar wrapper.
    ========================================= */


/* Keep your existing hover/focus handling for raw form controls */
.c-form input:focus,
.c-form textarea:focus,
.c-form select:focus {
    border-color: var(--color-accent-border);
}
/* ========== Component: Search Bar ========== */


/* Piano toy fully retired 2026-06 — widget CSS, ss-piano-* page styles, /js/piano.js,
   and the --color-piano-bar* tokens all removed (the toy never landed well). */

/* ========== Layout: Content Shell ========== */

.l-content {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: var(--wrap-content);
    margin: 0 auto;
    width: 100%;
    padding: 3em var(--header-gutter);
    position: relative;
    z-index: 0;
}

/* Flex-column items default to min-width:auto (= min-content), so a single wide
   descendant — a white-space:pre terminal, a fixed-min-width demo widget, a long
   unbreakable string — forces its whole section past the viewport, where the
   body's overflow-x:clip silently cuts it off with no way to scroll to it.
   Letting the sections shrink to the column width makes any genuinely-wide
   widget scroll/clip *itself* (its own overflow) instead of blowing out the page.
   Explicit widths (full-bleed sections) are unaffected — this only removes the
   min-content floor. */
.l-content > * {
    min-width: 0;
}

.l-content__section {
    width: 100%;
}

.l-content__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(220px, 1.1fr) minmax(220px, 1.1fr);
    gap: 2rem;
    align-items: flex-start;
    padding-inline: clamp(0.5em, 3vw, 3em);
}

.l-content__panel {
    height: 100%;
}

.l-content--ultra-wide {
    max-width: 1800px;
}

/* ========== Section Band (Full-Bleed Background) ========== */

.l-section-band {
    width: 100%;
    background: var(--color-band-bg);
    padding: clamp(3rem, 6vw, 5rem) 0;
    border-top: 1px solid var(--color-border-subtle);
    border-bottom: 1px solid var(--color-border-subtle);
}

/* Allow layered cards to overflow the band's bottom edge */
.l-section-band:has(.c-card--layered) {
    overflow: visible;
    padding-bottom: 0;
}

/* Sections after a band with a layered card need clearance */
.l-section-band:has(.c-card--layered) + .l-content {
    padding-top: 7rem;
}

.l-section-band .l-content {
    padding-top: 0;
    padding-bottom: 0;
}

.l-section-band .c-mega-cta {
    margin-top: 0;
    border-top: none;
    padding-top: 0;
    padding-bottom: 0;
}

/* ========== Prefooter (3-Column Layout) ========== */

.l-prefooter {
    color: var(--color-prefooter-text);
    width: 100%;
    position: relative;
    background: var(--color-prefooter-bg);
    /* A hairline, because this band had NO seam. Measured: .l-prefooter renders
       rgb(6,9,12) — the same ground as the page content above it AND the same as
       .l-footer below it — so three distinct regions painted as one continuous
       black field and the block read as floating in nothing. The footer already
       separates itself from this band with exactly this hairline; the band now
       does the same against the page. Flat grounds separated by rules is the
       site's own idiom — a different fill would be the other, worse fix. */
    border-top: 1px solid var(--color-border-subtle);
}

.l-prefooter .l-content {
    max-width: 1440px;
    margin: 0 auto;
    width: 100%;
    padding: 4rem clamp(1.5rem, 4vw, 2rem);
}

/* --- Grid layout --- */

.l-prefooter__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 3rem;
    padding-top: 4.5rem;
    padding-bottom: 2rem;
}

@media (min-width: 720px) {
    .l-prefooter__grid {
        grid-template-columns: 1.2fr 0.9fr;
        gap: 3rem;
    }
}

/* --- Column base --- */

.l-prefooter__col {
    display: flex;
    flex-direction: column;
}

/* --- Section headers --- */

.l-prefooter__header {
    margin-bottom: 1.25rem;
}

.l-prefooter__header .u-eyebrow {
    margin-bottom: 0.25rem;
    color: var(--color-prefooter-text-muted);
}

.l-prefooter__header .u-heading-small {
    color: var(--color-prefooter-heading);
}

/* --- Articles column --- */

.l-prefooter__articles {
    display: flex;
    flex-direction: column;
}

/* --- Articles column uses the canonical .c-sidebar-post pattern (defined further down) --- */

/* --- About column --- */

.l-prefooter__about {
    display: flex;
    flex-direction: column;
}

.l-prefooter__about-content {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}

.l-prefooter__about-content p {
    margin: 0;
    line-height: 1.6;
    font-size: 0.95rem;
}

/* --- Column link buttons --- */

.l-prefooter__link {
    margin-top: 1.25rem;
    align-self: flex-start;
}

.l-prefooter__about-content > .c-btn {
    margin-top: 0.5rem;
}

/* --- Links --- */

.l-prefooter a:not(.c-btn) {
    color: var(--color-prefooter-link);
    transition: color var(--t-fast);
}

.l-prefooter a:not(.c-btn):hover {
    color: var(--color-prefooter-link-hover);
}

.l-prefooter .u-text-muted {
    color: var(--color-prefooter-text-muted);
}

/* --- Mobile adjustments --- */

@media (max-width: 719px) {
    .l-prefooter__grid {
        gap: 2.5rem;
        padding-top: 3rem;
        padding-bottom: 1.5rem;
    }
}

/* ========== Footer ==========
   Four full-width sections sharing a common column rhythm at desktop —
   services 4-col and auxiliary 4-col stack vertically aligned so the eye
   reads two parallel grids, not a fragmented mosaic.

     1. .l-footer__identity   — heading + inline NAP banner (one row).
     2. .l-footer__services   — 4-col grid (Web · Search · Hosting · Brand).
     3. .l-footer__auxiliary  — 4-col grid (Company · Articles · Support
                                · Legal), aligned to services above.
     4. .l-footer__bottom     — copyright (left) + visitor IP (right).

   Background uses the gradient token so the brand-wordmark on the home
   page (which uses margin-bottom: -0.75vw to tuck under the footer) has
   a visible top edge to tuck under — surface fades to body bg downward. */

.l-footer {
    background: var(--color-footer-bg-gradient);
    border-top: 1px solid var(--color-border-subtle);
    width: 100%;
    position: relative;
    padding: 3.5rem 0 2rem;
}

.l-footer .l-content {
    width: 100%;
    max-width: 1440px;
    margin: 0 auto;
    padding: 0 clamp(1.5rem, 4vw, 2rem);
}

/* ----- 1. Identity banner — heading + inline NAP, single row ----- */
.l-footer__identity {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.6rem 2rem;
    padding-bottom: 2rem;
    margin-bottom: 2.5rem;
    border-bottom: 1px solid var(--color-border-subtle);
}

.l-footer__identity-heading {
    margin: 0;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text);
    flex-shrink: 0;
}

.l-footer__identity-nap {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0;
    color: var(--color-text-muted);
    font-size: 0.95rem;
}

.l-footer__identity-nap > li {
    display: inline-flex;
    align-items: baseline;
}

/* Middot separators between NAP items — rendered as a flex-end pseudo
   attached to each li except the last. Sits inside the li so it wraps
   with the item if the line breaks. */
.l-footer__identity-nap > li:not(:last-child)::after {
    content: "·";
    color: var(--color-text-muted);
    padding: 0 1rem;
    flex-shrink: 0;
    opacity: 0.7;
}

/* ----- 2. Services 4-col grid ----- */
.l-footer__services {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2rem;
    padding-bottom: 2.5rem;
    margin-bottom: 2.5rem;
    border-bottom: 1px solid var(--color-border-subtle);
}

/* ----- 3. Auxiliary 4-col grid (Company · Articles · Support · Legal)
   Same column count as services so the two grids share a visual rhythm. */
.l-footer__auxiliary {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2rem;
    padding-bottom: 2rem;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--color-border-subtle);
}

/* <1024px: 4-col compresses to <220px each — drop to 2-col where each
   column gets 260px+ for the longer service / category labels. */
@media (max-width: 1023px) {
    .l-footer__services,
    .l-footer__auxiliary {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 2rem 1.5rem;
    }
}

@media (max-width: 479px) {
    .l-footer__services,
    .l-footer__auxiliary {
        grid-template-columns: 1fr;
    }
}

/* ----- 4. Bottom strip — copyright + IP ----- */
.l-footer__bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem 1.5rem;
    font-size: 0.85rem;
    color: var(--color-text-muted);
}

.l-footer__bottom-meta {
    /* copyright + tagline as a single inline string */
}

.l-footer__bottom-ip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
}

/* Inside the bottom strip the meta-label sits inline (no top border or
   vertical separator the way it does inside the Legal column historically). */
.l-footer__bottom-ip .c-footer-meta-label {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

@media (max-width: 599px) {
    .l-footer__bottom {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
    }
}
/* ========== Component: Post List ========== */


/* ========== Footer Components ========== */

.c-footer-col {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.c-footer-col__heading {
    margin: 0 0 1rem 0;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text);
}

/* Stacked-list shape used by every footer category column */
.c-footer-links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.c-footer-links li {
    line-height: 1.5;
}

/* "Your IP" meta block at the bottom of the Legal column */

.c-footer-meta-label {
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Identity column — NAP list (vertical) + about-links (inline) */




/* Footer link styles */
.c-footer-link {
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: 0.95rem;
    transition: color var(--t-fast);
    display: inline-block;
    /* Defensive: long emails / URLs break inside the column instead of
       overflowing. Identity column is wide enough that this rarely fires. */
    overflow-wrap: break-word;
}

.c-footer-link:hover {
    color: var(--color-link-hover);
}

.c-footer-link:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--green) 70%, transparent);
    outline-offset: 3px;
    border-radius: 0.35rem;
}

/* Inline-context link (e.g. the IP in the Legal column meta block) */
.c-footer-link--inline {
    font-size: inherit;
}

/* Footer service link that leaves the site (Social Media Management). */
.c-footer-link--external i {
    font-size: 0.7em;
    margin-left: 0.4em;
    opacity: 0.55;
    transition: opacity var(--t-fast);
    vertical-align: baseline;
}

.c-footer-link--external:hover i {
    opacity: 1;
}

/* Footer nav + NAP links: roomier tap rows on touch — MOBILE ONLY (audit 2026-06-03).
   The stacked column links were only ~22px tall (lh 1.5 on 0.95rem) — cramped to tap.
   Desktop spacing is left exactly as it was. */
@media (max-width: 768px) {
    .c-footer-links .c-footer-link,
    .l-footer__identity-nap .c-footer-link {
        padding-block: 0.7rem;
    }
    /* NAP stacks on phones — the inline "·" separators are between-item markers that
       otherwise dangle at the end of each wrapped line (after the phone, the email). */
    .l-footer__identity-nap {
        flex-direction: column;
        align-items: flex-start;
    }
    .l-footer__identity-nap > li:not(:last-child)::after {
        content: none;
    }
}

/* ========== Breakpoints ========== */

@media (max-width: 1120px) {
    .l-content__grid {
        grid-template-columns: minmax(0, 1.6fr) minmax(220px, 1.2fr);
        grid-template-areas:
            "articles services"
            "articles about";
    }

    .l-content__panel--articles {
        grid-area: articles;
    }

    .l-content__panel--services {
        grid-area: services;
    }

    .l-content__panel--about {
        grid-area: about;
    }
}

@media (max-width: 960px) {
    .l-header__inner {
        flex-wrap: wrap;
        justify-content: space-between;
        gap: 0.75rem;
    }

    .l-header__actions {
        flex-grow: 1;
        justify-content: flex-end;
    }

    .l-content {
        padding-top: 2rem;
    }

    /* Footer responsive - tablet. Vertical padding lives HERE, not on
       .l-prefooter__grid — that grid's padding is clobbered by the later, equal-
       specificity `.l-content__section { padding: 0 }`, so the grid rules are
       dead. Keep the prefooter's top/bottom breathing room on the wrapper (as
       desktop does) so the About column's button doesn't smash the footer. */
    .l-prefooter .l-content {
        padding: 3.5rem 2rem;
    }

    .l-prefooter__grid {
        padding-top: 3rem;
        padding-bottom: 3rem;
    }
}

@media (max-width: 720px) {
    /* Keep single-row layout - override any stacking */
    .l-header__inner {
        flex-direction: row;
        align-items: center;
        padding: 0.75rem 1rem;
    }

    /* Keep brand left-aligned, allow it to shrink */
    .c-brand {
        justify-content: flex-start;
        flex-shrink: 1;
        min-width: 0;
    }

    .c-brand__title {
        font-size: 0.9rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .c-brand__logo {
        height: 28px;
    }

    /* Keep actions in a single row on the right */
    .l-header__actions {
        flex-direction: row;
        align-items: center;
        gap: 0.5rem;
        flex-shrink: 0;
    }

    .l-content__grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "articles"
            "services"
            "about";
    }

    /* Prefooter responsive - mobile. Vertical padding on the wrapper (see tablet
       note above) — the grid's own padding is dead, so this is what gives the
       button bottom room before the footer. */
    .l-prefooter .l-content {
        padding: 3rem 1.5rem;
    }

    .l-prefooter__grid {
        /* Up from 2.5rem so the prefooter's breathing room matches the content
           sections (~3.5–5rem) instead of reading cramped against them (mobile audit) */
        padding-top: 3.5rem;
        padding-bottom: 3.5rem;
    }

    .u-heading-display-lg {
        font-size: clamp(2.1rem, 6vw, 2.6rem);
    }
}

@media (max-width: 600px) {
    /* Extra small screens - hide brand title if needed */
    .l-header__inner {
        padding: 0.5rem 0.75rem;
    }

}

@media (max-width: 380px) {
    /* Very small screens - hide brand title to save space */
    .c-brand__title {
        display: none;
    }

    .c-brand__logo {
        height: 26px;
    }
}

/* =========================================================
    HEADER / PRIMARY NAV
    ========================================================= */


/* ===== Hamburger icon (3 lines) ===== */
.c-hamburger {
    width: 1.5rem;
    height: 1.125rem;
    display: inline-block;
    position: relative;
}
.c-hamburger::before,
.c-hamburger::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    background: currentColor;
    /* --r-full: genuinely circular, which the radius role rule exempts. Using
       the token rather than a literal 999px also means a future "kill the pills"
       sweep cannot flatten it by accident — the same protection the quote
       button's --radius-pill already gives it. */
    border-radius: var(--r-full);
    transition: transform var(--t), opacity var(--t-fast);
}
.c-hamburger::before {
    top: 0;
}
.c-hamburger::after {
    bottom: 0;
}

/* Middle line */
.c-hamburger span {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    height: 2px;
    background: currentColor;
    /* --r-full: genuinely circular, which the radius role rule exempts. Using
       the token rather than a literal 999px also means a future "kill the pills"
       sweep cannot flatten it by accident — the same protection the quote
       button's --radius-pill already gives it. */
    border-radius: var(--r-full);
    transition: opacity var(--t-fast);
}

/* ===== Mobile Menu Portal Layer ===== */
/* Portal sits above everything, prevents body scroll via isolation */
.c-menu-portal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
    isolation: isolate;
}

.c-menu-portal.is-open {
    pointer-events: auto;
}

/* ===== Overlay ===== */
.c-menu-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    transition: opacity var(--t-fast);
    z-index: 1;
}

.c-menu-portal.is-open .c-menu-overlay {
    opacity: 1;
}

/* ===== Slide-out Panel ===== */
.c-menu-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(92vw, 22rem);
    max-height: 100vh;
    max-height: 100dvh; /* Dynamic viewport height for mobile browsers */

    transform: translate3d(100%, 0, 0);
    will-change: transform;
    transition: transform var(--t);

    background: var(--color-menu-panel-bg);
    backdrop-filter: blur(16px);
    border-left: 1px solid var(--color-menu-panel-border);
    color: var(--color-menu-panel-text);

    z-index: 2;

    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

.c-menu-portal.is-open .c-menu-panel {
    transform: translate3d(0, 0, 0);
}


.c-menu-panel__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.9rem 1rem;
    border-bottom: 1px solid var(--color-menu-panel-border);
}

/* Menu panel brand logo link */
.c-menu-panel__brand {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    flex-shrink: 0;
}

.c-menu-panel__logo {
    height: 30px;
    width: auto;
    display: block;
}

.c-menu-panel__header-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.c-menu-panel .c-btn--menu-close {
    color: var(--color-menu-panel-text);
}

.c-menu-panel .c-btn--menu-close:hover {
    color: var(--color-accent-text);
}

/* Mobile menu sections */
.c-menu-panel__section {
    padding: 1rem 0.75rem 1.25rem;
    border-top: 1px solid var(--color-menu-panel-border);
}

.c-menu-panel__section-title {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    padding: 0.5rem 0.75rem 0.75rem;
}

/* Compact icon row for social/contact links */
.c-menu-contact-icons {
    display: flex;
    gap: 0.5rem;
    padding: 0 0.5rem 0.75rem;
}

.c-menu-contact-icons__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--r);
    color: var(--color-menu-panel-text);
    background: var(--color-menu-panel-hover);
    text-decoration: none;
    transition: background-color var(--t-fast), color var(--t-fast);
    font-size: 1.125rem;
}

.c-menu-contact-icons__btn:hover,
.c-menu-contact-icons__btn:focus-visible {
    /* --accent-solid, not --green. White on #1b944b is 3.58:1; on #07792f it
       is 5.55:1. Measured by audit_hover_contrast.py, which scores HOVER
       states — audit_contrast.py structurally cannot see them, because a
       :hover rule contributes nothing to an un-hovered element's computed
       style. "--accent is a surface colour, not a white-text surface" was
       already a written rule; these four had simply never been checked. */
    background: var(--accent-solid);
    color: var(--white);
    outline: none;
}

/* Full-width phone link below icon row */
.c-menu-contact__phone {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.65rem 0.75rem;
    color: var(--color-menu-panel-text);
    text-decoration: none;
    border-radius: var(--r);
    transition: background-color var(--t-fast), color var(--t-fast);
}

.c-menu-contact__phone:hover,
.c-menu-contact__phone:focus-visible {
    background: var(--color-menu-panel-hover);
    outline: none;
}

.c-menu-contact__phone i {
    font-size: 1.125rem;
    width: 1.5rem;
    text-align: center;
    color: var(--color-text-muted);
}

.c-menu-contact__phone span {
    font-size: 0.938rem;
    font-weight: var(--fw-medium);
}

.c-menu-external {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.c-menu-external__link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 0.9rem;
    color: var(--color-menu-panel-text);
    text-decoration: none;
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: var(--r);
    transition:
        background var(--t-fast),
        border-color var(--t-fast),
        color var(--t-fast),
        box-shadow var(--t-fast),
        transform var(--t);
    font-weight: 500;
}

.c-menu-external__link:hover,
.c-menu-external__link:focus-visible {
    /* --accent-solid, not --green. White on #1b944b is 3.58:1; on #07792f it
       is 5.55:1. Measured by audit_hover_contrast.py, which scores HOVER
       states — audit_contrast.py structurally cannot see them, because a
       :hover rule contributes nothing to an un-hovered element's computed
       style. "--accent is a surface colour, not a white-text surface" was
       already a written rule; these four had simply never been checked. */
    background: var(--accent-solid);
    border-color: var(--green);
    color: var(--white);
    outline: none;
}

/* ⚠ These MUST sit after both base rules. `.c-menu-external__link--social:hover`
   and `.c-menu-external__link:hover` are both (0,2,0), so source order decides
   — with the block placed up beside the desktop component, the generic mobile
   hover above won and both chips bloomed the same green, which is the exact
   sameness this block exists to remove. Rendered side by side it was obvious;
   the specificity was not. */
/* ── Destination identity, ONE definition, BOTH surfaces ────────────────────
   Each of these links goes somewhere else, and on hover it blooms into that
   destination's own colours — so the chip previews where it is about to send
   you. The cutover collapsed the two external ones into a single identical
   green hover, which made them interchangeable and deleted the whole point.

   The reason given for flattening was real but was solved the wrong way: white
   on #3cc1ca measured 2.17:1 and on #f36f5d 2.90:1. The fix is not to discard
   a third party's mark — Instagram's and PayPal's brand colours were KEPT for
   exactly that reason, and these were treated inconsistently — it is to lay a
   flat scrim UNDER the label. That keeps each gradient unmistakably teal and
   unmistakably red-orange while making the label readable.
   `linear-gradient(<colour> 0 0)` is a solid one-colour layer, not a gradient.

   The two scrims differ ON PURPOSE: cyan is a much lighter colour than the
   salmon, so an identical scrim would leave one chip readable and the other
   not. What is held equal is the RESULT — measured on rendered pixels — not the
   number that produces it. A single shared value left the social chip at
   4.38:1, under the bar.

   ⚠ Keyed on a VARIANT, and paired with the mobile component, for two reasons
   this file has now been bitten by:
   1. These were `:first-child` / `:last-child`, which is positional. The moment
      a third chip joined the cluster it inherited whichever brand gradient its
      position happened to match — Make a Payment bloomed website-in-a-day red.
   2. The desktop strip and the mobile sheet were styled separately and had
      drifted: on mobile these were flat identical rows with no destination
      identity at all. Both surfaces now render from $ss_header_actions and
      share the rule below, so neither the markup nor the styling can diverge.

   lint-ok throughout: a destination's brand colours are not ours to re-theme. */
.c-header-external__btn--social:hover,
.c-menu-external__link--social:hover {
    background-image: linear-gradient(rgba(0, 0, 0, 0.44) 0 0), linear-gradient(135deg, #155972, #3cc1ca, #032f3f); /* lint-ok: social.silverservers.com's own brand gradient + readability scrim */
    border-color: #3cc1ca; /* lint-ok: destination brand colour */
    color: var(--white);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(60, 193, 202, 0.3); /* lint-ok: glow keyed to the destination's brand */
}

.c-header-external__btn--wiad:hover,
.c-menu-external__link--wiad:hover {
    background-image: linear-gradient(rgba(0, 0, 0, 0.35) 0 0), linear-gradient(135deg, #92281a, #f36f5d, #ff4830); /* lint-ok: website-in-a-day.ca's own brand gradient + readability scrim */
    border-color: #f36f5d; /* lint-ok: destination brand colour */
    color: var(--white);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(243, 111, 93, 0.3); /* lint-ok: glow keyed to the destination's brand */
}

.c-menu-external__link i {
    font-size: 0.875rem;
    opacity: 0.8;
}

/* The menu-panel copy of the theme toggle lived here. Removed with its header
   twin, 2026-07-31. */

/* ===== NAV base ===== */
.c-nav {
    list-style: none;
    margin: 0;
    padding: 0.5rem 0.75rem 1rem;
}

.c-nav__item {
    position: relative;
}

/* Link row */
.c-nav__link {
    display: inline-flex;
    align-items: center;
    padding: 0.7rem 0.75rem;
    text-decoration: none;
    color: var(--color-menu-panel-text);
    font-weight: var(--fw-medium);
    font-size: 0.95rem;
    transition: background-color var(--t-fast);
}

/* Submenu toggle button (chevron) */
.c-nav__toggle {
    border: 1px solid var(--color-menu-panel-border);
    background: var(--color-menu-panel-hover);
    color: var(--color-menu-panel-text);
    cursor: pointer;
    padding: 0.5rem 0.65rem;
    border-radius: 0.6rem;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.c-nav__toggle i {
    font-size: 0.7rem;
    transition: transform var(--t);
}

.c-nav__toggle:hover {
    /* --accent-solid, not --green. White on #1b944b is 3.58:1; on #07792f it
       is 5.55:1. Measured by audit_hover_contrast.py, which scores HOVER
       states — audit_contrast.py structurally cannot see them, because a
       :hover rule contributes nothing to an un-hovered element's computed
       style. "--accent is a surface colour, not a white-text surface" was
       already a written rule; these four had simply never been checked. */
    background-color: var(--accent-solid);
    border-color: var(--green);
    color: var(--white);
}

/* Rotate chevron when expanded */
.c-nav__toggle[aria-expanded="true"] i {
    transform: rotate(180deg);
}

/* Mobile layout: link + toggle on same row */
.c-nav__item {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
}

/* ===== Mobile drawer nav — clean hairline-separated rows, subtle chevrons.
   Scoped to the off-canvas nav so the desktop inline nav is untouched. Meets the
   44×44 touch-target minimum (mobile audit 2026-06-03). Previously each chevron
   was a gray boxed button and the boxes collided edge-to-edge; rows now carry the
   site's FAQ/list rhythm (hairline separators) and the chevrons are borderless. */
.c-header-nav--mobile .c-nav {
    padding: 0.25rem 0.5rem 0.75rem;
}

/* Hairline between entries, matching the home FAQ rows */
.c-header-nav--mobile .c-nav__item {
    border-bottom: 1px solid var(--color-menu-panel-border);
}
.c-header-nav--mobile .c-nav__item:last-child {
    border-bottom: none;
}

/* Link fills its row; a touch larger for menu presence */
.c-header-nav--mobile .c-nav__link {
    width: 100%;
    min-height: 54px;
    padding-inline: 0.4rem;
    font-size: 1.05rem;
}

/* Chevron toggle: borderless and transparent — no boxed chip. The chevron alone
   carries the affordance and turns green when its submenu is open. */
.c-header-nav--mobile .c-nav__toggle {
    min-width: 54px;
    min-height: 54px;
    border: none;
    background: transparent;
    border-radius: 0;
    color: var(--color-menu-panel-text);
    opacity: 0.5;
}
.c-header-nav--mobile .c-nav__toggle i {
    font-size: 0.85rem;
}
.c-header-nav--mobile .c-nav__toggle:hover,
.c-header-nav--mobile .c-nav__toggle:focus-visible {
    background: transparent;
    border-color: transparent;
    color: var(--green);
    opacity: 1;
}
.c-header-nav--mobile .c-nav__toggle[aria-expanded="true"] {
    color: var(--green);
    opacity: 1;
}

/* Contact CTA: lift the green pill off the list so it breathes */
.c-header-nav--mobile .c-nav__item--cta {
    margin-top: 1rem;
    border-bottom: none;
}
.c-header-nav--mobile .c-nav__link--cta {
    width: 100%;
    justify-content: center;
    min-height: 54px;
}

/* Submenu */
.c-nav__menu {
    grid-column: 1 / -1;
    list-style: none;
    margin: 0 0 0.35rem 0;
    padding: 0.05rem 0.05rem 0.05rem;
}

.c-nav__submenu-link {
    position: relative;
    display: block;
    padding: 0.5rem 0.85rem 0.5rem 1.1rem;
    margin: 0.1rem 0;
    border-radius: var(--r-sm);
    text-decoration: none;
    color: var(--color-menu-panel-text);
    transition: background-color var(--t-fast);
}

.c-nav__submenu-link::before {
    content: "";
    position: absolute;
    left: 0.4rem;
    top: 50%;
    width: 3px;
    height: 65%;
    background: var(--green);
    border-radius: 2px;
    transform: translate(-4px, -50%);
    opacity: 0;
    transition: opacity var(--t-fast), transform var(--t);
    pointer-events: none;
}

.c-nav__submenu-link:hover,
.c-nav__submenu-link:focus-visible {
    background: rgba(255, 255, 255, 0.06);
    outline: none;
}

.c-nav__submenu-link:hover::before,
.c-nav__submenu-link:focus-visible::before {
    opacity: 1;
    transform: translate(0, -50%);
}

/* ===== Mobile-specific layout tweaks ===== */
@media (max-width: 899px) {
    .l-header__inner {
        padding: 1rem 1.5rem;
        gap: 0.75rem;
    }

    .l-header__actions {
        gap: 0.5rem;
        flex-shrink: 0;
    }

    .c-header-nav--desktop {
        display: none;
    }

    .c-brand {
        flex-shrink: 1;
        min-width: 0;
    }

    .c-brand__title {
        font-size: 0.95rem;
    }

    .c-brand__logo {
        height: 32px;
        flex-shrink: 0;
    }
}

/* ===== Desktop mode: nav sits inline, no off-canvas ===== */
@media (min-width: 900px) {
    /* Hide hamburger + off-canvas UI */
    .c-btn--menu,
    .c-menu-overlay,
    .c-menu-panel {
        display: none !important;   /* lint-ok — desktop must win over the off-canvas JS state, which sets inline styles */
    }

    /* Put nav inline somewhere in your header actions area (you can reposition as desired) */
    .c-header-nav {
        display: flex;
        align-items: center;
    }

    .c-nav {
        display: flex;
        gap: 0.65rem;
        padding: 0;
    }

    .c-nav__item {
        display: block;
    }

    /* Desktop dropdown positioning.
       Sharp, glass, and edged instead of a rounded near-opaque card with a 50px
       shadow. The radius comes off because a full-width-ish panel flush under
       the bar is not a floater — it is an extension of the chrome — and the 2px
       accent line along its top is what says so. That line meets the open
       trigger's own accent line, and the two read as one connected object;
       that is only possible because the triggers are now full height and there
       is no bar showing between them.

       The base rule is the CLOSED state, so its transition is the EXIT; the
       open rule below is the ENTER. Getting that backwards gives a menu that is
       slow to leave and abrupt to arrive. Enter and exit are deliberately
       asymmetric — waiting for a thing to go is the most irritating motion
       there is. */
    .c-nav__menu {
        position: absolute;
        /* Explicit, not inherited from the static position. Once .c-nav__item
           became a flex row the panel's static position moved up BESIDE the
           link instead of below it, and the narrow dropdowns started overlapping
           the bar — measured trigger->panel gap -92px. `top: 100%` against the
           now-full-height item is the bar's own bottom edge, so the panel sits
           flush under it. Measured after: 0px. */
        top: 100%;
        right: -0.5rem;
        min-width: 16rem;
        max-height: calc(100vh - 120px);
        overflow-y: auto;
        padding: 0.4rem 0.3rem 0.3rem;
        border-radius: 0;
        background: var(--glass-panel);
        backdrop-filter: blur(30px) saturate(170%);
        -webkit-backdrop-filter: blur(30px) saturate(170%);
        border: 1px solid var(--border);
        border-top: 2px solid var(--accent);
        box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
        z-index: 1000;

        opacity: 0;
        transform: translateY(-8px);
        transition: opacity var(--t-exit), transform var(--t-exit);
        pointer-events: none;
    }

    /* The 14px invisible hover-bridge that used to live here is DELETED, not
       disabled. It existed to span the dead gap between a floating trigger chip
       and its panel; the full-height triggers below close that gap
       geometrically, so the bridge is patching a problem that no longer exists.
       Leaving it would be dead code that looks load-bearing. */

    /* Show state — the ENTER. Expo-out: fast to nearly there, then eases the
       last few percent, no overshoot. */
    .c-nav__menu:not([hidden]) {
        opacity: 1;
        transform: translateY(0);
        pointer-events: auto;
        transition: opacity var(--t-enter), transform var(--t-enter);
    }

    /* Scrollbar styling for long menus */
    .c-nav__menu::-webkit-scrollbar {
        width: 6px;
    }

    .c-nav__menu::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.05);
        border-radius: 3px;
    }

    .c-nav__menu::-webkit-scrollbar-thumb {
        background: rgba(255, 255, 255, 0.2);
        border-radius: 3px;
    }

    .c-nav__menu::-webkit-scrollbar-thumb:hover {
        background: rgba(255, 255, 255, 0.3);
    }

    /* Desktop: hide caret button if you want hover-only dropdown trigger
       (I prefer to keep it for accessibility; you can choose) */
    .c-nav__toggle { display: none; }

    /* ── FULL-HEIGHT NAV TRIGGERS ─────────────────────────────────────────────
       Measured on the live bar before this: bar box 53..148 (95px tall), trigger
       box 79..123 (44px) — so every trigger was a small centred chip floating in
       the bar with ~22px of dead bar above and below it.

       That gap is a menu bug, not a cosmetic one. Move the cursor from a trigger
       toward its panel and it crosses bar that belongs to neither, :hover ends,
       and the menu closes before the panel picks the cursor up. The demo hit
       this and the first fix was two invisible bridge pseudo-elements spanning
       the gap. It worked, and it patched the symptom.

       The real fix is geometric: stretch the trigger so its bottom edge IS the
       bar's bottom edge. Then the panel sits flush and the hover zone is
       contiguous BY CONSTRUCTION, with nothing to maintain. The bridge below is
       deleted rather than left as dead code.

       Side effect, and it is the good kind: a full-height trigger is a full-
       height column, which is Current's own .nav-top tab idiom — so the hover
       chip loses its radius, and the open trigger can grow a 2px accent edge
       along its bottom that meets the panel's accent edge along its top. Two
       flush lines read as one connected object. That is only possible because
       there is no longer 20px of bar between them. */
    /* MOVE the vertical padding off the bar and onto the brand, rather than
       cancelling it with a negative margin on the nav. Two earlier attempts at
       the negative-margin version both failed, and measuring is what showed why:
         · on the LINK — .c-nav__item is `display: grid` (the mobile row layout)
           and a grid row sizes to its item's MARGIN box, so the negation
           cancelled itself. Link came out 70px in a 92px bar.
         · on the NAV CONTAINER — a negative margin shrinks that child's
           contribution to the flex container's height, so the bar itself
           collapsed 95px -> 81px. Fighting the height algorithm to win a
           height.
       With the padding on the brand instead, the brand still drives the bar's
       height exactly as before, and every stretched sibling simply fills it. No
       arithmetic, nothing to keep in sync. */
    .l-header__inner { padding-block: 0; align-items: stretch; }
    .c-brand { padding-block: var(--header-pad-y); }
    .l-header__actions { align-items: stretch; }

    /* Every link in the chain has to stretch, including the <nav class="c-header-nav">
       that ss_render_primary_menu() wraps the list in — miss that one element and
       the trigger fills from the bar's top edge and stops 37px short of the
       bottom, which is what the first measurement after this change showed. */
    /* `.l-header__actions >` is load-bearing, not decoration. A later rule in
       this file — the "Route 1 nav containers" toggle — sets
       `.c-header-nav--desktop { display: block }` at the same 0,1,0 specificity,
       so source order was winning and this container stayed a block while
       everything inside it was told to stretch against nothing. Measured: the
       container was 81px and the nav inside it 44px. */
    .l-header__actions > .c-header-nav--desktop,
    .c-header-nav--desktop > .c-header-nav {
        display: flex;
        align-items: stretch;
    }
    .c-header-nav--desktop .c-nav { align-items: stretch; gap: 0; }
    .c-header-nav--desktop .c-nav__item {
        display: flex;
        align-items: stretch;
    }
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta) > .c-nav__link {
        position: relative;
        display: inline-flex;
        align-items: center;
        padding-block: 0;
        padding-inline: 0.9rem;
        border-radius: 0;
        transition: background-color var(--t-fast), color var(--t-fast);
    }

    /* The 2px accent edge along the trigger's BOTTOM — the same line the panel
       carries along its top. Flush against each other, trigger and panel read as
       one connected object rather than a tab and a floating sheet that happen to
       share a colour. This is only possible because the trigger's bottom edge is
       now the bar's bottom edge; with the old floating chips there were 22px of
       bar between the two lines. scaleX so it wipes rather than blinks. */
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta) > .c-nav__link::after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 2px;
        background: var(--accent);
        transform: scaleX(0);
        transition: transform var(--t);
    }

    /* Hover chip is a full-height column, which is Current's own .nav-top tab
       idiom — hence no radius on it. `:has()` covers the JS-driven open state,
       so a menu opened by click keeps its edge lit, not just a hovered one. */
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta):hover > .c-nav__link,
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta):focus-within > .c-nav__link,
    .c-header-nav--desktop .c-nav__item:has(.c-nav__toggle[aria-expanded="true"]) > .c-nav__link {
        color: var(--ink);
        background-color: var(--hover);
    }
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta):hover > .c-nav__link::after,
    .c-header-nav--desktop .c-nav__item:not(.c-nav__item--cta):focus-within > .c-nav__link::after,
    .c-header-nav--desktop .c-nav__item:has(.c-nav__toggle[aria-expanded="true"]) > .c-nav__link::after {
        transform: scaleX(1);
    }

    /* The CTA is a button, not a tab: it stays centred at its own size.
       It also carries the bar's padding, and that is deliberate. Once the nav
       stretches it stops CONTRIBUTING height, and the bar collapsed 95px -> 81px
       because only the brand was left to drive it. The bar's height should be
       set by its tallest real control plus the bar's padding — which is exactly
       what set it before this change — so the CTA is padded and the tabs stretch
       to whatever that comes to. Measured after: 92px, against 95px before. */
    .c-nav__item--cta {
        align-items: center;
        padding-block: var(--header-pad-y);
    }
}

/* Route 1 nav containers */
.c-header-nav--desktop { display: none; }
.c-header-nav--mobile  { display: block; }

@media (min-width: 900px) {
    .c-header-nav--desktop { display: block; }
    .c-header-nav--mobile  { display: none; }
}

/* ========== Contact Button CTA Styling ========== */

/* The Contact CTA. Chassis converted, interaction kept.
   Was a 100px pill on --green-gradient; now 6px flat. --accent-solid, NOT
   --accent: this carries white text, and white on #1b944b is 3.90:1 while
   #07792f is 5.55:1. A button is a green SURFACE, which is the one thing raw
   --accent is not.

   The lift and the glow SURVIVE. The demo's nav CTA dropped both, but the rule
   that outranks matching the demo is "never reduce the polish count", and the
   precedent for this exact situation is the quote button: keep the interaction
   mechanism for mechanism and change only the chassis. The glow just moves onto
   the accent it now sits on.

   The `!important` on colour is gone too — it was beating .c-nav__link, which
   has the same 0,1,0 specificity and comes EARLIER in the file, so the cascade
   already resolves this correctly without it. */
.c-nav__link--cta {
    background: var(--accent-solid);
    color: var(--ink-on-strong);
    padding: 0.7rem 1.5rem;
    border: 1px solid transparent;   /* so border-color has something to animate FROM */
    border-radius: var(--r);
    font-weight: 600;
    transition:
        background var(--t-fast),
        border-color var(--t-fast),
        box-shadow var(--t-fast),
        transform var(--t);
}

/* The same bloom as .c-btn--primary, on the owner's call — this is the site's
   other primary action and the two should read as one family. It already had
   the lift and the glow (kept deliberately during the cutover); what it lacked
   was the fill blooming and the bright accent edge. */
.c-nav__link--cta:hover {
    background: linear-gradient(135deg, var(--accent-solid-deep), var(--accent-solid), var(--accent-solid-deeper)); /* lint-ok: hover bloom, in sync with .c-btn--primary */
    border-color: var(--accent-text);
    transform: translateY(-2px);
    box-shadow: 0 4px 16px color-mix(in srgb, var(--accent-text) 32%, transparent);
    /* Restating the colour is not redundant. base.css has a global
       `a:hover { color: var(--color-link-hover) }` at specificity (0,1,1), which
       out-specifies `.c-nav__link--cta` at (0,1,0) — so dropping the old
       `!important` let the button's label turn ACCENT GREEN on a dark green
       fill. Measured: rgb(83,212,137) on rgb(10,106,42). This selector is (0,2,0)
       and wins honestly. */
    color: var(--ink-on-strong);
}

/* Adjust spacing for the CTA item in desktop nav */
@media (min-width: 900px) {
    .c-nav__item--cta {
        margin-left: 0.5rem;
    }
}

/* ========== Mega-nav (Services 4-category dropdown) ==========
   Used by the Services entry only, via $primary_menu's children_groups shape.
   `.c-nav__menu--mega` extends the base `.c-nav__menu` panel chrome (background,
   border, shadow, open/close transitions) — overrides width + inner layout.
   At desktop ≥900px: 4-col grid, all groups always visible, second-level
   toggles hidden. At mobile: vertical stack; tap a group toggle to expand
   that category's services. */

.c-mega-nav__grid {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.c-mega-nav__group {
    display: flex;
    flex-direction: column;
}

.c-mega-nav__group-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.25rem 0.5rem;
}

/* Section heading inside the mega-nav. Plain text, NOT a link.
   Quiet on desktop, more present on mobile (where the column header is the
   only thing distinguishing categories before the accordion expands). */
.c-mega-nav__group-label {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    flex: 1;
    min-width: 0;
    margin: 0;
    color: var(--color-menu-panel-text);
    font-weight: var(--fw-medium);
    font-size: 0.95rem;
    padding: 0.4rem 0.5rem;
}

.c-mega-nav__group-label i {
    font-size: 0.85rem;
    color: var(--green);
    width: 1rem;
    text-align: center;
    flex-shrink: 0;
}

/* Second-level (Services group) chevron. Desktop hides it (display:none below);
   only the mobile drawer renders it, so it matches the borderless top-level
   chevrons instead of the old boxed-chip look. */
.c-mega-nav__group-toggle {
    border: none;
    background: transparent;
    color: var(--color-menu-panel-text);
    opacity: 0.5;
    cursor: pointer;
    min-width: 44px;
    min-height: 44px;
    border-radius: 0;
    transition: color var(--t-fast), opacity var(--t-fast);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    flex-shrink: 0;
}

.c-mega-nav__group-toggle i {
    font-size: 0.75rem;
    transition: transform var(--t);
}

.c-mega-nav__group-toggle:hover,
.c-mega-nav__group-toggle:focus-visible {
    color: var(--green);
    opacity: 1;
}

.c-mega-nav__group-toggle[aria-expanded="true"] {
    color: var(--green);
    opacity: 1;
}

.c-mega-nav__group-toggle[aria-expanded="true"] i {
    transform: rotate(180deg);
}

.c-mega-nav__items {
    list-style: none;
    margin: 0;
    padding: 0 0 0.4rem 1.75rem;
}

.c-mega-nav__items > li {
    margin: 0;
}

.c-mega-nav__link {
    position: relative;
    display: block;
    padding: 0.45rem 0.75rem 0.45rem 1.1rem;
    margin: 0.1rem 0;
    border-radius: var(--r-sm);
    text-decoration: none;
    color: var(--color-menu-panel-text);
    font-size: 0.9rem;
    transition: background-color var(--t-fast);
}

.c-mega-nav__link::before {
    content: "";
    position: absolute;
    left: 0.4rem;
    top: 50%;
    width: 3px;
    height: 60%;
    background: var(--green);
    border-radius: 2px;
    transform: translate(-4px, -50%);
    opacity: 0;
    transition: opacity var(--t-fast), transform var(--t);
    pointer-events: none;
}

.c-mega-nav__link:hover,
.c-mega-nav__link:focus-visible {
    background: rgba(255, 255, 255, 0.06);
    outline: none;
}

.c-mega-nav__link:hover::before,
.c-mega-nav__link:focus-visible::before {
    opacity: 1;
    transform: translate(0, -50%);
}

/* A mega-nav row that leaves the site (Social Media Management, which lives on
   social.silverservers.com). Same row treatment, plus the same outbound glyph
   the header's external chips use — so the new tab isn't a surprise. The row
   goes flex only in this variant; the default stays display:block. */
.c-mega-nav__link--external {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.c-mega-nav__link-ext {
    font-size: 0.7em;
    opacity: 0.55;
    transition: opacity var(--t-fast);
}

.c-mega-nav__link--external:hover .c-mega-nav__link-ext,
.c-mega-nav__link--external:focus-visible .c-mega-nav__link-ext {
    opacity: 1;
}

.c-mega-nav__footer {
    margin-top: 0.5rem;
    padding: 0.6rem 0.75rem 0.25rem;
    border-top: 1px solid var(--color-menu-panel-border);
    text-align: right;
}

.c-mega-nav__see-all {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    text-decoration: none;
    color: var(--color-menu-panel-text);
    font-size: 0.85rem;
    font-weight: var(--fw-medium);
    padding: 0.4rem 0.7rem;
    border-radius: var(--r-sm);
    transition: background-color var(--t-fast), color var(--t-fast);
}

.c-mega-nav__see-all i {
    font-size: 0.75rem;
    transition: transform var(--t);
}

.c-mega-nav__see-all:hover,
.c-mega-nav__see-all:focus-visible {
    /* --accent-solid, not --green. White on #1b944b is 3.58:1; on #07792f it
       is 5.55:1. Measured by audit_hover_contrast.py, which scores HOVER
       states — audit_contrast.py structurally cannot see them, because a
       :hover rule contributes nothing to an un-hovered element's computed
       style. "--accent is a surface colour, not a white-text surface" was
       already a written rule; these four had simply never been checked. */
    background: var(--accent-solid);
    color: var(--white);
    outline: none;
}

.c-mega-nav__see-all:hover i,
.c-mega-nav__see-all:focus-visible i {
    transform: translateX(3px);
}

/* Mobile (drawer): items collapsed by default, reveal when group toggle expanded */
@media (max-width: 899.98px) {
    .c-mega-nav__group:has(.c-mega-nav__group-toggle[aria-expanded="false"]) > .c-mega-nav__items {
        display: none;
    }
}

/* Desktop: 4-col grid panel, group toggles hidden, items always visible */
@media (min-width: 900px) {
    /* TRIGGER-ANCHORED, like every other dropdown — owner's call, 2026-08-05.
       It was previously full-bleed (`position: fixed; left: 0; right: 0`),
       which made the Services menu behave unlike the other three and put a
       1440px-wide bar under a 70px trigger.

       The earlier note here said a panel this wide "cannot" be anchored,
       citing the demo's measurements: `left: 50%` ran 80px off the right edge
       at 1440, `right: 0` ran 506px off the left at 1000. Both were true of a
       panel capped at --wrap (1200px+). They are not a property of anchoring —
       they are a property of that WIDTH. At 46rem the panel is 736px and it
       inherits the base `right: -0.5rem` used by the narrow dropdowns, so it
       opens leftward from the trigger and sits flush under the bar. Measured
       at 1440: x 456..1192, comfortably inside.

       Below 1200 there is not room to open a 3-column panel leftward from a
       trigger that far right, so it drops to 2 columns and then 1 rather than
       overflowing. Verified with audit_dropdown_fit.py across the width grid.

       Everything else — glass, the 2px accent top edge meeting the trigger's
       own edge, enter/exit motion — comes from the base .c-nav__menu rule,
       which is the point: it is now the same object as its siblings. */
    .c-nav__menu--mega {
        width: min(46rem, calc(100vw - 2rem));
        max-height: calc(100vh - var(--header-h, 116px));
        padding: 1rem 0.9rem;
    }

    .c-mega-nav__grid {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 1.25rem;
    }

    .c-mega-nav__group {
        gap: 0.35rem;
    }

    .c-mega-nav__group-header {
        padding: 0.15rem 0 0.4rem;
        border-bottom: 1px solid var(--color-menu-panel-border);
        margin-bottom: 0.4rem;
    }

    .c-mega-nav__group-label {
        font-size: 0.72rem;
        font-family: var(--font-mono);
        text-transform: uppercase;
        letter-spacing: 0.06em;
        padding: 0.25rem 0.3rem;
        color: var(--color-text-muted);
        font-weight: var(--fw-medium);
    }

    .c-mega-nav__group-label i {
        font-size: 0.8rem;
        color: var(--green);
    }

    .c-mega-nav__group-toggle {
        display: none;
    }

    .c-mega-nav__items {
        padding: 0;
    }

    .c-mega-nav__link {
        font-size: 0.9rem;
        padding: 0.4rem 0.6rem 0.4rem 1rem;
        line-height: 1.3;
    }

    .c-mega-nav__link::before {
        left: 0.3rem;
    }

    .c-mega-nav__footer {
        margin-top: 1.25rem;
        padding: 0.85rem 0 0;
    }
}

/* Three columns are kept at EVERY desktop width, deliberately. Dropping to two
   below 1200 was tried and looked worse than the problem it solved: with three
   groups in a 2-column grid the third sits alone under the first with a column
   of empty panel beside it, and the panel grows from 349px tall to 546px.
   Measured, the 736px panel does fit at the desktop breakpoint anyway — at
   1000 the Services trigger's right edge is ~752, so the panel lands at x≈16 —
   so there was nothing to solve. `width: min(46rem, calc(100vw - 2rem))` on
   the rule above is the backstop if that ever stops being true. */

/* ========== Breadcrumb Component ========== */

.c-breadcrumb {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.875rem;
}

.c-breadcrumb__link {
    color: var(--color-text-muted);
    text-decoration: none;
    transition: color var(--t-fast);
}

.c-breadcrumb__link:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

.c-breadcrumb__separator {
    color: var(--color-text-muted);
    opacity: 0.5;
}

.c-breadcrumb__current {
    color: var(--color-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 400px;
}

/* ========== Site-Wide Width System ========== */
/* Main layout container (.l-content) defined above with:
   - max-width: 1440px
   - padding: 3em clamp(1.5rem, 4vw, 2rem)
   Use .c-block--narrow (680px) for narrower content areas */

/* Content section spacing */
.l-content__section {
    padding: 0;
    margin: 0;
}

.l-content__section + .l-content__section {
    margin-top: 3rem;
}

/* Article-specific widths */
.l-article {
    margin: auto;
    max-width: 1440px;
    width: 100%;
}

/* Archive page header */
.l-content > header {
    padding-top: 2rem;
    padding-bottom: 1.5rem;
}

/* Grid system - no padding on grid itself */
.l-content__grid {
    padding-left: 0 !important;   /* lint-ok — must beat .l-content's own inline-width padding on this one full-bleed template */
    padding-right: 0 !important;  /* lint-ok — as above */
}

.l-content__panel {
    padding: 0;
}

@media (max-width: 768px) {
    .l-content__section + .l-content__section {
        margin-top: 2rem;
    }
}

/* ========== Article Layout: Two-Column with Sidebar ========== */
/* Note: Basic .l-article styles are in blocks.css. This section handles the optional two-column layout with sidebar. */

/* Two-column grid wrapper - use this when you want a sidebar */
.l-article-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: 3rem;
    align-items: start;
}

@media (min-width: 960px) {
    .l-article-layout {
        grid-template-columns: minmax(0, 2.5fr) minmax(280px, 1fr);
        /* Explicit rows so the sidebar's "grid-row: 1 / -1" actually spans header + main.
           Without this, -1 collapsed to row 1 and the tall sidebar stretched the header
           row, dumping a huge gap under the name. The 1fr soaks up any extra at the bottom. */
        grid-template-rows: auto 1fr;
        column-gap: 4rem;
        row-gap: 0;
    }

    .l-article__header { grid-column: 1; grid-row: 1; }
    .l-article__main   { grid-column: 1; grid-row: 2; }

    .l-article__sidebar {
        grid-column: 2;
        grid-row: 1 / -1;
    }
}

.l-article__main {
    min-width: 0;
}

/* Sticky Sidebar */
.l-article__sidebar {
    position: sticky;
    top: calc(var(--header-height, 80px) + 2rem);
    align-self: start;
    display: flex;
    flex-direction: column;
    gap: 2rem;
    max-height: calc(100vh - var(--header-height, 80px) - 4rem);
    padding: 2rem 0 2.5rem;
}

/* Hide scrollbar but keep functionality */
.l-article__sidebar::-webkit-scrollbar {
    width: 4px;
}

.l-article__sidebar::-webkit-scrollbar-track {
    background: transparent;
}

.l-article__sidebar::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 2px;
}

.l-article__sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.2);
}

/* ========== Component: Article CTA ========== */

.c-article-cta {
    position: relative;
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: 0;
    padding: 2rem 1.75rem;
}

.c-article-cta::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--green-gradient);
}

.c-article-cta__title {
    font-family: var(--font-sans);
    font-size: var(--fs-h4);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    margin: 0 0 0.75rem;
    color: var(--color-text);
}

.c-article-cta__text {
    font-size: var(--fs-sm);
    line-height: var(--lh-relaxed);
    margin: 0 0 1.5rem;
    color: var(--color-text-muted);
}

.c-btn--cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.85rem 1.5rem;
    /* Was var(--green-gradient), whose light end is --green #1b944b. Measured
       on real pixels under the label: 3.63:1 at 1440 and 3.67:1 at 390, on
       every article and team page — 18 route/width combinations. Invisible to
       audit_contrast because a gradient leaves background-color transparent;
       audit_gradient_contrast.py samples the rendered pixels instead.
       Same fill as .c-btn--primary so the two CTAs are one family. */
    background: var(--accent-solid);
    color: var(--white);
    border: none;
    border-radius: var(--r);
    font-weight: var(--fw-semibold);
    font-size: var(--fs-sm);
    text-decoration: none;
    cursor: pointer;
    transition: transform var(--t), box-shadow var(--t-fast), filter var(--t-fast);
}

/* The same bloom as .c-btn--primary, so the two CTAs read as one family.
   `filter: brightness(1.1)` is gone with the gradient: brightening a fill is a
   contrast change nobody can predict from the source, which is how the AA
   failure above went unnoticed in the first place. The bloom's stops are
   tokens, so they can be measured. */
.c-btn--cta:hover {
    background: linear-gradient(135deg, var(--accent-solid-deep), var(--accent-solid), var(--accent-solid-deeper)); /* lint-ok: restored hover bloom, in sync with .c-btn--primary */
    border-color: var(--accent-text);
    transform: translateY(-2px);
    box-shadow: 0 8px 24px color-mix(in srgb, var(--accent-text) 32%, transparent);
    color: var(--white);
}

.c-btn--cta:not(:has(i, svg))::after {
    content: '\2192';
    transition: transform var(--t);
}

.c-btn--cta:not(:has(i, svg)):hover::after {
    transform: translateX(3px);
}

/* ========== Component: Sidebar Section ========== */

.c-sidebar-section {
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: 0;
    padding: 1.75rem 1.5rem;
    box-shadow: var(--shadow-subtle);
}

.c-sidebar-section__title {
    font-size: 1.1rem;
    font-weight: 600;
    margin: 0 0 1.5rem;
    color: var(--color-heading);
}

/* ========== Component: Sidebar QR Code ========== */

.c-sidebar-qr__text {
    font-size: 0.9rem;
    line-height: 1.5;
    margin: 0 0 1rem;
    color: var(--color-text-secondary);
}

.c-sidebar-qr__link {
    display: block;
}

.c-sidebar-qr__image {
    width: 100%;
    height: auto;
    border-radius: 8px;
}

/* ========== Component: AI Legend (Blake's Q-learning demo) ========== */

.c-ai-legend {
    list-style: none;
    margin: 0.85rem 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.35rem 0.85rem;
    font-size: var(--fs-xs);
    color: var(--color-text-muted);
}

.c-ai-legend li {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

.c-ai-legend__sw {
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 0.2rem;
    flex-shrink: 0;
    border: 1px solid rgba(255, 255, 255, 0.08);
}

.c-ai-legend__sw--start { background: #ffe066; }   /* lint-ok — must match ctx.fillStyle in blake-noble.php's canvas JS */
.c-ai-legend__sw--goal  { background: #17b75a; }   /* lint-ok — must match ctx.fillStyle in blake-noble.php's canvas JS */
.c-ai-legend__sw--wall  { background: #3d3d4c; }   /* lint-ok — must match ctx.fillStyle in blake-noble.php's canvas JS */
.c-ai-legend__sw--path  { background: linear-gradient(90deg, #0a2a38, #53d489); }   /* lint-ok — must match ctx.fillStyle in blake-noble.php's canvas JS */

/* ========== Component: Sidebar Tags ========== */

.c-sidebar-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* ========== Component: Button Full Width ========== */



/* ========== Component: Article Meta (Portfolio Extensions) ========== */

.c-article-meta__client,
.c-article-meta__date {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.c-article-meta__client {
    font-weight: 600;
    color: var(--color-heading);
}

.c-article-meta__label {
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
}

/* ========== Component: Sidebar Posts ========== */

/* Hairline-separated rows, which is this site's idiom for a list — the mobile
   nav rows, the contact extensions table, the footer columns and the platform
   spec rows all use it. Four articles previously stacked on a 1.25rem gap with
   no structure at all, which is the main reason the prefooter did not read as
   part of the same site as everything above it. The gap becomes row padding so
   the separator has something to separate. */
.c-sidebar-posts {
    display: flex;
    flex-direction: column;
}

.c-sidebar-post {
    border-bottom: 1px solid var(--color-border-subtle);
}

.c-sidebar-post:last-child {
    border-bottom: none;
}

.c-sidebar-post__link {
    display: flex;
    gap: 1rem;
    padding: 0.9rem 0.5rem;
    margin-inline: -0.5rem;
    text-decoration: none;
    transition: transform var(--t), background-color var(--t-fast);
}

/* The whole row is one anchor, so the whole row may light up. */
.c-sidebar-post__link:hover {
    transform: translateX(2px);
    background-color: var(--hover);
}

.c-sidebar-post__thumbnail {
    flex: 0 0 70px;
    width: 70px;
    height: 70px;
    /* was a hardcoded 8px — under the lint's 10px floor, so it survived the
       radius sweep while being off the 0/4/6 scale. */
    border-radius: var(--r-sm);
    overflow: hidden;
    background: var(--color-post-thumb-bg);
    border: 1px solid var(--color-post-thumb-border);
}

.c-sidebar-post__thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--t);
}

.c-sidebar-post__link:hover .c-sidebar-post__thumbnail img {
    transform: scale(1.05);
}

.c-sidebar-post__content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.c-sidebar-post__title {
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.4;
    margin: 0;
    color: var(--color-post-title);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    transition: color var(--t-fast);
}

/* Titles rest at --ink, so hovering them to --color-link-hover (also --ink
   since 2026-08-04) changed nothing — a dead hover on every article title in
   these lists. Caught on .c-related-post__title by audit_dead_hover.py; the
   others share the defect but hide from that audit, because it pairs a :hover
   rule with a base rule for the SAME selector and these are written as
   `.x__link:hover .x__title`, which has no resting twin to compare against.

   The direction differs from a body link ON PURPOSE. A green body link
   brightens toward white; a white card title tints toward the accent. Both move
   along the same axis, from opposite ends. */
.c-sidebar-post__link:hover .c-sidebar-post__title {
    color: var(--accent-text);
}

.c-sidebar-post__date {
    font-size: 0.8rem;
    color: var(--color-post-date);
    opacity: 0.8;
}

/* ========== Responsive Adjustments ========== */

@media (max-width: 959px) {
    .l-article-layout {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .l-article__sidebar {
        position: static;
        max-height: none;
        margin-top: 0rem;
    }
}
/* ========================================================================
   EDITORIAL TEMPLATE STYLES
   Article/Blog, Category, Team, Portfolio - NOT for AI page assembly
   ======================================================================== */

/* ========== Article Content Styles ========== */


/* ========== Articles Grid (Listing Page) ========== */

.c-article-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 1.5rem;
    margin-bottom: 2rem;
}

.c-article-card {
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: 0;
    overflow: hidden;
    transition: transform var(--t), box-shadow var(--t-fast);
}

.c-article-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-soft);
}

.c-article-card__image {
    display: block;
    width: 100%;
    aspect-ratio: 2 / 1;
    overflow: hidden;
}

.c-article-card__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--t);
}

.c-article-card:hover .c-article-card__image img {
    transform: scale(1.05);
}

.c-article-card__content {
    padding: 1.25rem;
}

.c-article-card__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.625rem;
    font-size: 0.813rem;
    color: var(--color-text-muted);
}

.c-article-card__category {
    color: inherit;
    text-decoration: none;
}

.c-article-card__category:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

.c-article-card__title {
    font-size: 1.125rem;
    font-weight: 600;
    margin-bottom: 0.625rem;
    line-height: 1.35;
}

.c-article-card__title a {
    color: inherit;
    text-decoration: none;
}

.c-article-card__title a:hover {
    color: var(--color-primary);
}

.c-article-card__excerpt {
    font-size: 0.938rem;
    color: var(--color-text-muted);
    margin-bottom: 0.875rem;
    line-height: 1.5;
}

.c-article-card__link {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--color-primary);
    text-decoration: none;
    font-weight: 500;
    font-size: var(--fs-sm);
}

.c-article-card__link:hover {
    text-decoration: underline;
}

/* ========== Pagination ========== */

.c-pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.5rem;
    padding: 2.5rem 0;
    flex-wrap: wrap;
}

.c-pagination__arrow {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 1rem;
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--color-text);
    text-decoration: none;
    background: var(--color-surface);
    border: 1px solid var(--color-btn-outline-border);
    border-radius: 0.5rem;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
    cursor: pointer;
}

.c-pagination__arrow:hover {
    background: var(--color-btn-outline-hover-bg);
    border-color: var(--color-text);
    color: var(--color-text);
}

.c-pagination__arrow:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.c-pagination__arrow--disabled {
    color: var(--color-text-muted);
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.c-pagination__pages {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0 0.5rem;
}

.c-pagination__page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.5rem;
    height: 2.5rem;
    padding: 0 0.5rem;
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--color-text);
    text-decoration: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 0.5rem;
    transition: background-color var(--t-fast), border-color var(--t-fast);
}

.c-pagination__page:hover {
    background: var(--color-btn-outline-hover-bg);
    border-color: var(--color-btn-outline-border);
}

.c-pagination__page:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* --accent-solid, not --primary (= --green #1b944b). White on #1b944b is
   3.90:1; on #07792f it is 5.55:1. This is the current page number — a white
   digit on a green chip — and it had gone unnoticed by audit_contrast.py for a
   second reason worth knowing: that audit skipped text runs shorter than TWO
   characters, so a page number "1" was never scored at all. Both the audit and
   the colour are fixed. */
.c-pagination__page--current {
    background: var(--accent-solid);
    color: var(--ink-on-strong);
    border-color: var(--accent-solid);
    cursor: default;
}

/* Deliberately inert: you are already on this page, so it does not react. */
.c-pagination__page--current:hover {
    background: var(--accent-solid);
    border-color: var(--accent-solid);
}

.c-pagination__ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2.5rem;
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
    user-select: none;
}

/* Mobile: hide Previous/Next text, show only arrows */
@media (max-width: 480px) {
    .c-pagination {
        gap: 0.25rem;
    }

    .c-pagination__arrow {
        padding: 0.5rem 0.75rem;
    }

    .c-pagination__pages {
        margin: 0 0.25rem;
    }

    .c-pagination__page {
        min-width: 2.25rem;
        height: 2.25rem;
    }
}

.c-empty-state {
    text-align: center;
    padding: 4rem 2rem;
}

/* ========== Topic Bar ========== */

.c-topic-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 1rem 0 1.5rem;
    font-size: var(--fs-sm);
}

.c-topic-bar__label {
    font-weight: 600;
    color: var(--color-text-muted);
}

.c-topic-bar__link {
    display: inline-block;
    padding: 0.5rem 1rem;
    color: var(--color-primary);
    text-decoration: none;
    border: 1px solid var(--color-card-border);
    border-radius: 0.5rem;
    background: var(--color-card-bg);
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), transform var(--t);
}

.c-topic-bar__link:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-light);
    transform: translateY(-1px);
}

.c-topic-bar__link--back {
    padding: 0.5rem 0.75rem;
}

/* --accent-solid, not --color-primary. This is the trap recorded in step 1 and
   never closed: --color-primary is used BOTH as a text colour and, here, as a
   background under white text. One token cannot be both. Measured before the
   fix: #f5f5f6 on #53d489 = 1.73:1. It survived because nothing had run
   audit_contrast.py on /articles/category/*. */
.c-topic-bar__link--active {
    border-color: var(--accent-solid);
    background: var(--accent-solid);
    color: var(--ink-on-strong);
}

.c-topic-bar__link--active:hover {
    background: var(--accent-solid-hover);
    border-color: var(--accent-solid-hover);
    color: var(--ink-on-strong);
}
/* ========== Category Navigation ========== */

/* ========== Category Filter (Horizontal) ========== */


/* ========== Featured Article (Hero) ========== */

.c-featured-article {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
    align-items: center;
    padding: 3rem 0 0 0;
}

.c-featured-article__image {
    display: block;
    border-radius: 0;
    overflow: hidden;
    aspect-ratio: 16 / 9;
    border: 1px solid var(--color-card-border);
}

.c-featured-article__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--t);
}

.c-featured-article:hover .c-featured-article__image img {
    transform: scale(1.02);
}

.c-featured-article__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    color: var(--color-text-muted);
}

.c-featured-article__category {
    color: inherit;
    text-decoration: none;
}

.c-featured-article__category:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

.c-featured-article__title {
    font-size: var(--fs-h2);
    font-weight: var(--fw-regular);
    line-height: 1.1;
    margin-bottom: 1rem;
}

.c-featured-article__title a {
    color: inherit;
    text-decoration: none;
}

.c-featured-article__title a:hover {
    color: var(--color-primary);
}

.c-featured-article__excerpt {
    font-size: var(--fs-lg);
    line-height: 1.6;
    color: var(--color-text-muted);
    margin-bottom: 1.5rem;
}

@media (max-width: 768px) {
    .c-featured-article {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .c-featured-article__title {
        font-size: var(--fs-xl);
    }
}

/* ========== Article Template Layout ========== */

.l-page__breadcrumb {
    padding: 1rem 0;
    border-bottom: 1px solid var(--color-card-border);
}

.l-article__hero {
    padding: 1.5rem 0 0.5rem;
}

.c-article-hero {
    margin: 0;
    border-radius: 0.5rem;
    overflow: hidden;
    max-width: 100%;
    display: flex;
    flex-direction: row;
    justify-content: center;
    max-height: 512px;
}

.c-article-hero img {
    object-fit: cover;
    width: 100%;
    display: block;
    border-radius: 0;
}

@media (max-width: 768px) {
    .c-article-hero img {
        max-height: 256px;
    }
}

.l-article__header {
    padding: 1.5rem 0 1rem;
}

.c-article-header__title {
    font-size: var(--fs-h1);
    font-weight: 700;
    line-height: 1.2;
    margin-bottom: 1.5rem;
}

.l-article__content {
    padding: 2rem 0 2.5rem;
}

.c-article-body {
    font-size: 1.063rem;
    line-height: 1.75;
}

.c-article-body > * + * {
    margin-top: 1.25em;
}

.c-article-body h2 {
    margin-top: 1.25rem;
    margin-bottom: 0.5em;
    font-size: clamp(1.5rem, 4vw, 1.875rem);
    padding-top: 1.75rem;
    border-top: 1px solid var(--color-card-border);
}

/* Remove excessive top margin from first heading for better layout */
.c-article-body > h2:first-child {
    margin-top: 0;
}

.c-article-body h3 {
    margin-top: 1.75em;
    margin-bottom: 0.5em;
    font-size: 1.375rem;
}

.c-article-body p {
    margin-bottom: 1.25em;
}

.c-article-body ul,
.c-article-body ol {
    padding-left: 1.5em;
    margin-bottom: 1.25em;
}

.c-article-body li {
    margin-bottom: 0.625em;
}

.c-article-body strong {
    font-weight: 600;
    color: var(--color-text);
}

.c-article-body a:not(.c-btn) {
    color: var(--color-primary);
    text-decoration: underline;
}

.c-article-body a:not(.c-btn):hover {
    color: var(--color-primary-dark);
}
/* ========== Article Meta Component ========== */
.c-article-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1.5rem 0;
    border-top: 1px solid var(--color-card-border);
    border-bottom: 1px solid var(--color-card-border);
    flex-wrap: wrap;
    gap: 1rem;
}
.c-article-meta__info {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: var(--fs-sm);
    color: var(--color-text-muted);
}
.c-article-meta__separator {
    opacity: 0.5;
}
.c-article-meta__category {
    font-family: var(--ff-mono);
    color: inherit;
    text-decoration: none;
}
.c-article-meta__category:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

/* ===================================
   ARTICLE AUTHOR BYLINE
   =================================== */

.c-article-author {
    display: flex;
    align-items: center;
}

.c-article-author__link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-decoration: none;
    color: inherit;
    transition: opacity var(--t-fast);
}

.c-article-author__link:hover {
    opacity: 0.8;
}

.c-article-author__avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    border: 2px solid var(--color-card-border);
}

.c-article-author__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.c-article-author__details {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.c-article-author__label {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 500;
}

.c-article-author__name {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--color-text);
}

.l-article__nav {
    padding: 2.5rem 0;
    border-top: 1px solid var(--color-card-border);
}

.c-article-nav {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
}

.c-article-nav__link {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    padding: 1.25rem;
    background: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: 0.5rem;
    text-decoration: none;
    transition: background-color var(--t-fast), border-color var(--t-fast);
}

.c-article-nav__link:hover {
    background: var(--color-bg);
    border-color: var(--color-primary);
}

.c-article-nav__link--prev {
    text-align: left;
}

.c-article-nav__link--next {
    text-align: right;
}

.c-article-nav__label {
    font-size: 0.813rem;
    font-family: var(--ff-mono);
    color: var(--color-text-muted);
}

.c-article-nav__title {
    font-size: 0.938rem;
    font-weight: 600;
    color: var(--color-text);
}

@media (max-width: 768px) {
    .c-article-nav {
        grid-template-columns: 1fr;
    }

    .c-article-nav__link--next {
        text-align: left;
    }
}

.l-article__related {
    padding: 2.5rem 0;
    background: transparent;
    border-top: 1px solid var(--color-card-border);
}

.c-related-posts__heading {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 1.5rem;
}

.c-related-posts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1.5rem;
}

.c-related-post {
    display: flex;
    flex-direction: column;
}

.c-related-post__image {
    display: block;
    aspect-ratio: 16 / 9;
    border-radius: 0.5rem;
    overflow: hidden;
    margin-bottom: 0.875rem;
}

.c-related-post__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--t);
}

.c-related-post:hover .c-related-post__image img {
    transform: scale(1.05);
}

.c-related-post__category {
    display: inline-block;
    font-size: 0.813rem;
    color: var(--color-text-muted);
    margin-bottom: 0.5rem;
    text-decoration: none;
}

.c-related-post__category:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

.c-related-post__title {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 0.375rem;
    line-height: 1.4;
}

.c-related-post__title a {
    color: inherit;
    text-decoration: none;
}

.c-related-post__title a:hover {
    color: var(--accent-text);
}

.c-related-post__date {
    display: block;
    font-size: 0.813rem;
}

/* ========== Editorial Responsive Adjustments ========== */

@media (max-width: 1024px) {
    .c-featured-article {
        gap: 2.5rem;
    }

    .c-featured-article__title {
        font-size: 1.875rem;
    }
}

@media (max-width: 768px) {
    .c-featured-article {
        grid-template-columns: 1fr;
        gap: 1.5rem;
        margin: 1.5rem 0 2rem;
    }

    .c-featured-article__title {
        font-size: 1.625rem;
    }

    .c-featured-article__excerpt {
        font-size: 1rem;
    }

    .c-article-grid {
        grid-template-columns: 1fr;
        gap: 1.25rem;
    }

    .c-article-nav {
        grid-template-columns: 1fr;
    }

    .c-related-posts {
        grid-template-columns: 1fr;
    }

    .l-article__hero {
        padding: 1rem 0 0.5rem;
    }

    .c-article-meta {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
    }

    .c-article-author__avatar {
        width: 40px;
        height: 40px;
    }

    .c-article-author__label {
        font-size: 0.6875rem;
    }

    .c-article-author__name {
        font-size: 0.875rem;
    }
}
/* ========== TEAM MEMBER COMPONENTS ========== */


/* Profile header for individual team member pages */
.c-profile-header {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 2rem;
    align-items: center;
    padding: 1.5rem 0 1rem;
}

.c-profile-header__image {
    aspect-ratio: 1 / 1;
    border-radius: 0;
    overflow: hidden;
    background: var(--color-card-border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

.c-profile-header__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.c-profile-header__content {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.c-profile-header__eyebrow {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    margin-bottom: 0.5rem;
}

.c-profile-header__name {
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    font-weight: 700;
    line-height: 1.15;
    margin-bottom: 0;
}

/* Optional one-line positioning statement under the name (fills the header, no void) */
.c-profile-header__tagline {
    margin: 0.9rem 0 0;
    font-size: 1.05rem;
    line-height: var(--lh-relaxed);
    color: var(--color-text-muted);
    max-width: 48ch;
}

/* Optional focus-area chips row under the tagline */
.c-profile-header__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1.1rem;
}

.c-profile-header__social {
    display: flex;
    gap: 0.6rem;
    margin-top: 1rem;
}
/* Skills list */



/* Staff profile header sits directly above the body content (row 1 → row 2);
   spacing comes from the header/content padding, no negative-margin band-aid needed. */

/* Responsive adjustments for team components */
@media (max-width: 768px) {
    .c-profile-header {
        grid-template-columns: 200px 1fr;
        gap: 1.5rem;
        padding: 1rem 0;
    }

}

@media (max-width: 560px) {
    .c-profile-header {
        grid-template-columns: 1fr;
        gap: 1rem;
        text-align: center;
        max-width: 320px;
        margin-inline: auto;
    }

    .c-profile-header__image {
        max-width: 240px;
        margin-inline: auto;
    }

    .c-profile-header__content {
        align-items: center;
    }

    .c-profile-header__social {
        justify-content: center;
    }

    .c-profile-header__name {
        font-size: 1.5rem;
    }

    .c-profile-header__eyebrow {
        font-size: 0.7rem;
    }
}
/* ========== PORTFOLIO COMPONENTS ========== */


.c-portfolio-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 1.5rem;
    margin-top: 2rem;
}

.c-portfolio-gallery__item {
    border-radius: 0.5rem;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.c-portfolio-gallery__item img {
    width: 100%;
    height: auto;
    display: block;
}

/* Responsive Portfolio Styles */
@media (max-width: 768px) {

    .c-portfolio-gallery {
        grid-template-columns: 1fr;
    }
}

/* ========== Party Mode Easter Egg ========== */
/* Dark mode + neon lights: dark background shifts subtly, elements get glowing box-shadows */

/* Subtle dark background color shift - stays moody */
@keyframes party-bg-dark {
    0%   { background-color: #1a0a2e; }  /* deep purple */   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { background-color: #0a1a2e; }  /* deep teal */   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { background-color: #2e0a1a; }  /* deep magenta */   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { background-color: #0a2e1a; }  /* deep green */   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { background-color: #2e1a0a; }  /* deep amber */   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { background-color: #1a0a2e; }  /* deep purple */   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

@keyframes party-neon {
    0%   { box-shadow: 0 0 10px 2px #a855f7, 0 0 25px 5px rgba(168, 85, 247, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { box-shadow: 0 0 10px 2px #06b6d4, 0 0 25px 5px rgba(6, 182, 212, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { box-shadow: 0 0 10px 2px #ec4899, 0 0 25px 5px rgba(236, 72, 153, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { box-shadow: 0 0 10px 2px #22c55e, 0 0 25px 5px rgba(34, 197, 94, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { box-shadow: 0 0 10px 2px #f59e0b, 0 0 25px 5px rgba(245, 158, 11, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { box-shadow: 0 0 10px 2px #a855f7, 0 0 25px 5px rgba(168, 85, 247, 0.4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

@keyframes party-neon-intense {
    0%   { box-shadow: 0 0 15px 4px #a855f7, 0 0 40px 10px rgba(168, 85, 247, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { box-shadow: 0 0 15px 4px #06b6d4, 0 0 40px 10px rgba(6, 182, 212, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { box-shadow: 0 0 15px 4px #ec4899, 0 0 40px 10px rgba(236, 72, 153, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { box-shadow: 0 0 15px 4px #22c55e, 0 0 40px 10px rgba(34, 197, 94, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { box-shadow: 0 0 15px 4px #f59e0b, 0 0 40px 10px rgba(245, 158, 11, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { box-shadow: 0 0 15px 4px #a855f7, 0 0 40px 10px rgba(168, 85, 247, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

/* Button background cycles through colors (overrides green gradient) */
@keyframes party-btn-bg {
    0%   { background: #a855f7; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { background: #06b6d4; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { background: #ec4899; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { background: #22c55e; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { background: #f59e0b; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { background: #a855f7; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

@keyframes party-text-glow {
    0%   { text-shadow: 0 0 10px #a855f7, 0 0 20px rgba(168, 85, 247, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { text-shadow: 0 0 10px #06b6d4, 0 0 20px rgba(6, 182, 212, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { text-shadow: 0 0 10px #ec4899, 0 0 20px rgba(236, 72, 153, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { text-shadow: 0 0 10px #22c55e, 0 0 20px rgba(34, 197, 94, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { text-shadow: 0 0 10px #f59e0b, 0 0 20px rgba(245, 158, 11, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { text-shadow: 0 0 10px #a855f7, 0 0 20px rgba(168, 85, 247, 0.5); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

@keyframes party-glow {
    0%   { filter: drop-shadow(0 0 12px #a855f7); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { filter: drop-shadow(0 0 12px #06b6d4); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { filter: drop-shadow(0 0 12px #ec4899); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { filter: drop-shadow(0 0 12px #22c55e); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { filter: drop-shadow(0 0 12px #f59e0b); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { filter: drop-shadow(0 0 12px #a855f7); }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

@keyframes party-accent {
    0%   { color: #a855f7; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    20%  { color: #06b6d4; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    40%  { color: #ec4899; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    60%  { color: #22c55e; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    80%  { color: #f59e0b; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
    100% { color: #a855f7; }   /* lint-ok — party-mode rave colours, deliberately off-palette */
}

/* Body gets subtle dark color shift */
.is-party-mode body {
    animation: party-bg-dark 5s ease-in-out infinite;
}

/* Header stays transparent to show body background */
.is-party-mode .l-header {
    background: transparent !important;   /* lint-ok — party mode overrides live chrome for a few seconds; scoped to a body class */
}

/* The thing you clicked gets the intense glow. This was on .c-theme-toggle
   until 2026-07-31; the toggle went away with the light theme and party mode's
   trigger moved to the decorative footer wordmark, so the effect moved with it.
   Better feedback than it was, too — the reaction now lands under the cursor
   instead of on a control at the other end of the page. */
.is-party-mode .c-brand-wordmark {
    animation: party-neon-intense 5s ease-in-out infinite, party-accent 5s ease-in-out infinite;
}

/* Logo gets filter glow */
.is-party-mode .c-brand__logo {
    animation: party-glow 5s ease-in-out infinite;
}

/* Primary buttons get background color cycle + neon glow (overrides green) */
.is-party-mode .c-btn--primary,
.is-party-mode .c-nav__link--cta {
    animation: party-btn-bg 5s ease-in-out infinite, party-neon-intense 5s ease-in-out infinite;
    background: #a855f7 !important;   /* lint-ok — party-mode rave colour, deliberately off-palette */ /* Initial state, animation takes over */
}
/* Cards get neon borders */
.is-party-mode .c-card,
.is-party-mode .c-pricing-card {
    animation: party-neon 5s ease-in-out infinite;
}

/* Form inputs get subtle glow */
.is-party-mode .c-form input,
.is-party-mode .c-form textarea {
    animation: party-neon 5s ease-in-out infinite;
}

/* Headings get text glow */
.is-party-mode h1,
.is-party-mode h2,
.is-party-mode .c-hero-title {
    animation: party-text-glow 5s ease-in-out infinite;
}

/* Footer */
.is-party-mode .l-footer {
    animation: party-neon 5s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
.is-party-mode body,
.is-party-mode .l-header,
.is-party-mode .c-brand-wordmark,
.is-party-mode .c-brand__logo,
.is-party-mode .c-btn--primary,
.is-party-mode .c-nav__link--cta,
.is-party-mode .c-card,
.is-party-mode .c-pricing-card,
.is-party-mode .c-form input,
.is-party-mode .c-form textarea,
.is-party-mode h1,
.is-party-mode h2,
.is-party-mode .c-hero-title,
.is-party-mode .l-footer {
        animation: none;
    }
}