/**
 * LeanCMS v2 — Chrome Styles
 *
 * Header, footer, navigation, and mobile menu styling.
 * Consumes CSS variables defined in config.css.
 */

/* ── Skip Link ────────────────────────────────────────── */
.skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    background: var(--color-brand-primary);
    color: #fff;
    padding: 8px 16px;
    z-index: 9999;
    text-decoration: none;
    font-size: 0.875rem;
    transition: top var(--transition-fast);
}

.skip-link:focus {
    top: 0;
}

.screen-reader-text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ── Header ────────────────────────────────────────────── */
.site-header {
    background-color: var(--header-bg);
    position: relative;
    z-index: 100;
}

/* Sticky header modifier */
.site-header--sticky {
    position: sticky;
    top: 0;
    /* Respect the configured header background; --header-bg-sticky lets a site
       opt into a distinct sticky colour (was a hardcoded brand fill). */
    background-color: var(--header-bg-sticky, var(--header-bg));
}

/* Transparent header modifier */
.site-header--transparent {
    background-color: transparent;
    --nav-bg-active: transparent;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    transition: background-color var(--transition-standard);
}

/* Transparent header gradient overlay — aids nav legibility over hero images.
   Height and opacity are configurable via _brand-config.json → overlays section. */
.site-header--transparent::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-gradient-height, 150px);
    background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, var(--header-gradient-start-opacity, 0.5)) 0%,
        rgba(0, 0, 0, var(--header-gradient-end-opacity, 0)) 100%
    );
    pointer-events: none;
    z-index: -1;
    transition: opacity var(--transition-standard);
}

/* Hide gradient once header has scrolled to solid background */
.site-header--transparent.site-header--scrolled::after {
    opacity: 0;
}

.site-header--transparent.site-header--sticky {
    position: fixed;
}

/* WP Admin Bar offset — push sticky/fixed headers below the 32px admin bar */
.admin-bar .site-header--sticky {
    top: 32px;
}

.admin-bar .site-header--transparent {
    top: 32px;
}

@media screen and (max-width: 782px) {
    /* The WP admin bar is position:absolute (not fixed) at <=782px — it scrolls
       away with the page. A sticky header must therefore anchor to 0, not the
       bar height, or a 46px gap opens once the bar scrolls off. */
    .admin-bar .site-header--sticky {
        top: 0;
    }
    .admin-bar .site-header--transparent {
        top: 46px;
    }
}

/* ── Smart sticky (hide-on-scroll-down, reveal-on-up) ───
   Opt-in "headroom" behaviour layered on a sticky header. JS (SmartSticky in
   theme.js) toggles .site-header--hidden based on scroll direction; CSS owns
   the slide. The translate is local to the header so the admin-bar/announcement
   offsets (which set `top`) still apply.                                       */
.site-header--smart {
    transition: transform var(--transition-standard, 0.3s ease);
    will-change: transform;
}

.site-header--smart.site-header--hidden {
    transform: translateY(-100%);
}

@media (prefers-reduced-motion: reduce) {
    .site-header--smart {
        transition: none;
    }
}

/* ── Sticky CTA / action bar ────────────────────────────
   Opt-in bottom-of-viewport action bar (see lcms_render_cta_bar + CtaBar in
   theme.js). Off-screen by default (translateY); JS adds .is-visible after the
   first scroll, and removes it on scroll-down (smart) or when the real footer
   is in view. Sits below the drawer (200) + search (120) but above content.    */
.lcms-cta-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    display: flex;
    justify-content: center;
    padding: 10px 16px;
    /* Clear the iOS home indicator. */
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--header-bg);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.12);
    transform: translateY(100%);
    transition: transform var(--transition-standard, 0.3s ease);
}

.lcms-cta-bar.is-visible {
    transform: translateY(0);
}

.lcms-cta-bar__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    max-width: 480px;
    padding: 14px 20px;
    font-weight: var(--font-weight-bold);
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    border-radius: var(--button-radius);
    /* Brand button-treatment parity (see .site-header__cta). */
    border: var(--button-border, none);
    background: var(--button-bg, var(--color-brand-accent));
    color: var(--button-color, #fff);
    box-shadow: var(--shadow-btn, var(--shadow-btn-on-brand, none));
    transition: background var(--transition-fast), color var(--transition-fast),
                transform var(--transition-fast), box-shadow var(--transition-fast);
}

.lcms-cta-bar__link:hover,
.lcms-cta-bar__link:focus-visible {
    background: var(--button-bg-hover, var(--color-brand-accent-hover));
    color: var(--button-color-hover, #fff);
    transform: translate(calc(-1 * var(--button-hover-lift)), calc(-1 * var(--button-hover-lift)));
    box-shadow: var(--shadow-btn-hover, var(--shadow-btn, var(--shadow-btn-on-brand-hover, var(--shadow-btn-on-brand, none))));
}

.lcms-cta-bar__link:active {
    transform: translate(var(--button-hover-lift), var(--button-hover-lift));
}

/* Mobile-only scope (default): the header CTA is hidden < 1024px, so this is
   where the CTA surfaces. The "all screens" variant drops this rule. */
@media screen and (min-width: 1024px) {
    .lcms-cta-bar--mobile {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lcms-cta-bar {
        transition: none;
    }
}

/* Scrolled state - fade in background */
.site-header--transparent.site-header--scrolled {
    background-color: var(--header-bg);
    --nav-bg-active: var(--nav-bg-hover);
}

/* Fixed/scrolled logo size — only shrink once user scrolls */
.site-header--scrolled .site-header__brand img,
.site-header--scrolled .site-header__brand .custom-logo,
.site-header--scrolled .site-header__logo {
    max-width: var(--logo-max-width-fixed, var(--logo-max-width));
    transition: max-width var(--transition-standard);
}

.site-header__inner {
    max-width: var(--content-max-width-wide);
    margin: 0 auto;
    /*
     * Padding lives here, not on .site-header, so the header's content
     * aligns with the rest of the page — a max-width box centered in the
     * full viewport, inset by its own padding, is the same padding model
     * every other page-width element uses (e.g. .lcms-with-sidebar).
     * Padding on the outer wrapper instead would center the inner box
     * within an already-narrower space, producing a small but real
     * horizontal offset from that content instead of lining up with it.
     */
    padding: var(--header-padding);
    display: flex;
    align-items: center;
    /* Gap between logo, nav and actions — brand-config: chrome.header_gap. */
    gap: var(--header-gap, 20px);
}

.site-header__brand a {
    color: var(--header-color, var(--color-text-light));
    font-family: var(--font-heading);
    font-weight: var(--font-weight-bold);
    font-size: 1.25rem;
    text-decoration: none;
}

.site-header__brand img,
.site-header__brand .custom-logo,
.site-header__logo {
    max-width: var(--logo-max-width);
    height: auto;
    transition: max-width var(--transition-standard);
}

/* Optional sub-brand next to the logo/site name (identity.header_byline).
   A muted, smaller companion label — deliberately understated relative to
   .site-header__brand a's bold 1.25rem so it reads as secondary, not a
   second title. Sites needing a different treatment (stacked under the
   logo, different weight/colour) override via their own CSS — this is
   just a sane default that works whether the brand is an image logo or
   text (renders as a flex sibling either way). */
.site-header__brand {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.site-header__byline {
    color: var(--header-color, var(--color-text-light));
    opacity: 0.65;
    font-family: var(--font-heading);
    font-weight: var(--font-weight-normal, 400);
    font-size: 0.9rem;
    white-space: nowrap;
}

/* Mobile/Desktop logo switching */
.site-header__logo--desktop {
    display: none !important;
}

.site-header__logo--mobile {
    display: block !important;
}

@media screen and (min-width: 1024px) {
    .site-header__logo--desktop {
        display: block !important;
    }

    .site-header__logo--mobile {
        display: none !important;
    }
}

/* Header actions (CTA + mobile toggle) */
.site-header__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    /* Gap within the actions group (CTA + toggle) — brand-config: chrome.actions_gap. */
    gap: var(--header-actions-gap, 12px);
}

/* On mobile the desktop nav (which carries margin-left:auto on >=1024px) is
   hidden, so the actions group would otherwise sit left beside the logo. Push it
   to the right edge — logo-left / controls-right is the standard mobile header. */
@media screen and (max-width: 1023px) {
    .site-header__actions {
        margin-left: auto;
    }
}

/* Header CTA button */
.site-header__cta {
    display: none;
    align-items: center;
    justify-content: center;
    /* Match nav item height + text size so the header reads as one row.
       Padding/size come from the same brand-config tokens the nav uses;
       the CTA stays distinct via its bold weight + accent background. */
    padding: var(--nav-padding);
    font-size: var(--nav-font-size, 1rem);
    font-weight: var(--font-weight-bold);
    text-decoration: none;
    border-radius: var(--button-radius);
    /* Brand button-treatment parity: border + offset shadow + hover-lift track
       the same tokens as .btn, so bordered/brutalist/retro themes style the
       header CTA too. All default to no-op when their tokens are unset. */
    border: var(--button-border, none);
    background: var(--button-bg, var(--color-brand-accent));
    color: var(--button-color, #fff);
    box-shadow: var(--shadow-btn, var(--shadow-btn-on-brand, none));
    transition: background var(--transition-fast), color var(--transition-fast),
                transform var(--transition-fast), box-shadow var(--transition-fast);
}

.site-header__cta:hover {
    background: var(--button-bg-hover, var(--color-brand-accent-hover));
    color: var(--button-color-hover, #fff);
    /* Unset --button-hover-lift → invalid transform → `none` (no movement). */
    transform: translate(calc(-1 * var(--button-hover-lift)), calc(-1 * var(--button-hover-lift)));
    box-shadow: var(--shadow-btn-hover, var(--shadow-btn, var(--shadow-btn-on-brand-hover, var(--shadow-btn-on-brand, none))));
}

.site-header__cta:active {
    transform: translate(var(--button-hover-lift), var(--button-hover-lift));
}

@media screen and (min-width: 1024px) {
    .site-header__cta {
        display: inline-flex;
    }
}

/* ── Centered nav layout modifier ─────────────────────── */
.site-header--nav-centered .site-header__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
}

.site-header--nav-centered .site-header__actions {
    grid-column: 3;
}

/* ── Primary Navigation (Desktop) ─────────────────────── */
.site-nav--desktop {
    display: none;
    margin-left: auto;
}

@media screen and (min-width: 1024px) {
    .site-nav--desktop {
        display: block;
        margin-left: auto;
    }

    .site-header--nav-centered .site-nav--desktop {
        margin-left: 0;
    }
}

.site-nav__list {
    list-style: none;
    display: flex;
    /* Gap between nav items — brand-config: chrome.nav.gap. */
    gap: var(--nav-gap, 4px);
    margin: 0;
    padding: 0;
}

.site-nav__list li a {
    display: block;
    padding: var(--nav-padding);
    background-color: var(--nav-bg);
    color: var(--nav-color);
    font-size: var(--nav-font-size, 1rem);
    font-weight: var(--font-weight-normal);
    text-decoration: none;
    /* Casing token (G36) — brand-config typography.nav_transform. */
    text-transform: var(--nav-transform, none);
    /* Nav highlight radius cascades from brand config: dedicated --nav-radius
       if set, otherwise the base brand --border-radius. */
    border-radius: var(--nav-radius, var(--border-radius));
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.site-nav__list li a:hover {
    background-color: var(--nav-bg-hover);
    color: var(--nav-color-hover);
}

.site-nav__list li.current-menu-item > a {
    background-color: var(--nav-bg-active);
    color: var(--nav-color-hover);
}

/* Sub-menu (Desktop) */
.site-nav__list li {
    position: relative;
}

.site-nav__list .sub-menu {
    list-style: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 200px;
    background-color: var(--nav-bg-submenu, var(--nav-bg));
    display: none;
    z-index: 110;
    padding: 0;
    margin: 0;
}

.site-nav__list li:hover > .sub-menu,
.site-nav__list li:focus-within > .sub-menu {
    display: block;
}

.site-nav__list .sub-menu a {
    padding: 10px 20px;
    font-size: 0.85rem;
}

/* ── Mobile Menu Toggle ───────────────────────────────── */
.mobile-menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    cursor: pointer;
    color: var(--header-color, var(--color-text-light));
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    transition: color var(--transition-fast);
}

.mobile-menu-toggle:hover {
    color: var(--nav-color-hover);
}

@media screen and (min-width: 1024px) {
    .mobile-menu-toggle {
        display: none;
    }
}

/* ── Header Search ─────────────────────────────────────
   Phase 1 ships the full-overlay presentation. The panel carries a
   `lcms-search--{mode}` modifier + `data-search-mode` attribute so future
   presentation modes (below-header dropdown, inline expand) slot in as
   additional blocks here without touching markup. Tokens fall back to brand
   chrome vars so the search chrome tracks the rest of the header.            */
.site-header__search-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    cursor: pointer;
    color: var(--header-color, var(--color-text-light));
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    transition: color var(--transition-fast);
}

.site-header__search-toggle:hover,
.site-header__search-toggle:focus-visible {
    color: var(--nav-color-hover);
}

/* Panel — hidden by default; each lane reveals it on open. Also resets the UA
   popover box so our layout fully owns positioning. The two reveal rules below
   are kept SEPARATE on purpose: a browser without Popover support treats
   `:popover-open` as an invalid selector and drops only that rule, leaving the
   `.is-open` (manual fallback) rule intact. Merging them into one selector list
   would let the invalid one take the whole rule down with it.                 */
.lcms-search {
    display: none;
    border: 0;
    padding: 0;
    margin: 0;
    max-width: none;
    max-height: none;
    color: inherit;
    overflow: visible;
}

.lcms-search:popover-open {
    display: block;
}

.lcms-search.is-open {
    display: block;
}

/* ── Overlay mode (default) ──────────────────────────── */
.lcms-search--overlay {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    background: var(--lcms-search-overlay-bg, rgba(15, 23, 42, 0.72));
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

/* Hide the UA backdrop — the panel itself is the dim layer, so the two lanes
   (popover + manual fallback) look identical. */
.lcms-search--overlay::backdrop {
    background: transparent;
}

.lcms-search--overlay .lcms-search__inner {
    position: relative;
    width: min(640px, 100% - 40px);
    margin: 12vh auto 0;
    padding: 28px;
    background: var(--color-bg-primary, #fff);
    border-radius: var(--lcms-input-radius, var(--button-radius, 8px));
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

.lcms-search__close {
    position: absolute;
    top: 8px;
    right: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    cursor: pointer;
    color: var(--color-text-primary);
    background: transparent;
    border: none;
    border-radius: var(--border-radius, 4px);
    transition: background-color var(--transition-fast);
}

.lcms-search__close:hover,
.lcms-search__close:focus-visible {
    background: var(--color-bg-secondary, rgba(0, 0, 0, 0.06));
}

/* Editable lead-in above the field. */
.lcms-search__heading {
    margin: 8px 0 16px;
    padding-right: 40px; /* clear the close button */
    font-family: var(--font-heading, var(--font-body));
    font-size: 1.5rem;
    font-weight: var(--font-weight-bold);
    line-height: 1.2;
    color: var(--color-text-primary);
}

/* Give the form room below the close affordance when there is no heading.
   Inner children are [close, form], so the form is the 2nd child here; with a
   heading present it becomes the 3rd child and the heading provides the
   spacing instead. */
.lcms-search--overlay .lcms-search__inner > .lcms-search-form:nth-child(2) {
    margin-top: 28px;
}

/* ── Live search (.lcms-search--live) ──────────────────
   Layers instant results + the ⌘K hint over a presentation. Added by the Live
   Results toggle on the overlay and dropdown presentations; the result/status
   chrome below is presentation-agnostic.                                       */

/* ⌘K hint on the toggle — desktop only (keyboard shortcut is a desktop cue). */
.site-header__search-kbd {
    display: none;
}

@media screen and (min-width: 1024px) {
    .site-header__search-toggle .site-header__search-kbd {
        display: inline-block;
        margin-left: 2px;
        padding: 1px 5px;
        font-family: var(--font-body);
        font-size: 0.7rem;
        line-height: 1.4;
        color: var(--header-color, var(--color-text-light));
        background: color-mix(in oklch, currentColor 14%, transparent);
        border-radius: 4px;
        opacity: 0.75;
    }
}

/* Status line (Searching… / No results …). */
.lcms-search__status {
    margin: 12px 0 0;
    font-size: 0.9rem;
    color: var(--color-text-secondary, var(--color-text-primary));
    opacity: 0.85;
}

/* Results list. */
.lcms-search__results {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    max-height: min(50vh, 420px);
    overflow-y: auto;
    border-top: 1px solid var(--color-bg-secondary, rgba(0, 0, 0, 0.08));
}

.lcms-search__result {
    margin: 0;
}

.lcms-search__result-link {
    display: block;
    padding: 12px 10px;
    color: var(--color-text-primary);
    text-decoration: none;
    border-radius: var(--border-radius, 4px);
    transition: background-color var(--transition-fast);
}

.lcms-search__result-title {
    display: block;
    font-weight: var(--font-weight-bold);
    line-height: 1.3;
}

.lcms-search__result-excerpt {
    margin-top: 2px;
    font-size: 0.85rem;
    line-height: 1.4;
    /* Inherit the link's current colour (which flips on hover/active) and just
       mute it, so the preview keeps contrast in both the resting and hover
       states instead of vanishing into the hover background. */
    color: inherit;
    opacity: 0.75;
    /* Keep previews to two tidy lines regardless of the server word cap. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Hover + active-descendant (keyboard) share the same highlight. */
.lcms-search__result-link:hover,
.lcms-search__result[aria-selected="true"] .lcms-search__result-link {
    background: var(--nav-bg-hover, var(--color-bg-secondary, rgba(0, 0, 0, 0.06)));
    color: var(--nav-color-hover, var(--color-text-primary));
}

@media (prefers-reduced-motion: reduce) {
    .lcms-search__result-link,
    .lcms-search__close,
    .site-header__search-toggle {
        transition: none;
    }
}

/* ── Dropdown presentation (below header) ───────────────
   Anchors to .site-header, which is always a containing block (relative by
   default; sticky/absolute/fixed in its other states), so top:100% sits just
   under the bar across every header config. In flow → no top-layer popover;
   opens via the JS class-toggle (.is-open) lane with Escape + click-outside.  */
.lcms-search--dropdown {
    position: absolute;
    top: 100%;
    right: 0;
    width: min(420px, calc(100vw - 32px));
    margin-top: 8px;
    background: var(--color-bg-primary, #fff);
    border-radius: var(--lcms-input-radius, var(--button-radius, 8px));
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
    z-index: 120; /* above the desktop sub-menus (110) */
}

.lcms-search--dropdown .lcms-search__inner {
    padding: 16px;
}

/* Dropdowns close on Escape / click-outside / selecting a result, so the X
   would only collide with the full-width input — drop it. */
.lcms-search--dropdown .lcms-search__close {
    display: none;
}

@media screen and (max-width: 640px) {
    .lcms-search--dropdown {
        right: 8px;
        left: 8px;
        width: auto;
    }
}

/* ── Inline-expand presentation ─────────────────────────
   An opaque strip absolutely positioned over the header row — out of flow, so
   nav/CTA never shift. The icon stays put and the field animates open over the
   existing header elements (covering the hamburger too on small screens, which
   follows the user's intent). Static only (no live results).                  */
.lcms-search--inline,
.lcms-search--inline.is-open {
    /* Override the base display:none so the width can animate (display:none
       cannot transition). The higher-specificity .is-open selector also wins
       over the generic .lcms-search.is-open{display:block} rule. */
    display: flex;
}

.lcms-search--inline {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    align-items: center;
    width: 0;
    max-width: 100%;
    overflow: hidden;
    background: var(--header-bg);
    z-index: 120;
    transition: width var(--transition-standard, 0.25s ease);
}

.lcms-search--inline.is-open {
    width: min(560px, 100%);
    padding: 0 12px;
}

.lcms-search--inline .lcms-search__inner {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.lcms-search--inline .lcms-search-form {
    order: 1;
    flex: 1;
    margin: 0;
}

/* The submit button is redundant in the strip — Enter submits the form. */
.lcms-search--inline .lcms-search-form__submit {
    display: none;
}

/* Close sits in flow at the right end of the strip (where the icon was). */
.lcms-search--inline .lcms-search__close {
    position: static;
    order: 2;
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    color: var(--header-color, var(--color-text-light));
}

@media (prefers-reduced-motion: reduce) {
    .lcms-search--inline {
        transition: none;
    }
}

/* ── Mobile Menu Drawer ───────────────────────────────── */
/* DaisyUI drawer base - ensure it works without DaisyUI loaded */
.drawer {
    display: flex;
    width: 100%;
}

.drawer-toggle {
    position: absolute;
    height: 0;
    width: 0;
    appearance: none;
    opacity: 0;
}

.drawer-content {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    width: 100%;
}

/* ── Boxed container ───────────────────────────────────
   Whole-site frame: header + content + footer sit in a centred column with
   the surround showing around it. Off by default; engaged when the brand
   config sets layout.container = "boxed", which adds the `lcms-boxed` body
   class (theme functions.php). Targets #main-wrapper — the universal shell
   present in both the header-on (DaisyUI drawer) and header-off branches;
   .drawer-side is position:fixed so the off-canvas mobile menu is unaffected.
   The --site-* tokens (brand config) size/colour the frame, each with a
   fallback so the class alone still produces a usable box. frame_bg takes any
   CSS background value, so colours and gradients both work. An image surround
   is deferred (theme-option asset, layered above this var) — see
   docs/planning/ENHANCEMENT-CANDIDATES.md §3.1. */
body.lcms-boxed {
    background: var(--site-frame-bg, var(--color-bg-secondary));
    /* Viewport-locked so a gradient surround spans the browser height and
       reads identically on every page, instead of stretching to the full
       (variable) page height. Harmless for a flat colour; irrelevant on
       mobile, where the box is full-width and the surround isn't shown. */
    background-attachment: fixed;
}

body.lcms-boxed #main-wrapper {
    max-width: var(--site-max-width, 1280px);
    margin-inline: auto;
    background: var(--color-bg-primary, #ffffff);
    box-shadow: var(--site-frame-shadow, 0 0 60px rgba(0, 0, 0, 0.08));
}

.drawer-side {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 100%;
    pointer-events: none;
    z-index: 200;
    display: flex;
    justify-content: flex-end;
    overflow: hidden;
}

.drawer-overlay {
    position: fixed;
    inset: 0;
    background-color: rgba(0, 0, 0, 0);
    cursor: pointer;
    transition: background-color var(--transition-standard);
}

.mobile-menu {
    width: var(--mobile-drawer-width, 300px);
    max-width: 85vw;
    height: 100%;
    background-color: var(--mobile-drawer-bg, var(--color-bg-primary));
    transform: translateX(100%);
    transition: transform var(--transition-standard);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Drawer Open State */
.drawer-toggle:checked ~ .drawer-side {
    pointer-events: auto;
}

.drawer-toggle:checked ~ .drawer-side .drawer-overlay {
    background-color: rgba(0, 0, 0, 0.5);
}

.drawer-toggle:checked ~ .drawer-side .mobile-menu {
    transform: translateX(0);
}

/* Mobile Menu Header.
   header_bg defaults transparent (= drawer bg, today's look); a brand can set a
   dark band (chrome.mobile.header_bg) so a white-on-dark logo reads. */
.mobile-menu__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    background-color: var(--mobile-drawer-header-bg, transparent);
    border-bottom: 1px solid var(--mobile-drawer-border, var(--color-bg-secondary));
}

.mobile-menu__brand a {
    color: var(--mobile-drawer-header-color, var(--color-text-primary));
    font-family: var(--font-heading);
    font-weight: var(--font-weight-bold);
    font-size: 1.125rem;
    text-decoration: none;
}

.mobile-menu__brand img,
.mobile-menu__brand .custom-logo {
    max-width: 80px;
    height: auto;
}

.mobile-menu__close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    cursor: pointer;
    color: var(--mobile-drawer-header-color, var(--color-text-secondary));
    background: transparent;
    border: none;
    padding: 0;
    border-radius: var(--border-radius);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.mobile-menu__close:hover {
    background-color: var(--color-bg-secondary);
    color: var(--color-text-primary);
}

/* Mobile Menu Navigation */
.mobile-menu__nav {
    flex: 1;
    padding: 16px 0;
}

.mobile-menu__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.mobile-menu__list li a {
    display: block;
    padding: 14px 24px;
    color: var(--mobile-drawer-color, var(--color-text-primary));
    font-size: 1rem;
    font-weight: var(--font-weight-normal);
    text-decoration: none;
    border-bottom: 1px solid var(--mobile-drawer-border, var(--color-bg-secondary));
    transition: background-color var(--transition-fast);
}

.mobile-menu__list li a:hover,
.mobile-menu__list li.current-menu-item > a {
    background-color: var(--color-bg-secondary);
    color: var(--mobile-drawer-accent, var(--color-brand-accent));
}

/* Mobile Sub-menu */
.mobile-menu__list .sub-menu {
    list-style: none;
    margin: 0;
    padding: 0;
    background-color: var(--color-bg-secondary);
}

.mobile-menu__list .sub-menu a {
    padding-left: 40px;
    font-size: 0.9rem;
    border-bottom-color: var(--color-bg-primary);
}

/* Accordion sub-menus (LCMS_Mobile_Nav_Walker).
   Parent items get a real <button> disclosure toggle. With no JS the sub-menu
   renders expanded (every link reachable); theme.js adds
   .mobile-menu__list--enhanced, which collapses sub-menus until opened. */
.mobile-menu__list .menu-item-has-children {
    position: relative;
}

.mobile-menu__list .menu-item-has-children > a {
    /* Leave room for the toggle button so the label never runs under it. */
    padding-right: 60px;
}

.mobile-menu__submenu-toggle {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 52px;
    padding: 0;
    background: transparent;
    border: none;
    color: var(--mobile-drawer-color, var(--color-text-secondary));
    cursor: pointer;
}

.mobile-menu__submenu-toggle:hover {
    color: var(--color-text-primary);
}

.mobile-menu__chevron {
    transition: transform var(--transition-fast);
}

.mobile-menu__submenu-toggle[aria-expanded="true"] .mobile-menu__chevron {
    transform: rotate(180deg);
}

/* Collapsed-by-default only once JS has enhanced the list. */
.mobile-menu__list--enhanced .mobile-menu__sub {
    display: none;
}

.mobile-menu__list--enhanced .menu-item-has-children.is-open > .mobile-menu__sub {
    display: block;
}

/* ── Mobile Menu Footer: CTA + contact ────────────────── */
.mobile-menu__footer {
    margin-top: auto;
    padding: 16px 24px 24px;
    border-top: 1px solid var(--mobile-drawer-border, var(--color-bg-secondary));
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Full-width drawer CTA. Self-styled from the same brand tokens as the desktop
   header CTA (.site-header__cta) so the two match, rather than depending on the
   plugin's DaisyUI .btn classes resolving inside the drawer. Other treatments
   (e.g. a quiet text link) are a per-site custom-CSS override. */
.mobile-menu__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: var(--nav-padding);
    font-size: var(--nav-font-size, 1rem);
    font-weight: var(--font-weight-bold);
    text-decoration: none;
    border-radius: var(--button-radius);
    /* Brand button-treatment parity (see .site-header__cta). */
    border: var(--button-border, none);
    background: var(--button-bg, var(--color-brand-accent));
    color: var(--button-color, #fff);
    box-shadow: var(--shadow-btn, var(--shadow-btn-on-brand, none));
    transition: background var(--transition-fast), color var(--transition-fast),
                transform var(--transition-fast), box-shadow var(--transition-fast);
}

.mobile-menu__cta:hover {
    background: var(--button-bg-hover, var(--color-brand-accent-hover));
    color: var(--button-color-hover, #fff);
    transform: translate(calc(-1 * var(--button-hover-lift)), calc(-1 * var(--button-hover-lift)));
    box-shadow: var(--shadow-btn-hover, var(--shadow-btn, var(--shadow-btn-on-brand-hover, var(--shadow-btn-on-brand, none))));
}

.mobile-menu__cta:active {
    transform: translate(var(--button-hover-lift), var(--button-hover-lift));
}

.mobile-menu__contact {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.mobile-menu__contact a {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--mobile-drawer-color, var(--color-text-secondary));
    font-size: 0.9rem;
    text-decoration: none;
    transition: color var(--transition-fast);
}

.mobile-menu__contact a:hover {
    color: var(--mobile-drawer-accent, var(--color-brand-accent));
}

.mobile-menu__contact svg {
    flex-shrink: 0;
}

/* ── Popover lane (Option B) ───────────────────────────
   theme.js promotes .mobile-menu to a Popover where the API is supported,
   adding .mobile-menu--popover. Top-layer popovers are positioned against the
   viewport (not their DOM parent), so re-anchor as a right-side drawer here.
   The checkbox lane above is untouched and remains the no-JS fallback. */
.mobile-menu--popover {
    position: fixed;
    inset: 0 0 0 auto; /* pin right, full height */
    margin: 0;
    width: var(--mobile-drawer-width, 300px);
    max-width: 85vw;
    height: 100%;
    max-height: 100%;
    border: 0;
    padding: 0;
    /* .drawer-side sets pointer-events:none (re-enabled by :checked in the
       checkbox lane); the popover lane never checks the box, so opt the
       promoted panel back in explicitly. */
    pointer-events: auto;
    transform: translateX(100%);
    transition:
        transform var(--transition-standard),
        overlay var(--transition-standard) allow-discrete,
        display var(--transition-standard) allow-discrete;
}

.mobile-menu--popover:popover-open {
    transform: translateX(0);
}

/* Animate in from off-screen when first shown (transition from display:none). */
@starting-style {
    .mobile-menu--popover:popover-open {
        transform: translateX(100%);
    }
}

.mobile-menu--popover::backdrop {
    background-color: rgba(0, 0, 0, 0);
    transition:
        background-color var(--transition-standard),
        overlay var(--transition-standard) allow-discrete,
        display var(--transition-standard) allow-discrete;
}

.mobile-menu--popover:popover-open::backdrop {
    background-color: rgba(0, 0, 0, 0.5);
}

@starting-style {
    .mobile-menu--popover:popover-open::backdrop {
        background-color: rgba(0, 0, 0, 0);
    }
}

/* Respect reduced-motion across both lanes. */
@media (prefers-reduced-motion: reduce) {
    .mobile-menu,
    .mobile-menu--popover,
    .drawer-overlay,
    .mobile-menu--popover::backdrop,
    .mobile-menu__chevron {
        transition: none;
    }
}

/* Hide desktop nav at mobile */
@media screen and (max-width: 1023px) {
    .site-header__inner {
        padding: var(--header-padding-mobile);
    }

    .site-header__brand img,
    .site-header__brand .custom-logo {
        max-width: var(--logo-max-width-mobile);
    }
}

/* Hide mobile menu at desktop */
@media screen and (min-width: 1024px) {
    .drawer-side {
        display: none;
    }
}

/* ── Footer ────────────────────────────────────────────── */
.site-footer {
    background-color: var(--footer-bg);
    color: var(--footer-color);
    margin-top: auto;
}

/* Row 1: Main Footer */
.site-footer__main-inner {
    max-width: var(--content-max-width-wide);
    margin: 0 auto;
    /* Padding lives here, not on .site-footer__main — see the matching
       note on .site-header__inner above. */
    padding: var(--footer-padding, 40px 20px);
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 40px;
    /* Vertical (cross-axis) alignment of the three columns. */
    align-items: var(--footer-columns-align, start);
    /*
     * Horizontal alignment of the content *inside* each column — a separate
     * axis, driven by --footer-columns-content-align (start | center | end).
     * text-align handles the inline content; the brand/social/image flex
     * containers below read the same var so all three columns stay in sync.
     * Each fallback preserves the original per-column default (brand left,
     * social centered, image right) when the var is unset.
     */
    text-align: var(--footer-columns-content-align, start);
}

/* Col 1: Brand + Contact */
.site-footer__brand {
    display: flex;
    flex-direction: column;
    align-items: var(--footer-columns-content-align, start);
    gap: 16px;
}

.site-footer__logo-link,
.site-footer__logo-wp {
    display: inline-block;
}

.site-footer__logo,
.site-footer__logo-wp img,
.site-footer__logo-wp .custom-logo {
    max-width: var(--footer-logo-max-width, 160px);
    height: auto;
}

.site-footer__title {
    font-family: var(--font-heading);
    font-weight: var(--font-weight-bold);
    font-size: 1.25rem;
    color: var(--footer-color);
    text-decoration: none;
}

.site-footer__contact {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.site-footer__contact-item {
    font-size: 0.875rem;
    line-height: 1.5;
    opacity: 0.85;
}

.site-footer__contact-item a {
    color: var(--footer-color);
    text-decoration: none;
    transition: opacity var(--transition-fast);
}

.site-footer__contact-item a:hover {
    opacity: 1;
    text-decoration: underline;
}

/* Col 2: Social */
.site-footer__social {
    display: flex;
    flex-direction: column;
    align-items: var(--footer-columns-content-align, center);
    gap: 12px;
}

.site-footer__heading {
    font-weight: var(--font-weight-bold);
    letter-spacing: 0.05em;
    margin: 0;
    color: var(--footer-color);
}

.site-footer__social-list {
    list-style: none;
    display: flex;
    gap: 8px;
    margin: 0;
    padding: 0;
}

.site-footer__social-list a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    color: var(--footer-color);
    background-color: rgba(255, 255, 255, 0.1);
    border-radius: var(--border-radius);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.site-footer__social-list a:hover {
    background-color: var(--color-brand-accent);
    color: #fff;
}

/* Col 3: Footer Image */
.site-footer__image {
    display: flex;
    align-items: start;
    justify-content: var(--footer-columns-content-align, flex-end);
}

.site-footer__feature-img {
    max-width: var(--footer-feature-max-width, 300px);
    height: auto;
    border-radius: var(--border-radius);
}

/* Row 2: Imprint Bar */
.site-footer__imprint {
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.site-footer__imprint-inner {
    max-width: var(--content-max-width-wide);
    margin: 0 auto;
    /* Padding lives here, not on .site-footer__imprint — see the matching
       note on .site-header__inner above. */
    padding: 16px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.site-footer__copy {
    font-size: 0.8rem;
    opacity: 0.7;
    white-space: nowrap;
}

/* 3-col grid when footer nav is visible: left / center (page-centered) / right */
.site-footer__imprint-inner--with-nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
}

.site-footer__imprint-inner--with-nav .site-footer__agency {
    text-align: right;
}

.site-footer__nav {
    display: flex;
    justify-content: center;
}

.site-footer__list {
    list-style: none;
    display: flex;
    gap: 0;
    margin: 0;
    padding: 0;
}

.site-footer__list a {
    display: block;
    padding: 4px 12px;
    color: var(--footer-color);
    font-size: 0.8rem;
    text-decoration: none;
    opacity: 0.7;
    transition: opacity var(--transition-fast);
}

.site-footer__list a:hover {
    opacity: 1;
}

.site-footer__agency {
    font-size: 0.8rem;
    opacity: 0.7;
    white-space: nowrap;
}

.site-footer__agency a {
    color: var(--footer-color);
    text-decoration: none;
    transition: opacity var(--transition-fast);
}

.site-footer__agency a:hover {
    opacity: 1;
    text-decoration: underline;
}

/* Footer Mobile */
@media screen and (max-width: 1023px) {
    .site-footer__main-inner {
        grid-template-columns: 1fr;
        text-align: center;
        gap: 30px;
    }

    .site-footer__brand {
        align-items: center;
    }

    .site-footer__logo,
    .site-footer__logo-wp img,
    .site-footer__logo-wp .custom-logo {
        max-width: var(--footer-logo-max-width-mobile, 120px);
    }

    .site-footer__social {
        align-items: center;
    }

    .site-footer__image {
        justify-content: center;
    }

    .site-footer__imprint-inner,
    .site-footer__imprint-inner--with-nav {
        display: flex;
        flex-direction: column;
        text-align: center;
        gap: 12px;
    }

    .site-footer__imprint-inner--with-nav .site-footer__agency {
        text-align: center;
    }
}

/* ── Footer: columns variation ─────────────────────────── */
.site-footer__cols {
    max-width: var(--content-max-width-wide);
    margin: 0 auto;
    padding: var(--footer-padding, 40px 20px);
    display: flex;
    flex-direction: column;
    gap: 2.5rem;
}

.site-footer__row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--footer-columns-gap, 2.5rem);
    align-items: start;
}

/* Row 1 newsletter and row 3 legal menu each span the last two columns. */
.site-footer__row--1 .site-footer__cell--newsletter,
.site-footer__row--3 .site-footer__cell--legal {
    grid-column: span 2;
}

.site-footer__row--3 {
    align-items: center;
    border-top: 1px solid var(--color-border, rgba(255, 255, 255, 0.15));
    padding-top: 1.5rem;
}

.site-footer__cell {
    min-width: 0;
}

.site-footer__newsletter {
    margin-top: 0.5rem;
}

/* Match the newsletter cell: small gap under the "Follow Us" heading.
   Scoped to the columns social cell so the default footer's flex-gap
   social block is untouched. */
.site-footer__cell--social .site-footer__social-list {
    margin-top: 0.5rem;
}

/* Contact icon list */
.site-footer__contact-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.site-footer__contact-item,
.site-footer__contact-item > a {
    display: inline-flex;
    align-items: flex-start;
    gap: 0.6rem;
    color: var(--footer-color);
    text-decoration: none;
}

.site-footer__contact-item > a:hover {
    color: var(--color-brand-accent, var(--footer-color));
}

.site-footer__contact-icon {
    display: inline-flex;
    flex-shrink: 0;
    line-height: 1;
}

/* Vertical footer menu (row 2) */
.site-footer__menu-list {
    list-style: none;
    margin: 0;
    padding: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.site-footer__menu-list a {
    color: var(--footer-color);
    text-decoration: none;
}

.site-footer__menu-list a:hover {
    color: var(--color-brand-accent, var(--footer-color));
}

/* Horizontal legal menu (row 3) */
.site-footer__legal-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    justify-content: flex-end;
}

.site-footer__legal-list a {
    color: var(--footer-color);
    text-decoration: none;
    font-size: 0.9rem;
}

.site-footer__legal-list a:hover {
    color: var(--color-brand-accent, var(--footer-color));
}

@media screen and (max-width: 768px) {
    .site-footer__row {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .site-footer__row--1 .site-footer__cell--newsletter,
    .site-footer__row--3 .site-footer__cell--legal {
        grid-column: auto;
    }

    .site-footer__row--3 {
        align-items: start;
    }

    .site-footer__legal-list {
        justify-content: flex-start;
    }
}

/* ── 404 Page ──────────────────────────────────────────────
   A 404 is an error response, not a content page — a simple centered recovery
   block on the page background. It opts out of the decorative system-header
   band + divider (title-band features for list pages like search/archive), and
   the header renders SOLID here rather than transparent (lcms_header_is_transparent
   returns false on 404): a solid header is position:sticky, so it reserves its
   space, keeps light nav legible, and never overlaps this content. */
.error-404 {
    min-height: 60vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-section) 20px;
    text-align: center;
}

.error-404__inner {
    max-width: 500px;
}

/* Decorative oversized error code — aria-hidden in markup, so the real <h1>
   is the human message below (better for SR/SEO than an "404" heading). */
.error-404__code {
    font-size: clamp(72px, 12vw, 120px);
    font-weight: var(--font-weight-bold);
    line-height: 1;
    color: var(--color-brand-primary);
    margin: 0 0 8px;
}

.error-404__title {
    font-size: var(--font-size-h2, 2rem);
    margin: 0 0 16px;
}

.error-404__message {
    font-size: 1.1rem;
    color: var(--color-text-secondary);
    margin: 0 0 30px;
}

/* 404 recovery — search + primary-menu fallback (mirrors the search
   empty-state so "nothing found" is consistent across both surfaces). */
.error-404__search {
    max-width: 420px;
    margin: 0 auto 30px;
    text-align: left;
}

.error-404__menu-label {
    font-size: 0.9rem;
    color: var(--color-text-secondary);
    margin: 0 0 10px;
}

.error-404__menu ul {
    list-style: none;
    margin: 0 0 30px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 20px;
}

.error-404__menu a {
    color: var(--color-brand-primary);
    text-decoration: none;
    font-weight: var(--font-weight-bold);
}

.error-404__menu a:hover {
    text-decoration: underline;
}

/* ── System / article reading column ───────────────────────
   One shared measure for system pages (search, 404) and article pages
   (post-single, comments) so they read at a consistent width. Defaults to the
   brand-config narrow measure (lcms-core.css); set --lcms-article-measure in a
   site theme.css for a distinct article column. --lcms-system-header-bg fills a
   system-page title BAND edge-to-edge when set (default transparent) — the
   measure only caps the inner content, never the band. The system-header trio
   (--lcms-system-header-bg / -color / -accent) is intentionally NOT defaulted
   at :root: a hard :root default here would lose the cascade to the brand
   config's own :root inline style (equal specificity, and chrome.css loads
   later), silently overriding a synced value back to transparent. Each
   consuming rule carries its own var() fallback instead, so an unset token
   falls back to transparent / the light-page tokens, while a brand-set value
   wins cleanly. */
:root {
    --lcms-article-measure: var(--lcms-measure-narrow, 760px);
}

/* ── Search Results Page ───────────────────────────────── */
/* Band + inner: the header/body BANDS span full width (so a site can give the
   title section a full-width background via --lcms-system-header-bg); the INNER
   wrappers cap to the shared article reading column. */
.search-page__header {
    background-color: var(--lcms-system-header-bg, transparent);
    padding: var(--spacing-section) 20px;
    border-bottom: 1px solid var(--color-bg-secondary);
    /* Centre the title + count + form, matching the centered post header. */
    text-align: center;
    /* Positioned ancestor for an optional absolute bottom divider (swish). */
    position: relative;
}

/* A decorative bottom divider replaces the hairline border. */
.search-page__header--has-divider {
    border-bottom: 0;
}

/* Overlay-header clearance. A transparent header is position:absolute (out of
   flow), so a theme system template's top content tucks under it. When the
   overlay header is active (body.lcms-header-transparent) give it extra top
   room, tunable per-site via chrome.system_header_pad_top; unset → the standard
   section pad, so in-flow (solid) headers are unaffected.

   Covers the theme templates that KEEP the overlay header: search (its styled
   dark title band), the blog listing + non-LCMS page fallback (.content-default),
   and the sidebar layout. The 404, blog archives, and single posts render a
   solid (sticky, in-flow) header instead of the overlay (see
   lcms_header_is_transparent()), so they need no clearance. LCMS block pages are
   also excluded — they render via the plugin with a full-bleed hero meant to sit
   under the transparent header. */
body.lcms-header-transparent .search-page__header,
body.lcms-header-transparent .content-default,
body.lcms-header-transparent .lcms-with-sidebar {
    padding-top: var(--lcms-system-header-pad-top, var(--spacing-section));
}

/* Mobile clearance — the overlay header is a different height on small screens
   (smaller logo, mobile padding). Falls back to the desktop pad, then the
   section pad, so the mobile token is purely additive. Matches the chrome
   mobile breakpoint (--header-padding-mobile engages here too). */
@media screen and (max-width: 1023px) {
    body.lcms-header-transparent .search-page__header,
    body.lcms-header-transparent .content-default,
    body.lcms-header-transparent .lcms-with-sidebar {
        padding-top: var(--lcms-system-header-pad-top-mobile, var(--lcms-system-header-pad-top, var(--spacing-section)));
    }
}

.search-page__header-inner {
    max-width: var(--lcms-article-measure);
    margin: 0 auto;
}

.search-page__body {
    padding: 40px 20px var(--spacing-section);
}

.search-page__body-inner {
    max-width: var(--lcms-article-measure);
    margin: 0 auto;
}

.search-page__title {
    margin: 0 0 8px;
    /* Band ink. Unset → inherits the page text colour (dark on a light band);
       a brand sets system_header_color for a dark band. */
    color: var(--lcms-system-header-color, inherit);
}

.search-page__title em {
    font-style: italic;
    color: var(--lcms-system-header-accent, var(--color-brand-primary));
}

.search-page__count {
    color: var(--lcms-system-header-color, var(--color-text-secondary));
    font-size: 0.95rem;
    margin: 0 0 20px;
}

.search-page__form {
    max-width: 480px;
    margin: 0 auto;
}

/* ── Search Form (used by get_search_form everywhere) ──── */
.lcms-search-form {
    display: flex;
    gap: 8px;
    width: 100%;
    align-items: stretch;
}

/* Compact inline search bar — distinct LAYOUT from the stacked .lcms-form
   substrate, but consumes the same control tokens (lcms-forms.css :root) so
   border/radius/focus track the brand. Kills the old hardcoded purple ring. */
.lcms-search-form__input {
    flex: 1;
    min-width: 0;
    padding: 10px 14px;
    font-family: var(--font-body);
    font-size: 0.95rem;
    line-height: 1.4;
    color: var(--lcms-input-fg, var(--color-text-primary));
    background-color: var(--color-bg-primary);
    border: 1px solid var(--lcms-input-border, var(--color-bg-secondary));
    border-radius: var(--lcms-input-radius, var(--button-radius, 4px));
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.lcms-search-form__input:focus-visible {
    outline: 2px solid transparent;
    outline-offset: 2px;
    border-color: var(--lcms-input-accent, var(--color-brand-primary));
    box-shadow: 0 0 0 3px var(--lcms-input-ring, color-mix(in oklch, var(--color-brand-primary) 20%, transparent));
}

.lcms-search-form__submit {
    flex-shrink: 0;
}

@media screen and (max-width: 640px) {
    .lcms-search-form {
        flex-direction: column;
        gap: 6px;
    }
}

.search-page__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 30px;
}

.search-result__title {
    margin: 0 0 4px;
    font-size: var(--font-size-h3);
}

.search-result__title a {
    color: var(--color-brand-primary);
    text-decoration: none;
}

.search-result__title a:hover {
    text-decoration: underline;
}

.search-result__permalink {
    margin: 0 0 8px;
    color: var(--color-text-secondary);
    font-size: 0.85rem;
    word-break: break-word;
}

.search-result__excerpt {
    color: var(--color-text-primary);
    line-height: 1.55;
}

.search-page__nav {
    margin-top: 50px;
}

.search-page__empty {
    text-align: center;
    padding: 30px 0;
}

.search-page__empty-message {
    font-size: 1.05rem;
    color: var(--color-text-secondary);
    margin: 0 0 30px;
}

.search-page__empty-message em {
    font-style: italic;
    color: var(--color-brand-primary);
}

.search-page__menu-label {
    font-size: 0.9rem;
    color: var(--color-text-secondary);
    margin: 0 0 10px;
}

.search-page__menu ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 20px;
}

.search-page__menu a {
    color: var(--color-brand-primary);
    text-decoration: none;
    font-weight: var(--font-weight-bold);
}

.search-page__menu a:hover {
    text-decoration: underline;
}

/* ── Comments ──────────────────────────────────────────────
   The comment FORM inherits the `.lcms-form` substrate (inc/forms.php). These
   rules own the list + thread layout only. */
.lcms-comments {
    max-width: var(--lcms-article-measure);
    margin: 50px auto 0;
}

.lcms-comments__title {
    font-size: 1.4rem;
    font-weight: var(--font-weight-bold);
    margin: 0 0 24px;
}

.lcms-comments__list {
    list-style: none;
    margin: 0 0 40px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.lcms-comments__list .children {
    list-style: none;
    margin: 24px 0 0;
    padding-left: 24px;
    border-left: 2px solid var(--color-border, #e5e5e5);
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.lcms-comments__list .comment-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lcms-comments__list .comment-author {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: var(--font-weight-bold);
}

.lcms-comments__list .comment-author .avatar {
    border-radius: 9999px;
}

.lcms-comments__list .comment-meta {
    font-size: 0.85rem;
    color: var(--color-text-secondary);
}

.lcms-comments__list .comment-meta a {
    color: inherit;
    text-decoration: none;
}

.lcms-comments__closed {
    color: var(--color-text-secondary);
    font-style: italic;
    margin: 0 0 24px;
}

/* Comment form (#respond / #commentform). The form carries .lcms-form, so it
   reads --lcms-form-measure; for the comment context we widen it to 48rem to
   match the comment column (.lcms-comments) rather than the global 32rem. */
.lcms-comments .comment-respond {
    --lcms-form-measure: var(--lcms-article-measure);
    margin-top: 40px;
}

/* Reply title ("Leave a Reply") — spacing so it isn't flush with the form. */
.lcms-comments .comment-reply-title {
    margin: 0 0 1.25rem;
    font-size: 1.4rem;
    font-weight: var(--font-weight-bold);
}

/* Lead line on the password gate + comment-form intro. text-wrap: pretty
   avoids a lone last-word widow (e.g. "…view it." dropping "it" alone);
   degrades to normal wrapping where unsupported. */
.lcms-form__lead {
    margin: 0 0 1rem;
    color: var(--color-text-secondary, #6c757d);
    text-wrap: pretty;
}

/* ── Single Post (classic article view) ────────────────── */
.post-single {
    padding: var(--spacing-section) 20px;
}

/* Composed (compositor) content self-gutters via each block's px-5, so the
   wrapper's 20px horizontal padding would double up on mobile. Cancel it for
   the composed content only — block px-5 becomes the sole content gutter
   (matching layout mode). Header / meta / chrome / classic-prose keep the
   wrapper gutter. (-20px matches the .post-single horizontal padding above.) */
.post-single__content--composed {
    margin-inline: -20px;
}

.post-single__inner {
    max-width: var(--lcms-article-measure);
    margin: 0 auto;
}

.post-single__header {
    margin-bottom: 30px;
    text-align: center;
}

.post-single__categories {
    margin: 0 0 12px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.8rem;
    font-weight: var(--font-weight-bold);
    color: var(--color-brand-primary);
}

.post-single__categories a {
    color: inherit;
    text-decoration: none;
}

.post-single__categories a:hover { text-decoration: underline; }

.post-single__title {
    margin: 0 0 16px;
    line-height: 1.2;
}

.post-single__meta {
    color: var(--color-text-secondary);
    font-size: 0.9rem;
    margin: 0;
}

.post-single__meta-sep {
    margin: 0 8px;
    opacity: 0.5;
}

.post-single__featured {
    margin: 0 0 30px;
}

.post-single__featured img {
    width: 100%;
    height: auto;
    /* Optional height cap (brand-config layout.article_image_max_height). Unset
       → none = natural height; when set, a tall image is cropped to the cap
       (full-bleed width) rather than letterboxed. */
    max-height: var(--lcms-article-image-max-height, none);
    object-fit: cover;
    object-position: center;
    border-radius: var(--border-radius, 6px);
}

/* Classic-article typography removed (0.30.425): compositor articles render
   through `.prose`, which owns the heading rhythm, measure, and element spacing.
   The old `.post-single__content` rules only applied to a layout-less classic
   post and fought prose. Archived at
   docs/archive/post-single-classic-typography.css — restore there (or converge
   classic posts onto prose) if a raw-the_content post needs styling. */

.post-single__footer {
    margin-top: 40px;
    padding-top: 20px;
    border-top: 1px solid var(--color-bg-secondary);
}

.post-single__tags {
    color: var(--color-text-secondary);
    font-size: 0.9rem;
    margin: 0;
}

.post-single__tags-label {
    font-weight: var(--font-weight-bold);
    margin-right: 4px;
}

.post-single__tags a {
    color: var(--color-brand-primary);
    text-decoration: none;
    margin-right: 8px;
}

.post-single__tags a:hover { text-decoration: underline; }

/* Post navigation */
.post-nav {
    max-width: 760px;
    margin: 40px auto 0;
    padding: 30px 20px 0;
    border-top: 1px solid var(--color-bg-secondary);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.post-nav__link {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px;
    border-radius: var(--border-radius, 6px);
    background: var(--color-bg-secondary);
    color: var(--color-text-primary);
    text-decoration: none;
    transition: background var(--transition-fast);
}

.post-nav__link:hover {
    background: var(--color-bg-brand-light, var(--color-bg-secondary));
}

.post-nav__link--prev { text-align: left; grid-column: 1; }
.post-nav__link--next { text-align: right; grid-column: 2; }

.post-nav__direction {
    font-size: 0.85rem;
    color: var(--color-text-secondary);
    font-weight: var(--font-weight-bold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.post-nav__title {
    font-size: 1rem;
    line-height: 1.3;
}

@media screen and (max-width: 640px) {
    .post-nav {
        grid-template-columns: 1fr;
    }
    .post-nav__link--next { grid-column: 1; }
}

/* ── Archive ───────────────────────────────────────────── */
.archive-page {
    padding: var(--spacing-section) 20px;
}

.archive-page__inner {
    max-width: var(--content-max-width);
    margin: 0 auto;
}

.archive-page__header {
    margin-bottom: 40px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--color-bg-secondary);
}

.archive-page__title {
    margin: 0 0 8px;
}

.archive-page__description {
    color: var(--color-text-secondary);
    margin: 8px 0 0;
}

.archive-page__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 30px;
}

@media screen and (min-width: 768px) {
    .archive-page__list {
        grid-template-columns: repeat(2, 1fr);
    }
}

.post-card {
    display: flex;
    flex-direction: column;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-bg-secondary);
    border-radius: var(--border-radius, 6px);
    overflow: hidden;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.post-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}

.post-card__thumb {
    display: block;
    overflow: hidden;
}

.post-card__thumb img {
    width: 100%;
    height: auto;
    display: block;
    transition: transform var(--transition-fast);
}

.post-card:hover .post-card__thumb img {
    transform: scale(1.03);
}

.post-card__body {
    padding: 20px;
    display: flex;
    flex-direction: column;
    flex: 1;
}

.post-card__meta {
    color: var(--color-text-secondary);
    font-size: 0.85rem;
    margin: 0 0 8px;
}

.post-card__title {
    margin: 0 0 12px;
    font-size: var(--font-size-h3);
    line-height: 1.3;
}

.post-card__title a {
    color: var(--color-brand-primary);
    text-decoration: none;
}

.post-card__title a:hover { text-decoration: underline; }

.post-card__excerpt {
    color: var(--color-text-primary);
    line-height: 1.55;
    margin-bottom: 16px;
    flex: 1;
}

.post-card__more {
    color: var(--color-brand-primary);
    text-decoration: none;
    font-weight: var(--font-weight-bold);
    align-self: flex-start;
}

.post-card__more:hover { text-decoration: underline; }

.archive-page__nav {
    margin-top: 50px;
}

.archive-page__empty {
    text-align: center;
    padding: 60px 20px;
    color: var(--color-text-secondary);
}
