/*
Theme Name: MOOD
Theme URI:
Author: Tavish Keegan
Author URI:
Description: A portfolio and creative-studio block theme. Editorial typography, a warm monochrome palette, and generous whitespace built for showcasing work. Edit everything in the Site Editor.
Version: 0.18.55
Requires at least: 6.4
Tested up to: 6.5
Requires PHP: 7.4
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: mood
Tags: block-theme, full-site-editing, portfolio, one-column, custom-colors, custom-logo, editor-style, wide-blocks, block-styles
*/

/* Most styling lives in theme.json. Anything below is for nuances the editor can't express. */

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

.wp-block-post-title a,
.wp-block-site-title a {
    text-decoration: none;
}

.wp-block-post-title a:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
}

.wp-block-navigation .wp-block-navigation-item__content {
    text-decoration: none;
}

.wp-block-navigation .wp-block-navigation-item__content:hover {
    color: var(--wp--preset--color--accent);
}

/* ─────────────────────────────────────────────────────────────
   Logo show/hide — driven by body class set per page template
   ───────────────────────────────────────────────────────────── */

.mood-logo { line-height: 0; }
.mood-logo a { display: inline-block; line-height: 0; }
.mood-logo img { display: block; }

/* ─────────────────────────────────────────────────────────────
   Empty columns collapse on mobile — when a Columns block
   stacks (≤781px in WP core), an empty column would become
   dead vertical space. Hide it instead so the remaining
   columns flow naturally.
   ───────────────────────────────────────────────────────────── */

@media (max-width: 781px) {
    .wp-block-column:empty,
    .wp-block-column:not(:has(*)) {
        display: none !important;
    }
}

/* ─────────────────────────────────────────────────────────────
   Tight content pairings — block-gap is suppressed between
   blocks that form a single visual unit, so global Block
   Spacing only kicks in at major section transitions.
     • paragraph → paragraph (continuous prose)
     • eyebrow   → heading   (label + headline pair)
   ───────────────────────────────────────────────────────────── */

p + p,
.wp-block-mood-eyebrow + h1,
.wp-block-mood-eyebrow + h2,
.wp-block-mood-eyebrow + h3,
.wp-block-mood-eyebrow + h4,
.wp-block-mood-eyebrow + h5,
.wp-block-mood-eyebrow + h6,
.wp-block-mood-eyebrow + .wp-block-heading,
.wp-block-mood-eyebrow + .wp-block-post-title {
    margin-block-start: 0 !important;
}

/* ─────────────────────────────────────────────────────────────
   Per-page "Hide page title" toggle — set via the MOOD Page
   Options panel in the page sidebar. Hides the rendered post-
   title block and removes the gap it would have left behind.
   ───────────────────────────────────────────────────────────── */

body.mood-hide-page-title .wp-block-post-title {
    display: none !important;
}

/* Inline font-weight classes — applied by the inline-typography
   format types in the block editor (`assets/js/inline-typography.js`).
   WP auto-generates `.has-{slug}-font-family` and
   `.has-{slug}-font-size` from theme.json; font-weight has no
   equivalent compiled output, so we declare it here. `!important`
   is required because theme.json compiles per-block typography
   into rules more specific than a bare `.has-…` class. */
.has-300-font-weight { font-weight: 300 !important; }
.has-500-font-weight { font-weight: 500 !important; }
.has-600-font-weight { font-weight: 600 !important; }

/* Author avatar in the single-post header — opt-in per post via
   "Include author avatar" toggle in MOOD Post Options. The avatar
   block is always present in single.html so any post can opt in,
   but hidden by default so existing posts don't suddenly grow a
   portrait. The body class added by mood_body_classes reveals it.
   Sized + circular + spaced from the meta line below. */
body.single-post main .wp-block-avatar {
    display: none !important;
}
body.single-post.mood-post-show-avatar main .wp-block-avatar {
    display: block !important;
    margin-bottom: var(--wp--preset--spacing--30);
}
body.single-post.mood-post-show-avatar main .wp-block-avatar img {
    border-radius: 50%;
    display: block;
}
/* In overlay mode (meta-on-image), keep the avatar centered with the
   rest of the meta column unless left-aligned. */
body.mood-post-meta-on-image.mood-post-show-avatar main > .wp-block-group:first-child .wp-block-avatar {
    margin-left: auto;
    margin-right: auto;
}
body.mood-post-meta-on-image.mood-post-meta-align-left.mood-post-show-avatar main > .wp-block-group:first-child .wp-block-avatar {
    margin-left: 0;
    margin-right: 0;
}

/* Editor-only: cap the post-title input size in the block editor
   canvas so it doesn't dominate the workspace. The front-end title
   keeps its Display-tier theme.json sizing — this only constrains
   the editing-UX preview where the giant size is unhelpful (and
   especially noisy when "Hide page title" is on). Covers both the
   modern post-title block wrapper and the classic
   `.editor-post-title__input` field. */
.editor-styles-wrapper .wp-block-post-title,
.editor-styles-wrapper .editor-post-title,
.editor-styles-wrapper .editor-post-title__input,
.editor-styles-wrapper h1.wp-block-post-title {
    font-size: clamp(1.5rem, 2.5vw, 2.25rem) !important;
    line-height: 1.15 !important;
    letter-spacing: -0.01em !important;
    margin: 0 0 0.5rem !important;
}

/* ─────────────────────────────────────────────────────────────
   Header & footer horizontal padding — uses the WP global
   root padding vars so they always match Site Editor → Styles
   → Layout → Padding (and follow any future change there).
   ───────────────────────────────────────────────────────────── */

.mood-site-header,
.mood-site-footer {
    padding-right: var(--wp--style--root--padding-right) !important;
    padding-left: var(--wp--style--root--padding-left) !important;
}

/* Kill the default border-bottom under the site header on every
   page. The transparent-header treatment (line ~363) already does
   this for hero pages; this rule covers the rest. The border can
   come from WP global styles, theme.json `core/group` defaults, or
   a one-off Site Editor edit on the header template part — easier
   to override unconditionally than to chase the source.

   Also force vertical centering of the header's flex children
   (logo + nav). WP normally emits `is-vertical-aligned-center`
   when the template-part's `verticalAlignment: center` is set,
   but a Site Editor edit can strip that class — which leaves
   items default-aligned (stretch / flex-start) and makes the
   logo and menu items sit at different vertical positions. */
.mood-site-header {
    border-bottom: 0 !important;
    border-bottom-width: 0 !important;
    border-bottom-color: transparent !important;
    align-items: center !important;
}
/* Navigation links — force `line-height: normal` and
   `vertical-align: middle` so the link text height matches its
   font size (no extra line-box padding above / below) and aligns
   to the middle of the flex row. Without these, inherited
   body-level line-height stretches the nav items vertically,
   so the flex-centered logo and menu items end up at different
   visual positions. */
.mood-site-header .wp-block-navigation,
.mood-site-header .wp-block-navigation a,
.mood-site-header .wp-block-navigation .wp-block-navigation-item__content,
.mood-site-header .wp-block-navigation button {
    line-height: normal !important;
    vertical-align: middle !important;
}
/* Submenu dropdown arrow (chevron) — make the parent submenu
   item / toggle a flex container so text + chevron align as
   flex children. `vertical-align: middle` alone doesn't fix it
   because the chevron sits in a nested wrapper that defaults to
   baseline alignment regardless.

   Scoped to desktop (≥782px) — on mobile the same rule makes
   the submenu li shrink to content width and center inside the
   mobile menu panel (where items should be left-aligned). */
@media (min-width: 782px) {
    .mood-site-header .wp-block-navigation-submenu,
    .mood-site-header .wp-block-navigation-submenu__toggle,
    .mood-site-header .wp-block-navigation-item.has-child > .wp-block-navigation-item__content {
        display: inline-flex !important;
        align-items: center !important;
        gap: 0.25em;
    }
}
.mood-site-header .wp-block-navigation__submenu-icon {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    line-height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
}
.mood-site-header .wp-block-navigation__submenu-icon svg {
    display: block !important;
    vertical-align: middle !important;
}

/* Override the inline-flex centering on dropdown children — the
   parent submenu li is inline-flex (so the toggle's text + chevron
   align together), but the dropdown items inside the absolutely-
   positioned panel inherit `justify-content / align-items: center`
   visually, which centers their text. Force left-alignment + start
   justification on every dropdown item. */
.mood-site-header .wp-block-navigation__submenu-container,
.mood-site-header .wp-block-navigation__submenu-container li,
.mood-site-header .wp-block-navigation__submenu-container .wp-block-navigation-item,
.mood-site-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content,
.mood-site-header .wp-block-navigation__submenu-container a {
    text-align: left !important;
    justify-content: flex-start !important;
    align-items: flex-start !important;
}

/* Default state: dark logo visible, light hidden */
.mood-logo--light { display: none !important; }
.mood-logo--dark  { display: block !important; }

/* ─────────────────────────────────────────────────────────────
   Navigation dropdown (submenu) — dark transparent panel that
   lets the page show through. Background color is exposed as a
   CSS variable so admins can override site-wide via
   Appearance → Layout Settings → "Navigation Dropdown Background"
   (functions.php emits an override `:root` rule when set).
   ───────────────────────────────────────────────────────────── */

:root {
    --mood-nav-dropdown-bg:   rgba(16, 19, 27, 0.85);
    --mood-nav-dropdown-text: var(--wp--preset--color--base, #ffffff);
}

.wp-block-navigation .wp-block-navigation__submenu-container {
    background-color: var(--mood-nav-dropdown-bg) !important;
    color: var(--mood-nav-dropdown-text) !important;
    /* Drop the default border + chevron tick WP draws on submenus
       so the panel reads as a clean tinted glass. */
    border: 0 !important;
    border-radius: 0;
    /* Frosted-glass backdrop blur — falls back gracefully to a
       slightly more opaque background when blur isn't supported. */
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    /* Panel padding — comfortable but compact. */
    padding: 0.75rem 1rem !important;
}
/* Strip any background WP / theme defaults paint on the inner
   submenu wrappers, items, and links — without this, a nested
   item background creates a visible second "panel" inside the
   tinted-glass outer container, which is what the user was
   seeing as the darker interior box. */
.wp-block-navigation .wp-block-navigation__submenu-container,
.wp-block-navigation .wp-block-navigation__submenu-container *,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
    box-shadow: none !important;
}
.wp-block-navigation .wp-block-navigation__submenu-container > *,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation__container,
.wp-block-navigation .wp-block-navigation__submenu-container ul {
    background: transparent !important;
    background-color: transparent !important;
}
/* Force links + chevrons inside the dropdown to inherit the text
   color from the panel. Also shrink the item type a touch — WP
   nav links inherit the parent nav font-size, which is fine for
   the top-level row but reads as oversized in a compact dropdown. */
.wp-block-navigation .wp-block-navigation__submenu-container a,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content,
.wp-block-navigation .wp-block-navigation__submenu-container button.wp-block-navigation-submenu__toggle {
    color: inherit !important;
    font-size: clamp(0.9rem, 0.95vw, 1rem);
    line-height: 1.4;
    padding-block: 0.35em;
    padding-inline: 0;
}
.wp-block-navigation .wp-block-navigation__submenu-container a:hover,
.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
    color: var(--wp--preset--color--accent, currentColor) !important;
}

/* ── Mobile menu — slide-down dropdown ─────────────────────────
   Re-skins WP's native mobile-menu modal so it slides down from
   below the header instead of taking over the full viewport.
   Notes:
     • All sizing/visibility overrides are scoped inside the
       `@media (max-width: 599px)` block below — desktop layout
       is untouched (an earlier version forced `display` on the
       hamburger globally, which made the icon leak into desktop
       and bumped the header layout).
     • The hamburger stays visible when the menu is open and
       toggles the panel — so WP's dedicated close (X) button is
       hidden. Users tap the hamburger again to close.
     • Background + text color default to the active theme:
       light theme → base/contrast, dark theme → contrast/base.
       Admin overrides at Appearance → Layout Settings → "Mobile
       Menu" still win via the `--mood-mobile-menu-*` variables.
   ───────────────────────────────────────────────────────────── */

/* Theme-aware default colors. Declared once so the slide-down
   panel below can read `var(--mood-mobile-menu-bg, var(--mood-mobile-menu-bg-default))`
   without each rule branching on light vs dark theme itself. */
:root {
    --mood-mobile-menu-bg-default:    var(--wp--preset--color--base, #ffffff);
    --mood-mobile-menu-color-default: var(--wp--preset--color--contrast, #10131B);
}
body.has-dark-theme {
    --mood-mobile-menu-bg-default:    var(--wp--preset--color--contrast, #10131B);
    --mood-mobile-menu-color-default: var(--wp--preset--color--base, #ffffff);
}

/* Three-line hamburger icon — replaces WP's default 2-line SVG.
   `::before` plus two `box-shadow` lines draw 3 horizontal bars.
   Intentionally no `display` override here; WP's own media
   queries decide when the hamburger is visible (only on mobile
   when `overlayMenu: "mobile"` is set on the nav block). */
.wp-block-navigation__responsive-container-open svg {
    display: none !important;
}
.wp-block-navigation__responsive-container-open::before {
    content: "";
    display: block;
    width: 24px;
    height: 2px;
    background: currentColor;
    box-shadow:
        0 -7px 0 currentColor,
        0  7px 0 currentColor;
}

@media (max-width: 781px) {
    /* Hamburger button — just a bit of padding for hit area. No
       `min-width` / `min-height` / `height` forcing: those were
       making the header row taller than the natural logo height
       and re-centering the logo to compensate, which is what was
       reading as "logo pushed down". With only padding here, the
       button sizes to its content; WP's flex header naturally
       centers everything against the tallest item (the logo). */
    .wp-block-navigation__responsive-container-open {
        padding: 0.5rem;
        background: transparent;
        border: 0;
    }
    /* Hide the hamburger once the menu is open. Multiple
       selectors are needed because different WP versions toggle
       different attributes — `aria-expanded` on the button,
       `.is-menu-open` on the container, or both. The `:has()`
       form is the most reliable (matches whenever any descendant
       container has `.is-menu-open`), with the others as
       fallbacks for older browsers. */
    .wp-block-navigation__responsive-container-open[aria-expanded="true"],
    .wp-block-navigation:has(.wp-block-navigation__responsive-container.is-menu-open) .wp-block-navigation__responsive-container-open,
    .wp-block-navigation:has(.wp-block-navigation__responsive-container.is-menu-open) > .wp-block-navigation__responsive-container-open {
        display: none !important;
    }

    /* Slide-down panel — overrides WP's full-screen modal.
       Anchored at viewport top (covers the header area) and slides
       in via `translateY`. Padding lives on the inner dialog (a
       grid container) so logo + X share the same header row
       geometry as the real desktop header. */
    .wp-block-navigation__responsive-container.is-menu-open {
        position: fixed !important;
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: auto !important;
        height: auto !important;
        max-height: 100vh;
        overflow-y: auto;
        z-index: 90;
        background-color: var(--mood-mobile-menu-bg, var(--mood-mobile-menu-bg-default)) !important;
        color: var(--mood-mobile-menu-color, var(--mood-mobile-menu-color-default));
        padding: 0 !important;
        display: block !important;
        animation: mood-mobile-menu-slide 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
    }
    /* Strip the WP wrappers between the panel and its contents
       (`__responsive-close` is an intermediate div that defaults
       to padded vertical-center, which fights our layout). */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__responsive-close {
        position: static !important;
        padding: 0 !important;
        margin: 0 !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        width: 100% !important;
    }

    /* Dialog is the grid container — mirrors the desktop header
       exactly: padding-block matches the header's rendered padding
       (spacing|60 → 36px, as confirmed via DevTools box model),
       padding-inline matches the root content padding (same value
       the .mood-site-header rule above uses). Row 1 = logo + X
       sharing `align-items: center` so they auto-align regardless
       of individual heights (same trick the header's flex row
       uses to center the 44×~23px logo against the hamburger). */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__responsive-dialog {
        display: grid !important;
        grid-template-columns: auto 1fr auto;
        grid-template-rows: auto auto;
        align-items: center;
        column-gap: 0;
        row-gap: 0;
        margin: 0 !important;
        padding:
            var(--wp--preset--spacing--60)
            var(--wp--style--root--padding-right, 1.5rem)
            2rem
            var(--wp--style--root--padding-left, 1.5rem) !important;
        width: 100% !important;
        min-height: 0 !important;
        max-height: none !important;
        height: auto !important;
        position: static !important;
    }
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__responsive-container-content {
        grid-column: 1 / -1;
        grid-row: 2;
        width: 100% !important;
        padding: var(--wp--preset--spacing--60) 0 0 !important;
        margin: 0 !important;
        display: block !important;
    }
    @keyframes mood-mobile-menu-slide {
        from { transform: translateY(-100%); }
        to   { transform: translateY(0);    }
    }
    /* Admin bar (46px on mobile) — menu starts below it so the
       toolbar stays clickable. */
    body.admin-bar .wp-block-navigation__responsive-container.is-menu-open {
        top: 46px !important;
        max-height: calc(100vh - 46px);
    }

    /* Logo: grid-column 1 (left), natural aspect ratio at 44px
       wide. The source image is 520×270, so width:44 + height:auto
       renders it at ~22.85px tall — the actual logo height shown
       in the desktop header. Forcing height:44px (a previous
       attempt) stretched it vertically. The grid placement only
       activates inside `.is-menu-open` (see default `display:none`
       below the media query — desktop renders the responsive
       container inline, where this anchor must stay hidden). */
    .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo {
        grid-column: 1;
        grid-row: 1;
        margin: 0 !important;
        line-height: 0;
        display: block;
        align-self: center;
    }
    .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo__img {
        width: 44px;
        height: auto;
        display: block;
    }
    /* Default: dark icon visible, light hidden. Flipped under
       has-dark-theme — same body class that flips the mobile
       menu's default bg from light → dark, so the logo always
       contrasts the menu surface. */
    .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo__img--light { display: none; }
    body.has-dark-theme .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo__img--dark { display: none; }
    body.has-dark-theme .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo__img--light { display: block; }

    /* X close button: grid-column 3 (right). `position: static`
       drops WP's default absolute positioning so the grid can
       place it. `align-self: center` lets grid's row-level
       align-items:center pick up its center against the logo.

       Horizontal padding mirrors the hamburger button
       (`padding: 0.5rem` → 8px each side around a 24px-wide icon
       = 40px total). Without matching padding, the 24px-wide X
       svg's center sat 8px further right than the hamburger's
       center, since both buttons are right-anchored to the same
       root padding edge but had different widths. */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__responsive-container-close {
        grid-column: 3;
        grid-row: 1;
        position: static !important;
        top: auto !important;
        right: auto !important;
        margin: 0 !important;
        padding: 0 0.5rem !important;
        background: transparent !important;
        border: 0 !important;
        align-self: center;
        color: var(--mood-mobile-menu-color, var(--mood-mobile-menu-color-default)) !important;
    }

    /* Don't lock body scroll while the menu is open — and don't
       let WP shift the page by removing the scrollbar (the source
       of the "page jump" the user saw when toggling). */
    html.has-modal-open,
    body.has-modal-open {
        overflow: auto !important;
        margin-right: 0 !important;
        padding-right: 0 !important;
    }

    /* Hide submenu dropdown chevron inside the open mobile menu —
       sub-items are rendered inline (flat list) on mobile, so the
       "expand" affordance is meaningless and just adds visual noise
       next to parent labels like "Work". */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__submenu-icon {
        display: none !important;
    }

    /* Breathing room between top-level menu items in the open
       panel. Sub-items (rendered as an inner <ul>) already get
       generous spacing from their own block-gap; the top-level
       <ul> defaults to a tight gap that read as cramped between
       "About Us / Press / Contact Us". Adding row-gap on the
       outer container gives each top-level item its own line of
       breathing room without affecting the submenu cluster.

       `justify-content: flex-start` overrides the layout flow from
       parts/header.html's `"justifyContent":"right"` on the
       navigation block, which is correct for desktop (pushes menu
       items right of the logo) but propagates into the open mobile
       panel as right-alignment of the stacked items. We want them
       left-aligned with the logo / sub-items. */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__container {
        row-gap: 1rem !important;
        justify-content: flex-start !important;
        align-items: flex-start !important;
        text-align: left !important;
    }
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__container > .wp-block-navigation-item {
        margin-block: 0.25rem;
        justify-content: flex-start !important;
        text-align: left !important;
    }
    /* "Work" is a `<button class="wp-block-navigation-submenu__toggle">`,
       not an `<a>` — it's the parent that opens the submenu. WP
       wraps it in `<li class="wp-block-navigation-submenu">` which
       defaults to `display: flex; align-items: center` (so the
       button + chevron + sub-UL stack cleanly), but on the open
       mobile panel that center-alignment pulls "Work" to the middle
       while the sibling link items (Hospitality / About Us)
       sit flush-left.

       Defeating it requires three layers:
       1. The parent LI: make it a column-flex with items at start.
       2. The toggle button content: align-self: flex-start so the
          button doesn't stretch + recenter.
       3. The button's text alignment: left (in case width !=
          content-width). */
    .wp-block-navigation__responsive-container.is-menu-open
        li.wp-block-navigation-submenu,
    .wp-block-navigation__responsive-container.is-menu-open
        li.wp-block-navigation-item.has-child {
        display: flex !important;
        flex-direction: column !important;
        align-items: flex-start !important;
        justify-content: flex-start !important;
        text-align: left !important;
    }
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation-submenu__toggle,
    .wp-block-navigation__responsive-container.is-menu-open
        li.wp-block-navigation-submenu > .wp-block-navigation-item__content,
    .wp-block-navigation__responsive-container.is-menu-open
        li.wp-block-navigation-item.has-child > .wp-block-navigation-item__content {
        align-self: flex-start !important;
        justify-content: flex-start !important;
        text-align: left !important;
        width: auto !important;
        max-width: none !important;
        margin-left: 0 !important;
        margin-right: auto !important;
        padding-left: 0 !important;
    }
    /* Same for the inner submenu UL (Hospitality / Private
       Residential / Play Studio). The block's layout cascade can
       leak `justify-content: flex-end` down through nested ULs. */
    .wp-block-navigation__responsive-container.is-menu-open
        .wp-block-navigation__submenu-container {
        justify-content: flex-start !important;
        align-items: flex-start !important;
        text-align: left !important;
    }
}

/* The mobile-menu logo is injected into EVERY navigation block by
   the PHP filter (mood_inject_mobile_menu_logo) — it can't be
   conditionally rendered based on viewport. Hide it by default so
   it doesn't appear inline next to the desktop menu items; the
   mobile media query above re-shows it inside `.is-menu-open` via
   grid placement. */
.mood-mobile-menu-logo {
    display: none !important;
}
@media (max-width: 781px) {
    .wp-block-navigation__responsive-container.is-menu-open
        .mood-mobile-menu-logo {
        display: block !important;
    }
}

/* Color + typography for menu items — driven by the same admin
   override variables, with theme-aware fallbacks (set above) so
   leaving the admin fields blank gives the right default per page. */
.wp-block-navigation__responsive-container.is-menu-open,
.wp-block-navigation__responsive-container.is-menu-open a,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content,
.wp-block-navigation__responsive-container.is-menu-open button.wp-block-navigation-submenu__toggle {
    color: var(--mood-mobile-menu-color, var(--mood-mobile-menu-color-default)) !important;
}
.wp-block-navigation__responsive-container.is-menu-open a,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content,
.wp-block-navigation__responsive-container.is-menu-open button.wp-block-navigation-submenu__toggle {
    font-family:     var(--mood-mobile-menu-font-family, inherit);
    font-size:       var(--mood-mobile-menu-font-size, inherit);
    font-weight:     var(--mood-mobile-menu-font-weight, inherit);
    line-height:     var(--mood-mobile-menu-line-height, inherit);
    letter-spacing:  var(--mood-mobile-menu-letter-spacing, inherit);
    text-transform:  var(--mood-mobile-menu-text-transform, inherit);
}

/* ─────────────────────────────────────────────────────────────
   Headlines — large display sizes can hit narrow-container
   thresholds and break mid-character. Force whole-word breaks
   (only break when truly necessary) and balance line lengths.
   ───────────────────────────────────────────────────────────── */

/* Theme-wide wrap rules: prefer breaking at real spaces, only fall back
   to mid-character if a single token genuinely won't fit. If you see
   mid-character breaks, the source text usually has non-breaking spaces
   (U+00A0) gluing words together — fix the content, not the CSS. */
*,
*::before,
*::after {
    word-break: normal !important;
    overflow-wrap: break-word !important;
    hyphens: none !important;
}

/* ─────────────────────────────────────────────────────────────
   Hero (full-bleed slideshow with zoom + parallax)
   ───────────────────────────────────────────────────────────── */

.mood-hero {
    position: relative;
    min-height: 100vh; /* fallback for older browsers */
    min-height: 100dvh; /* dynamic viewport height — accounts for mobile toolbar showing/hiding */
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    padding: 0 !important;
    overflow: hidden;
    background-color: #10131B; /* fallback while images load */
    isolation: isolate;
}

/* Force the Cover block's background image to fully fill its slide.
   Defensive against any inline width/height/object-fit overrides that
   could leave the dark fallback color showing at the edges.

   Intentionally NOT setting `object-position` here — WP's Cover block
   writes the user's focal-point pick as an inline `style="object-position:…"`
   on this image element. A blanket `object-position: center center !important`
   would override that and ignore the focal point set in the block
   inspector. The browser default (`50% 50%`) covers the no-focal-point
   case naturally. */
.mood-hero .wp-block-cover__image-background,
.mood-hero img.wp-block-cover__image-background {
    position: absolute !important;
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    z-index: 0 !important;
}

/* If the editor sets an inline aspect-ratio via Dimensions → Aspect Ratio,
   drop min-height so the ratio actually governs the height. */
.mood-hero[style*="aspect-ratio"] {
    min-height: 0;
}

/* ─ Per-breakpoint aspect-ratio (set via the "Hero — Aspect Ratio" inspector panel) ─ */

/* Desktop / base — applies at all sizes; tablet & mobile overrides cascade on top. */
.mood-hero.desktop-ratio-21-9   { aspect-ratio: 21 / 9; min-height: 0; }
.mood-hero.desktop-ratio-16-9   { aspect-ratio: 16 / 9; min-height: 0; }
.mood-hero.desktop-ratio-3-2    { aspect-ratio: 3 / 2;  min-height: 0; }
.mood-hero.desktop-ratio-4-3    { aspect-ratio: 4 / 3;  min-height: 0; }
.mood-hero.desktop-ratio-1-1    { aspect-ratio: 1;      min-height: 0; }
.mood-hero.desktop-ratio-3-4    { aspect-ratio: 3 / 4;  min-height: 0; }
.mood-hero.desktop-ratio-9-16   { aspect-ratio: 9 / 16; min-height: 0; }
@media (max-width: 1024px) {
    .mood-hero.tablet-fullscreen   { aspect-ratio: auto !important; min-height: 100vh !important; }
    .mood-hero.tablet-ratio-21-9   { aspect-ratio: 21 / 9 !important; min-height: 0 !important; }
    .mood-hero.tablet-ratio-16-9   { aspect-ratio: 16 / 9 !important; min-height: 0 !important; }
    .mood-hero.tablet-ratio-3-2    { aspect-ratio: 3 / 2  !important; min-height: 0 !important; }
    .mood-hero.tablet-ratio-4-3    { aspect-ratio: 4 / 3  !important; min-height: 0 !important; }
    .mood-hero.tablet-ratio-1-1    { aspect-ratio: 1      !important; min-height: 0 !important; }
    .mood-hero.tablet-ratio-3-4    { aspect-ratio: 3 / 4  !important; min-height: 0 !important; }
}
@media (max-width: 600px) {
    .mood-hero.mobile-fullscreen   { aspect-ratio: auto !important; min-height: 100vh !important; }
    .mood-hero.mobile-ratio-21-9   { aspect-ratio: 21 / 9 !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-16-9   { aspect-ratio: 16 / 9 !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-3-2    { aspect-ratio: 3 / 2  !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-4-3    { aspect-ratio: 4 / 3  !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-1-1    { aspect-ratio: 1      !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-3-4    { aspect-ratio: 3 / 4  !important; min-height: 0 !important; }
    .mood-hero.mobile-ratio-9-16   { aspect-ratio: 9 / 16 !important; min-height: 0 !important; }
}

/* Belt-and-braces: force the alignfull hero to escape any constrained
   parent and span the full viewport, regardless of theme.json layout. */
.mood-hero.alignfull {
    width: 100vw !important;
    max-width: 100vw !important;
    margin-left: calc(50% - 50vw) !important;
    margin-right: calc(50% - 50vw) !important;
}

/* Each slide is a Cover block. They're stacked absolutely on top of each
   other and crossfaded by toggling .is-active via JS. */
.mood-hero .mood-hero-slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0 !important;
    padding: 0 !important;
    opacity: 0;
    transition: opacity 1.4s ease-in-out;
    /* Parallax: JS sets --mood-hero-scroll in pixels on the hero.
       `max(0px, …)` is a safety net — a negative scroll value would
       translate the slide upward and expose the hero's dark fallback
       background at the bottom (happens when the hero starts below
       viewport top: admin bar, top page padding, fixed header). */
    transform: translate3d(0, max(0px, calc(var(--mood-hero-scroll, 0px) * 0.4)), 0);
    will-change: opacity, transform;
    pointer-events: none;
}

.mood-hero .mood-hero-slide.is-active {
    opacity: 1;
    pointer-events: auto;
}

/* The Cover block's background image element — apply the slow zoom
   only while the slide is active so the keyframe restarts on each cycle. */
.mood-hero .mood-hero-slide .wp-block-cover__image-background,
.mood-hero .mood-hero-slide .wp-block-cover__video-background {
    transform: scale(1.08);
    will-change: transform;
}
.mood-hero .mood-hero-slide.is-active .wp-block-cover__image-background,
.mood-hero .mood-hero-slide.is-active .wp-block-cover__video-background {
    animation: moodHeroZoom 12s ease-out forwards;
}

@keyframes moodHeroZoom {
    from { transform: scale(1.08); }
    to   { transform: scale(1.00); }
}

/* Center the wordmark + subtitle inside each slide's inner-container. */
.mood-hero .mood-hero-slide .wp-block-cover__inner-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    width: 100%;
}

/* Wordmark is now an Image block — sized fluidly to mirror the live reference
   (~55% of viewport width, capped at 900px on huge screens). */
.mood-hero .mood-hero-wordmark {
    margin-block: 0 !important;
    margin-inline: auto !important;
    align-self: center;
    width: fit-content;
    max-width: 90vw;
    line-height: 0;
}
.mood-hero .mood-hero-wordmark img {
    max-width: 100%;
    height: auto;
    display: block;
    margin-inline: auto;
}

.mood-hero .mood-hero-subtitle {
    color: #fff !important;
    font-size: clamp(1rem, 1.6vw, 1.5rem);
    letter-spacing: 0.02em;
    margin: 0 !important;
}

/* Default subtitle typography — wrapped in :where() so editor font selections
   (has-{slug}-font-family classes) override these without !important wars. */
:where(.mood-hero .mood-hero-subtitle) {
    font-family: "Juana", Georgia, serif;
    font-style: italic;
    font-weight: 400;
}

/* Reduce motion users get a static first slide — no zoom, no parallax. */
@media (prefers-reduced-motion: reduce) {
    .mood-hero .mood-hero-slide { transform: none !important; }
    .mood-hero .mood-hero-slide.is-active .wp-block-cover__image-background,
    .mood-hero .mood-hero-slide.is-active .wp-block-cover__video-background {
        animation: none;
        transform: none;
    }
}

/* When a page contains the hero, kill the body's top padding so the hero
   starts flush at the top of the viewport, and force the site header to
   the transparent overlay treatment (independent of the static-front-page
   body class, which only fires under specific WP Settings).
   `.wp-site-blocks` is WP's auto-generated wrapper — it carries
   `padding-top: var(--wp--style--root--padding-top)` from theme.json's
   global styles, which sits *above* the hero and reads as a white band.
   Zeroing it here lets the hero reach the viewport top. */
body:has(.mood-hero) {
    padding-top: 0 !important;
}
body:has(.mood-hero) .wp-site-blocks {
    padding-top: 0 !important;
}
body:has(.mood-hero) main,
body:has(.mood-hero) main.wp-block-group {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
    padding-top: 0 !important;
}
body:has(.mood-hero) header.wp-block-template-part {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
    margin-bottom: 0 !important;
    margin-block-end: 0 !important;
    padding: 0 !important;
}
body:has(.mood-hero) .mood-site-header {
    background-color: transparent !important;
    border-bottom-color: transparent !important;
    border-bottom-width: 0 !important;
    position: absolute;
    /* Offset by the root padding-top so the absolute header lines up
       vertically with where it would sit on a non-transparent page
       (whose `.wp-site-blocks` has root padding-top pushing the
       in-flow header down). Falls back to 0 for sites that don't set
       a vertical root padding. */
    top: var(--wp--style--root--padding-top, 0);
    left: 0;
    right: 0;
    z-index: 100;
}

/* Admin bar offset — absolute-positioned headers don't shift with the
   html margin WP adds for the admin bar, so push them down manually.
   Includes root padding-top so the header still aligns with the
   in-flow header on non-transparent pages. */
body.admin-bar:has(.mood-hero) .mood-site-header,
body.admin-bar.has-transparent-header .mood-site-header {
    top: calc(32px + var(--wp--style--root--padding-top, 0px));
}
@media screen and (max-width: 782px) {
    body.admin-bar:has(.mood-hero) .mood-site-header,
    body.admin-bar.has-transparent-header .mood-site-header {
        top: calc(46px + var(--wp--style--root--padding-top, 0px));
    }
}
body:has(.mood-hero) .mood-site-header .mood-logo--dark { display: none !important; }
body:has(.mood-hero) .mood-site-header .mood-logo--light { display: block !important; }
body:has(.mood-hero) .mood-site-header,
body:has(.mood-hero) .mood-site-header .wp-block-navigation a,
body:has(.mood-hero) .mood-site-header .wp-block-navigation button,
body:has(.mood-hero) .mood-site-header .wp-block-navigation .wp-block-navigation-item__content {
    color: #fff;
}
body:has(.mood-hero) .mood-site-header .wp-block-navigation a:hover,
body:has(.mood-hero) .mood-site-header .wp-block-navigation .wp-block-navigation-item__content:hover {
    color: var(--wp--preset--color--accent);
}

/* Per-page "Transparent header (overlay)" toggle — mirrors the
   `body:has(.mood-hero)` flush-top treatment for any page where
   the user opts in via the MOOD Page Options sidebar, regardless
   of which hero pattern (or none) the page uses. The
   `has-transparent-header` class (added in the same body_class
   filter call) handles the overlay nav styling via the rules
   immediately below this block — we only need to zero the
   top padding / margin chain here so the hero / featured image
   sits flush under the now-overlaid header. */
body.mood-page-flush-top {
    padding-top: 0 !important;
}
body.mood-page-flush-top .wp-site-blocks {
    padding-top: 0 !important;
}
body.mood-page-flush-top main,
body.mood-page-flush-top main.wp-block-group {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
    padding-top: 0 !important;
}
body.mood-page-flush-top header.wp-block-template-part {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
    margin-bottom: 0 !important;
    margin-block-end: 0 !important;
    padding: 0 !important;
}
/* Post-content (`.wp-block-post-content`, the wrapper that holds
   the page body) and its first child also need to be flush. WP's
   layout-constrained rule `:where(.is-layout-constrained) > * + *`
   gives post-content a `margin-block-start: var(--wp--style--block-gap)`
   when it follows post-title — even when post-title is hidden via
   mood-hide-page-title (display:none, but still a sibling, so `+`
   matches). That gap is what pushes the hero down from viewport top
   on page templates that include the post-title block. Zero it here
   plus the first visible block inside post-content so the hero
   actually lands flush. */
body.mood-page-flush-top main > .wp-block-post-content,
body.mood-page-flush-top main > .wp-block-post-content > :first-child {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
}

/* ─────────────────────────────────────────────────────────────
   Transparent header — set on pages with full-bleed top hero
   ───────────────────────────────────────────────────────────── */

body.has-transparent-header .mood-site-header {
    background-color: transparent !important;
    border-bottom-color: transparent !important;
    border-bottom-width: 0 !important;
    position: absolute;
    /* Mirror the root padding-top offset — see the
       `body:has(.mood-hero) .mood-site-header` rule above for the
       rationale (keeps absolute and in-flow header positions aligned
       across transparent / non-transparent pages). */
    top: var(--wp--style--root--padding-top, 0);
    left: 0;
    right: 0;
    z-index: 10;
}
body.has-transparent-header .mood-site-header .mood-logo--dark { display: none !important; }
body.has-transparent-header .mood-site-header .mood-logo--light { display: block !important; }

body.has-transparent-header .mood-site-header,
body.has-transparent-header .mood-site-header .wp-block-navigation a,
body.has-transparent-header .mood-site-header .wp-block-navigation button,
body.has-transparent-header .mood-site-header .wp-block-navigation .wp-block-navigation-item__content {
    color: #fff;
}
body.has-transparent-header .mood-site-header .wp-block-navigation a:hover,
body.has-transparent-header .mood-site-header .wp-block-navigation .wp-block-navigation-item__content:hover {
    color: var(--wp--preset--color--accent);
}

/* ─────────────────────────────────────────────────────────────
   Single post — full-width featured image at top.
   Toggled per-post via the "Full-width featured image at top"
   switch in the MOOD Post Options sidebar panel; functions.php
   emits the `mood-post-fullwidth-featured` body class (paired
   with `has-transparent-header`, whose rules above style the
   overlay nav).
   ───────────────────────────────────────────────────────────── */

/* Zero the page-top padding + main margin so the image sits
   flush under the now-transparent header. */
body.mood-post-fullwidth-featured {
    padding-top: 0 !important;
}
body.mood-post-fullwidth-featured .wp-site-blocks {
    padding-top: 0 !important;
}
body.mood-post-fullwidth-featured main {
    margin-top: 0 !important;
    margin-block-start: 0 !important;
    padding-top: 0 !important;
    /* Flex so we can reorder the featured image to the top
       regardless of where it sits in single.html's source. */
    display: flex !important;
    flex-direction: column !important;
}

/* Hoist the featured image to the top of the layout and let it
   span the full viewport width. The default `wp:post-featured-image`
   block ships with align: wide; this rule promotes it to align: full
   only when this body class is set. */
body.mood-post-fullwidth-featured main > .wp-block-post-featured-image {
    order: -1 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    margin-left: calc(50% - 50vw) !important;
    margin-right: calc(50% - 50vw) !important;
    margin-top: 0 !important;
    margin-bottom: clamp(1.5rem, 4vw, 3rem) !important;
}
body.mood-post-fullwidth-featured main > .wp-block-post-featured-image img {
    width: 100% !important;
    height: auto !important;
    max-height: 85vh;
    object-fit: cover !important;
    display: block;
}

/* Featured image aspect-ratio crop — opt-in via MOOD Post Options →
   Aspect ratio. The body class encodes the ratio as `W-H`; we map
   each one to a CSS aspect-ratio on the figure, then make the
   inner <img> fill that frame and cover-fit so the crop is clean
   no matter how tall the source photo is. Wins over the
   `max-height: 85vh` cap above (which only applies to natural
   ratio). The `--mood-post-featured-aspect` custom property pattern
   keeps the per-ratio rules to a single line each. */
body.mood-post-featured-aspect-32-9 { --mood-post-featured-aspect: 32 / 9; }
body.mood-post-featured-aspect-21-9 { --mood-post-featured-aspect: 21 / 9; }
body.mood-post-featured-aspect-16-9 { --mood-post-featured-aspect: 16 / 9; }
body.mood-post-featured-aspect-3-2  { --mood-post-featured-aspect: 3 / 2; }
body.mood-post-featured-aspect-4-3  { --mood-post-featured-aspect: 4 / 3; }
body.mood-post-featured-aspect-1-1  { --mood-post-featured-aspect: 1 / 1; }
body.mood-post-featured-aspect-4-5  { --mood-post-featured-aspect: 4 / 5; }
body.mood-post-featured-aspect-2-3  { --mood-post-featured-aspect: 2 / 3; }
body.mood-post-featured-aspect-9-16 { --mood-post-featured-aspect: 9 / 16; }

/* Per-breakpoint overrides — re-bind the same custom property inside
   a media query, so the cascade at that viewport size picks up the
   per-breakpoint value. An unset breakpoint falls through to the
   desktop value (the body class above is set unconditionally and
   stays in the cascade until a more-specific media-query rule
   rebinds the variable). */
@media (min-width: 600px) and (max-width: 781px) {
    body.mood-post-featured-aspect-tablet-32-9    { --mood-post-featured-aspect: 32 / 9; }
    body.mood-post-featured-aspect-tablet-21-9    { --mood-post-featured-aspect: 21 / 9; }
    body.mood-post-featured-aspect-tablet-16-9    { --mood-post-featured-aspect: 16 / 9; }
    body.mood-post-featured-aspect-tablet-3-2     { --mood-post-featured-aspect: 3 / 2; }
    body.mood-post-featured-aspect-tablet-4-3     { --mood-post-featured-aspect: 4 / 3; }
    body.mood-post-featured-aspect-tablet-1-1     { --mood-post-featured-aspect: 1 / 1; }
    body.mood-post-featured-aspect-tablet-4-5     { --mood-post-featured-aspect: 4 / 5; }
    body.mood-post-featured-aspect-tablet-2-3     { --mood-post-featured-aspect: 2 / 3; }
    body.mood-post-featured-aspect-tablet-9-16    { --mood-post-featured-aspect: 9 / 16; }
    /* "Natural" override — explicitly disable the desktop crop on
       this breakpoint. `auto` makes aspect-ratio resolve to the
       image's intrinsic dimensions. */
    body.mood-post-featured-aspect-tablet-natural { --mood-post-featured-aspect: auto; }
}
@media (max-width: 599px) {
    body.mood-post-featured-aspect-mobile-32-9    { --mood-post-featured-aspect: 32 / 9; }
    body.mood-post-featured-aspect-mobile-21-9    { --mood-post-featured-aspect: 21 / 9; }
    body.mood-post-featured-aspect-mobile-16-9    { --mood-post-featured-aspect: 16 / 9; }
    body.mood-post-featured-aspect-mobile-3-2     { --mood-post-featured-aspect: 3 / 2; }
    body.mood-post-featured-aspect-mobile-4-3     { --mood-post-featured-aspect: 4 / 3; }
    body.mood-post-featured-aspect-mobile-1-1     { --mood-post-featured-aspect: 1 / 1; }
    body.mood-post-featured-aspect-mobile-4-5     { --mood-post-featured-aspect: 4 / 5; }
    body.mood-post-featured-aspect-mobile-2-3     { --mood-post-featured-aspect: 2 / 3; }
    body.mood-post-featured-aspect-mobile-9-16    { --mood-post-featured-aspect: 9 / 16; }
    body.mood-post-featured-aspect-mobile-natural { --mood-post-featured-aspect: auto; }
}

/* Consumption rule. The selector still uses the wildcard
   `[class*="mood-post-featured-aspect-"]` so it matches whether the
   desktop, tablet, or mobile class is present (or any combination).
   The `aspect-ratio` falls back to `auto` if no breakpoint has a
   bound value at the current viewport — e.g. when only mobile is
   set but the viewport is desktop, you get the image's natural ratio. */
body[class*="mood-post-featured-aspect-"] main > .wp-block-post-featured-image {
    aspect-ratio: var(--mood-post-featured-aspect, auto);
    height: auto !important;
    max-height: none !important;
    overflow: hidden;
}
body[class*="mood-post-featured-aspect-"] main > .wp-block-post-featured-image img {
    width: 100% !important;
    height: 100% !important;
    max-height: none !important;
    object-fit: cover !important;
    display: block;
}

/* Desktop-only min-height floor on the featured-image figure.
   Combines with `aspect-ratio` — the larger of (aspect-derived height,
   min-height) wins, so the hero stays at least this tall on wide
   viewports even when a narrow aspect would otherwise collapse it.
   Scoped to ≥782px so mobile / tablet aren't forced to oversized
   heroes. */
@media (min-width: 782px) {
    body.mood-post-featured-min-h-200px  main > .wp-block-post-featured-image { min-height: 200px;  }
    body.mood-post-featured-min-h-300px  main > .wp-block-post-featured-image { min-height: 300px;  }
    body.mood-post-featured-min-h-400px  main > .wp-block-post-featured-image { min-height: 400px;  }
    body.mood-post-featured-min-h-500px  main > .wp-block-post-featured-image { min-height: 500px;  }
    body.mood-post-featured-min-h-600px  main > .wp-block-post-featured-image { min-height: 600px;  }
    body.mood-post-featured-min-h-700px  main > .wp-block-post-featured-image { min-height: 700px;  }
    body.mood-post-featured-min-h-800px  main > .wp-block-post-featured-image { min-height: 800px;  }
    body.mood-post-featured-min-h-900px  main > .wp-block-post-featured-image { min-height: 900px;  }
    body.mood-post-featured-min-h-1000px main > .wp-block-post-featured-image { min-height: 1000px; }
}

/* Overlay post meta on the image — switches main from flex-column
   to CSS Grid so the featured image and the meta group (first
   .wp-block-group child of main: date + title + terms) can occupy
   the same grid cell. The meta sits at the bottom of the cell;
   subsequent items (post-content, post-nav) flow into row 2+
   automatically via grid auto-placement. */
body.mood-post-meta-on-image main {
    display: grid !important;
    grid-template-columns: 1fr;
    grid-auto-flow: row;
}
body.mood-post-meta-on-image main > .wp-block-post-featured-image {
    grid-column: 1;
    grid-row: 1;
    /* Drop the order:-1 from the flex layout (irrelevant in grid)
       and the trailing margin so nothing pushes content downward. */
    margin-bottom: 0 !important;
}
body.mood-post-meta-on-image main > .wp-block-group:first-child {
    grid-column: 1;
    grid-row: 1;
    align-self: end;
    justify-self: center;
    z-index: 2;
    width: 100%;
    max-width: var(--wp--style--global--content-size, 720px);
    margin: 0 auto !important;
    padding: 0 var(--wp--style--root--padding-left, 1.5rem) clamp(2rem, 6vw, 5rem);
    text-align: center;
    color: var(--wp--preset--color--base, #fff);
}
/* Recolor the children — the template hardcodes `textColor: muted`
   on date + author, which compiles to `.has-muted-color` with high
   specificity. Override scoped to the overlay context. (Post-terms
   is its own pill below — excluded here so its dark text shows on
   the light pill background.) */
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-title,
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-date,
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-date *,
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-author-name,
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-author-name *,
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-sep {
    color: var(--wp--preset--color--base, #fff) !important;
    text-align: inherit;
}

/* Post-terms styled as a pill — mirrors `.mood-featured-article__category`
   so the post-page hero meta matches the featured-articles card layout
   (pill → title → avatar · author · date). */
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-terms {
    display: inline-block;
    background: rgba(255, 255, 255, 0.92);
    color: #1a1a1a !important;
    padding: 0.3em 0.85em;
    border-radius: 999px;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.85rem, 1vw, 1rem);
    font-weight: 500;
    letter-spacing: 0.02em;
    line-height: 1.3;
    text-transform: none;
}
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-terms a {
    color: inherit !important;
    text-decoration: none;
}

/* Meta row — avatar + author · date in an inline flex line, mirroring
   `.mood-featured-article__meta`. The author-name and date blocks are
   block-level by default, so we force them inline inside the row. */
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row {
    display: inline-flex !important;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: center;
    gap: 0.5em;
    margin-top: var(--wp--preset--spacing--20);
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.85rem, 1vw, 1rem);
    line-height: 1.4;
}
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .wp-block-post-author-name,
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .wp-block-post-date,
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .mood-post-meta-sep {
    margin: 0 !important;
    line-height: inherit;
    font-size: inherit;
}
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .mood-post-meta-sep {
    opacity: 0.6;
}
/* Avatar inside the meta row — small inline circle. Overrides the
   default 64px from the block attribute and the `margin: 0 auto`
   from the centering rule earlier in this file. */
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .wp-block-avatar {
    margin: 0 !important;
    flex-shrink: 0;
    line-height: 0;
}
body.mood-post-meta-on-image main > .wp-block-group:first-child .mood-post-meta-row .wp-block-avatar img {
    width: 2em;
    height: 2em;
    border-radius: 50%;
    display: block;
}
/* When the user toggles date or author off, drop the separator so the
   row doesn't end with an orphan `·`. */
body.mood-post-no-date    .mood-post-meta-row .mood-post-meta-sep,
body.mood-post-no-author  .mood-post-meta-row .mood-post-meta-sep {
    display: none !important;
}

/* Tighter, bolder post title in the overlay context. The h1
   default in theme.json is `display` size + weight 400 — way
   too large/light when sitting over a photo. Drop to xx-large
   and use Juana bold (700, file shipped with the theme). */
body.mood-post-meta-on-image main > .wp-block-group:first-child .wp-block-post-title {
    font-family: var(--wp--preset--font-family--juana) !important;
    font-size: var(--wp--preset--font-size--xx-large) !important;
    font-weight: 700 !important;
    line-height: 1.05 !important;
    letter-spacing: -0.015em;
    margin: 0 !important;
}

/* Show/hide individual meta items — emitted only when the user
   toggles the corresponding "Show X" in the sidebar to off. */
body.mood-post-no-date    main > .wp-block-group:first-child .wp-block-post-date,
body.mood-post-no-title   main > .wp-block-group:first-child .wp-block-post-title,
body.mood-post-no-terms   main > .wp-block-group:first-child .wp-block-post-terms,
body.mood-post-no-author  main > .wp-block-group:first-child .wp-block-post-author-name {
    display: none !important;
}

/* Hide featured image entirely — opt-in via MOOD Post Options →
   Hide featured image. Paired with `mood_post_meta_bg_color` (printed
   by `mood_print_post_meta_bg_color` in functions.php) this turns the
   meta block into a colored hero band in lieu of an image.

   Also undoes the meta-on-image grid layout: with no image to stack
   under, the meta block just flows normally and the wp_head printer
   gives it its full-bleed band styling. */
body.mood-post-no-featured main > .wp-block-post-featured-image {
    display: none !important;
}
body.mood-post-no-featured.mood-post-meta-on-image main {
    display: block !important;
}
body.mood-post-no-featured.mood-post-meta-on-image main > .wp-block-group:first-child {
    justify-self: auto;
    align-self: auto;
}

/* Hide the prev / next post navigation footer on single posts
   when Layout Settings → Blog Posts → "Previous / Next post links"
   is unchecked. Hides the inner link blocks AND the wrapper group
   (with its top border) so no empty bordered shell remains. */
body.mood-hide-post-nav .wp-block-post-navigation-link {
    display: none !important;
}
body.mood-hide-post-nav main > .wp-block-group:has(> .wp-block-post-navigation-link) {
    display: none !important;
}

/* Left-aligned meta overlay — line up with the site logo. The
   center rule above sets `margin: 0 auto !important` (which beats
   `justify-self: start` in a grid cell) and a left padding of
   root-padding (which adds an extra inset on top of what the
   main already has). Both must be undone for left-align so the
   meta's leftmost glyph sits at the same x-coordinate as the
   header logo (both = viewport_left + root_padding). */
body.mood-post-meta-on-image.mood-post-meta-align-left:not(.mood-post-no-featured) main > .wp-block-group:first-child {
    justify-self: start;
    text-align: left;
    margin: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
/* Left-align text in the no-featured colored-band case — the
   margin/padding resets above would break the full-bleed band
   (`mood_print_post_meta_bg_color` in functions.php), so we keep
   the band's own bleed/padding and just flip the text alignment. */
body.mood-post-meta-on-image.mood-post-meta-align-left.mood-post-no-featured main > .wp-block-group:first-child {
    text-align: left;
}
body.mood-post-meta-on-image.mood-post-meta-align-left main > .wp-block-group:first-child .wp-block-post-title,
body.mood-post-meta-on-image.mood-post-meta-align-left main > .wp-block-group:first-child .wp-block-post-date,
body.mood-post-meta-on-image.mood-post-meta-align-left main > .wp-block-group:first-child .wp-block-post-author-name,
body.mood-post-meta-on-image.mood-post-meta-align-left main > .wp-block-group:first-child .wp-block-post-terms {
    text-align: left !important;
}
body.mood-post-meta-on-image.mood-post-meta-align-left main > .wp-block-group:first-child .mood-post-meta-row {
    justify-content: flex-start;
}

/* Gradient overlay — independent of meta-on-image, but designed
   to pair with it. Drawn on the featured-image figure via ::after
   so it sits between the <img> and any overlaid content. Bottom-
   weighted so light text near the bottom of the image stays legible
   without darkening the entire photo. */
body.mood-post-image-gradient main > .wp-block-post-featured-image {
    position: relative;
}
body.mood-post-image-gradient main > .wp-block-post-featured-image::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top,
        rgba(0, 0, 0, 0.7) 0%,
        rgba(0, 0, 0, 0.35) 35%,
        rgba(0, 0, 0, 0) 70%
    );
    pointer-events: none;
    z-index: 1;
}
/* When meta is also overlaid, the meta group sits at z-index: 2
   so it lands above the gradient — already handled above. */

/* ─────────────────────────────────────────────────────────────
   Team Member block (mood/team-member)
     • Card: portrait image with name + subtitle overlay, arrow
     • Modal: full-page overlay opened on card click, with
       larger image, bio, and optional contact icon. Custom X
       cursor on desktop; close button on mobile.
   ───────────────────────────────────────────────────────────── */

/* Card --------------------------------------------------------- */

.wp-block-mood-team-member {
    position: relative;
}

.mood-team-member__card {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    background: var(--wp--preset--color--contrast);
    border: 0;
    padding: 0;
    margin: 0;
    overflow: hidden;
    cursor: pointer;
    color: var(--wp--preset--color--base);
    text-align: left;
    font: inherit;
}

.mood-team-member__thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.mood-team-member__card:hover .mood-team-member__thumb,
.mood-team-member__card:focus-visible .mood-team-member__thumb {
    transform: scale(1.04);
}

/* Gradient overlay (toggleable in the inspector) — improves
   readability of the name on busy / lighter photos. */
.mood-team-member__card--has-gradient::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 55%;
    background: linear-gradient(to top, rgba(16, 19, 27, 0.75) 0%, rgba(16, 19, 27, 0) 100%);
    pointer-events: none;
    z-index: 1;
}

.mood-team-member__caption {
    position: absolute;
    left: 1.5rem;
    bottom: 1.25rem;
    z-index: 2;
    color: var(--wp--preset--color--base);
    pointer-events: none;
}

/* Typography props consume `--mood-team-{target}-{prop}` custom
   properties with the original hardcoded values as fallbacks.
   Site-wide defaults are set on :root by functions.php (Layout
   Settings → Team Member Typography). Per-instance overrides are
   set on the block wrapper as inline styles by render.php. */
.mood-team-member__name {
    display: block;
    font-family:     var(--mood-team-card-name-font-family, var(--wp--preset--font-family--juana));
    font-weight:     var(--mood-team-card-name-font-weight, 600);
    font-size:       var(--mood-team-card-name-font-size, clamp(1.5rem, 2.4vw, 2.25rem));
    line-height:     var(--mood-team-card-name-line-height, 1.05);
    letter-spacing:  var(--mood-team-card-name-letter-spacing, -0.01em);
    font-style:      var(--mood-team-card-name-font-style, normal);
}

.mood-team-member__subtitle {
    display: block;
    font-family:     var(--mood-team-card-subtitle-font-family, var(--wp--preset--font-family--josefin-sans));
    font-weight:     var(--mood-team-card-subtitle-font-weight, 300);
    font-size:       var(--mood-team-card-subtitle-font-size, 0.9rem);
    line-height:     var(--mood-team-card-subtitle-line-height, normal);
    letter-spacing:  var(--mood-team-card-subtitle-letter-spacing, normal);
    font-style:      var(--mood-team-card-subtitle-font-style, normal);
    margin-top: 0.35rem;
    opacity: 0.92;
}

/* Hover-capable devices only:
   • Default: only the name is visible; it sits low (occupying the
     subtitle's normal position).
   • Hover/focus: name slides UP, subtitle fades in below it,
     arrow fades + slides right.
   Touch devices skip the hover-reveal so users can still read the
   subtitle on tap-only devices. */
@media (hover: hover) and (pointer: fine) {
    .mood-team-member__name {
        transform: translateY(1.6rem);
        transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .mood-team-member__subtitle,
    .mood-team-member__arrow {
        opacity: 0;
        transform: translateY(0.4em);
        transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1),
                    transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .mood-team-member__card:hover .mood-team-member__name,
    .mood-team-member__card:focus-visible .mood-team-member__name {
        transform: translateY(0);
    }
    .mood-team-member__card:hover .mood-team-member__subtitle,
    .mood-team-member__card:focus-visible .mood-team-member__subtitle {
        opacity: 0.92;
        transform: translateY(0);
    }
    .mood-team-member__card:hover .mood-team-member__arrow,
    .mood-team-member__card:focus-visible .mood-team-member__arrow {
        opacity: 1;
        transform: translateX(0.4em);
    }
}

.mood-team-member__arrow {
    position: absolute;
    bottom: 1.5rem;
    right: 1.5rem;
    width: 1.75rem;
    height: 1.75rem;
    color: var(--wp--preset--color--base);
    z-index: 2;
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: none;
}

.mood-team-member__card:hover .mood-team-member__arrow,
.mood-team-member__card:focus-visible .mood-team-member__arrow {
    transform: translateX(0.4em);
}

/* Modal -------------------------------------------------------- */

.mood-team-member__modal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background-color: var(--wp--preset--color--base);
    color: var(--wp--preset--color--contrast);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Slide-in from the right. visibility delays so the modal
       isn't focusable / interactive while transitioning out. */
    transform: translateX(100%);
    visibility: hidden;
    pointer-events: none;
    transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s linear 0.5s;
}

.mood-team-member__modal.is-open {
    transform: translateX(0);
    visibility: visible;
    pointer-events: auto;
    transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s linear 0s;
}

@media (prefers-reduced-motion: reduce) {
    .mood-team-member__modal {
        transition: none;
    }
}

.mood-team-member__modal-inner {
    display: flex;
    width: 100%;
    min-height: 100vh;
    min-height: 100dvh;
}

.mood-team-member__modal-text {
    flex: 1 1 50%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1rem;
    padding: clamp(2rem, 6vw, 6rem);
}

.mood-team-member__modal-name {
    font-family:     var(--mood-team-modal-name-font-family, var(--wp--preset--font-family--josefin-sans));
    font-weight:     var(--mood-team-modal-name-font-weight, 600);
    font-size:       var(--mood-team-modal-name-font-size, clamp(2rem, 4.5vw, 3.75rem));
    line-height:     var(--mood-team-modal-name-line-height, 1.05);
    letter-spacing:  var(--mood-team-modal-name-letter-spacing, -0.01em);
    font-style:      var(--mood-team-modal-name-font-style, normal);
    margin: 0;
}

.mood-team-member__modal-subtitle {
    font-family:     var(--mood-team-modal-text-font-family, var(--wp--preset--font-family--josefin-sans));
    font-weight:     var(--mood-team-modal-text-font-weight, 300);
    font-size:       var(--mood-team-modal-text-font-size, 1rem);
    line-height:     var(--mood-team-modal-text-line-height, normal);
    letter-spacing:  var(--mood-team-modal-text-letter-spacing, normal);
    font-style:      var(--mood-team-modal-text-font-style, normal);
    color: var(--wp--preset--color--muted);
    margin: 0 0 1rem;
}

.mood-team-member__modal-bio {
    font-family:     var(--mood-team-modal-text-font-family, var(--wp--preset--font-family--josefin-sans));
    font-weight:     var(--mood-team-modal-text-font-weight, 300);
    font-size:       var(--mood-team-modal-text-font-size, clamp(1rem, 1.2vw, 1.125rem));
    line-height:     var(--mood-team-modal-text-line-height, 1.5);
    letter-spacing:  var(--mood-team-modal-text-letter-spacing, normal);
    font-style:      var(--mood-team-modal-text-font-style, normal);
    max-width: 36em;
}

.mood-team-member__modal-bio p + p {
    margin-block-start: 1em !important;
}

.mood-team-member__contact {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    align-self: flex-start;
    width: 2.75rem;
    height: 2.75rem;
    text-decoration: none;
    margin-top: 1.5rem;
}

.mood-team-member__contact svg {
    display: block;
    width: 2.75rem;
    height: 2.75rem;
}

.mood-team-member__modal-image {
    flex: 1 1 50%;
    background: var(--wp--preset--color--rule);
    overflow: hidden;
}

.mood-team-member__modal-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}

/* Ken Burns — slow continuous zoom + diagonal pan, only while
   the modal is open. The slight oversize (scale 1.05 → 1.18)
   keeps the panning translate from revealing the edges. */
.mood-team-member__modal.is-open .mood-team-member__modal-image img {
    animation: moodTeamMemberKenBurns 22s ease-in-out infinite alternate;
    will-change: transform;
}

@keyframes moodTeamMemberKenBurns {
    from { transform: scale(1.05) translate3d(0, 0, 0); }
    to   { transform: scale(1.18) translate3d(-2.5%, -1.5%, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .mood-team-member__modal.is-open .mood-team-member__modal-image img {
        animation: none;
        transform: scale(1.05);
    }
}

/* Close button — circle with X. Top-right on mobile; on desktop
   the entire backdrop closes via the custom cursor, but this
   button stays for accessibility / keyboard / fallback. */
.mood-team-member__close {
    position: fixed;
    top: clamp(1rem, 2vw, 1.5rem);
    right: clamp(1rem, 2vw, 1.5rem);
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    border: 1px solid currentColor;
    background: transparent;
    color: var(--wp--preset--color--contrast);
    cursor: pointer;
    z-index: 10000;
    padding: 0;
}

.mood-team-member__close-icon {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
}

.mood-team-member__close-icon::before,
.mood-team-member__close-icon::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1rem;
    height: 1px;
    background: currentColor;
}

.mood-team-member__close-icon::before {
    transform: translate(-50%, -50%) rotate(45deg);
}

.mood-team-member__close-icon::after {
    transform: translate(-50%, -50%) rotate(-45deg);
}

/* Body scroll lock while a modal is open */
body.mood-team-modal-open {
    overflow: hidden;
}

/* Desktop: the X-in-circle replaces the cursor while hovering the
   modal backdrop — clicking anywhere closes. Interactive elements
   (links, buttons) get the normal pointer back. */
@media (hover: hover) and (pointer: fine) {
    .mood-team-member__modal {
        cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='18' fill='none' stroke='%2310131B' stroke-width='1.5'/%3E%3Cline x1='14' y1='14' x2='26' y2='26' stroke='%2310131B' stroke-width='1.5'/%3E%3Cline x1='26' y1='14' x2='14' y2='26' stroke='%2310131B' stroke-width='1.5'/%3E%3C/svg%3E") 20 20, auto;
    }

    .mood-team-member__modal a,
    .mood-team-member__modal button {
        cursor: pointer;
    }

    /* Hide the redundant close button on desktop — the cursor IS the X. */
    .mood-team-member__close {
        display: none;
    }
}

/* Mobile / tablet: stack the modal vertically; show the close button. */
@media (max-width: 781px) {
    .mood-team-member__modal-inner {
        flex-direction: column;
    }
    .mood-team-member__modal-image {
        flex: 0 0 auto;
        height: 60vh;
        order: -1;
    }
    .mood-team-member__modal-text {
        padding: 2rem 1.5rem;
    }

    /* Per-block mobile aspect-ratio override: replaces the 60vh crop with
       an explicit aspect ratio so the whole image is visible. Set via
       "Modal image → Mobile aspect ratio" in the block sidebar. */
    .mood-team-member--mobile-aspect-1-1  .mood-team-member__modal-image { height: auto; aspect-ratio: 1 / 1;   }
    .mood-team-member--mobile-aspect-4-5  .mood-team-member__modal-image { height: auto; aspect-ratio: 4 / 5;   }
    .mood-team-member--mobile-aspect-3-4  .mood-team-member__modal-image { height: auto; aspect-ratio: 3 / 4;   }
    .mood-team-member--mobile-aspect-2-3  .mood-team-member__modal-image { height: auto; aspect-ratio: 2 / 3;   }
    .mood-team-member--mobile-aspect-9-16 .mood-team-member__modal-image { height: auto; aspect-ratio: 9 / 16;  }
    .mood-team-member--mobile-aspect-4-3  .mood-team-member__modal-image { height: auto; aspect-ratio: 4 / 3;   }
    .mood-team-member--mobile-aspect-3-2  .mood-team-member__modal-image { height: auto; aspect-ratio: 3 / 2;   }
    .mood-team-member--mobile-aspect-16-9 .mood-team-member__modal-image { height: auto; aspect-ratio: 16 / 9;  }

    /* "Auto" — let the image dictate its own height at its natural ratio. */
    .mood-team-member--mobile-aspect-auto .mood-team-member__modal-image {
        height: auto;
        aspect-ratio: auto;
    }
    .mood-team-member--mobile-aspect-auto .mood-team-member__modal-image img {
        height: auto;
        object-fit: contain;
    }
}

/* Editor-only previews (when editing the block in WP editor) ---- */

.mood-team-member-editor__card {
    position: relative;
    aspect-ratio: 4 / 5;
    background: var(--wp--preset--color--contrast);
    color: var(--wp--preset--color--base);
    overflow: hidden;
}

.mood-team-member-editor__thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.mood-team-member-editor__placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--wp--preset--color--base);
    opacity: 0.6;
    font-size: 0.9rem;
    padding: 1rem;
    text-align: center;
}

.mood-team-member-editor__caption {
    position: absolute;
    left: 1.5rem;
    bottom: 1.25rem;
    z-index: 2;
    color: var(--wp--preset--color--base);
}

.mood-team-member-editor__name {
    display: block;
    font-family: var(--wp--preset--font-family--juana);
    font-weight: 600;
    font-size: clamp(1.5rem, 2.4vw, 2.25rem);
    line-height: 1.05;
}

.mood-team-member-editor__subtitle {
    display: block;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-weight: 300;
    font-size: 0.9rem;
    margin-top: 0.35rem;
    opacity: 0.92;
}

.mood-team-member-editor__bio-sidebar {
    margin-top: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 2px;
}

.mood-team-member-editor__bio {
    font-family: var(--wp--preset--font-family--juana);
    font-weight: 300;
    font-size: 0.8125rem;
    line-height: 1.5;
    min-height: 6em;
}

.mood-team-member-editor__bio p {
    margin: 0 0 0.75em;
}

.mood-team-member-editor__bio p:last-child {
    margin-bottom: 0;
}

/* ─────────────────────────────────────────────────────────────
   Image caption — toggled via the Image block's "Caption style"
   sidebar panel. Caption text flows below the image, aligned to
   the chosen corner, with a tall decorative vertical line that
   crosses up from the gap into the image's bottom edge. Caption
   text + line use `--mood-caption-color` (from the panel's color
   picker) and fall back to the figure's current text color.
   ───────────────────────────────────────────────────────────── */

/* Selectors match in two contexts: front-end (the class is on the
   figure itself via the save filter) and editor (the class is on the
   BlockListBlock wrapper via the editor.BlockListBlock filter). */
.mood-caption-left,
.mood-caption-right {
    position: relative;
}

.mood-caption-left figcaption,
.mood-caption-right figcaption {
    position: relative;
    margin: clamp(1rem, 1.6vw, 1.4rem) 0 0;
    padding: 0;
    max-width: 22em;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.875rem, 1vw, 1.125rem);
    font-style: normal;
    font-weight: 400;
    line-height: 1.25;
    color: var(--mood-caption-color, currentColor);
}

.mood-caption-left figcaption {
    margin-right: auto;
    text-align: left;
}
.mood-caption-right figcaption {
    margin-left: auto;
    text-align: right;
}

.mood-caption-left figcaption::before,
.mood-caption-right figcaption::before {
    content: "";
    position: absolute;
    bottom: calc(100% + clamp(0.5rem, 0.8vw, 0.75rem));
    width: 2px;
    height: clamp(2rem, 3vw, 2.75rem);
    background: var(--mood-caption-color, currentColor);
}
.mood-caption-left figcaption::before  { left: clamp(1.5rem, 5%, 4rem); }
.mood-caption-right figcaption::before { right: clamp(1.5rem, 5%, 4rem); }

/* ─────────────────────────────────────────────────────────────
   Eyebrow block (mood/eyebrow) — small section label with an
   optional short rule before / after the text. Inserted from
   the block inserter; line placement is set in the block's
   "Eyebrow" inspector panel. Renders identically in editor +
   front end (style.css is loaded into the editor too).
   ───────────────────────────────────────────────────────────── */

/* Inline-block layout (not flex) so the rule attaches to the wrapped
   end of the text — i.e., the dash sits right after the last word
   ("development —"), not at the right edge of the widest line. A flex
   container would size the text item to the width of its longest line
   and place the dash after that whole block; the gap between the last
   word and the dash would equal (longest-line-width − last-line-width),
   which is exactly the issue this is fixing. */
.wp-block-mood-eyebrow.mood-eyebrow--line-before,
.wp-block-mood-eyebrow.mood-eyebrow--line-after {
    line-height: 1.2;
}

.wp-block-mood-eyebrow.mood-eyebrow--line-before::before,
.wp-block-mood-eyebrow.mood-eyebrow--line-after::after {
    content: "";
    display: inline-block;
    width:  var(--mood-eyebrow-line-length, 3.5rem);
    height: var(--mood-eyebrow-line-thickness, 5px);
    background-color: currentColor;
    vertical-align: middle;
}

.wp-block-mood-eyebrow.mood-eyebrow--line-before::before {
    margin-right: 0.75em;
}
.wp-block-mood-eyebrow.mood-eyebrow--line-after::after {
    margin-left: 0.75em;
}

/* Text alignment now works naturally — the inline rule is part of
   the text flow, so `text-align: center / right` shifts the last
   line (including the dash) without any extra rule. */

/* ─────────────────────────────────────────────────────────────
   Button style: "Arrow link" — text-only button with an arrow
   that slides right on hover. Apply via the block sidebar
   Styles → "Arrow link". The arrow is a masked SVG so it
   inherits the link's text color via currentColor.
   ───────────────────────────────────────────────────────────── */

.wp-block-button.is-style-mood-arrow-link .wp-block-button__link {
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    color: var(--wp--preset--color--contrast);
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-weight: 700;
    letter-spacing: 0.01em;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    line-height: 1.2;
    transition: color 0.25s ease;
}

.wp-block-button.is-style-mood-arrow-link .wp-block-button__link::after {
    content: "";
    display: inline-block;
    width: 1.1em;
    height: 1.1em;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M5 16 L27 16 M20 9 L27 16 L20 23' stroke='black' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M5 16 L27 16 M20 9 L27 16 L20 23' stroke='black' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

.wp-block-button.is-style-mood-arrow-link .wp-block-button__link:hover {
    color: var(--wp--preset--color--accent);
}

.wp-block-button.is-style-mood-arrow-link .wp-block-button__link:hover::after {
    transform: translateX(0.4em);
}

/* Reduce motion: skip the arrow translation, keep the color shift. */
@media (prefers-reduced-motion: reduce) {
    .wp-block-button.is-style-mood-arrow-link .wp-block-button__link::after {
        transition: none;
    }
    .wp-block-button.is-style-mood-arrow-link .wp-block-button__link:hover::after {
        transform: none;
    }
}

/* ─────────────────────────────────────────────────────────────
   Dark theme — full-page inversion (page-dark template)
   ───────────────────────────────────────────────────────────── */

body.has-dark-theme {
    background-color: var(--wp--preset--color--contrast) !important;
    color: var(--wp--preset--color--base);
}

/* Header + footer blend with the dark page (no separate bg/border). */
body.has-dark-theme .mood-site-header,
body.has-dark-theme .mood-site-footer {
    background-color: transparent !important;
    border-top-color: transparent !important;
    border-bottom-color: transparent !important;
    border-top-width: 0 !important;
    border-bottom-width: 0 !important;
    color: var(--wp--preset--color--base);
}

/* Swap to light logo wherever the dark logo would be invisible. */
body.has-dark-theme .mood-logo--dark { display: none !important; }
body.has-dark-theme .mood-logo--light { display: block !important; }

/* Nav text + links flip to light, hover stays accent. */
body.has-dark-theme .mood-site-header,
body.has-dark-theme .mood-site-header .wp-block-navigation a,
body.has-dark-theme .mood-site-header .wp-block-navigation button,
body.has-dark-theme .mood-site-header .wp-block-navigation .wp-block-navigation-item__content,
body.has-dark-theme .mood-site-footer,
body.has-dark-theme .mood-site-footer a,
body.has-dark-theme a {
    color: var(--wp--preset--color--base);
}
body.has-dark-theme .mood-site-header .wp-block-navigation a:hover,
body.has-dark-theme .mood-site-footer a:hover,
body.has-dark-theme a:hover {
    color: var(--wp--preset--color--accent);
}

/* Buttons: invert from dark-on-light to light-on-dark; hover still goes accent. */
body.has-dark-theme .wp-block-button .wp-block-button__link {
    background-color: var(--wp--preset--color--base);
    color: var(--wp--preset--color--contrast);
    border-color: var(--wp--preset--color--base);
}
body.has-dark-theme .wp-block-button .wp-block-button__link:hover {
    background-color: var(--wp--preset--color--accent);
    color: var(--wp--preset--color--base);
    border-color: var(--wp--preset--color--accent);
}

/* ─────────────────────────────────────────────────────────────
   Dark footer
   ───────────────────────────────────────────────────────────── */

body.has-dark-footer .mood-site-footer {
    background-color: var(--wp--preset--color--contrast);
    color: var(--wp--preset--color--base);
    border-top-color: transparent !important;
    border-top-width: 0 !important;
    margin-top: 0 !important;
}
body.has-dark-footer .mood-site-footer .mood-logo--dark { display: none !important; }
body.has-dark-footer .mood-site-footer .mood-logo--light { display: block !important; }
body.has-dark-footer .mood-site-footer,
body.has-dark-footer .mood-site-footer a,
body.has-dark-footer .mood-site-footer .wp-block-navigation a,
body.has-dark-footer .mood-site-footer .wp-block-navigation .wp-block-navigation-item__content {
    color: var(--wp--preset--color--base);
}
body.has-dark-footer .mood-site-footer a:hover,
body.has-dark-footer .mood-site-footer .wp-block-navigation a:hover {
    color: var(--wp--preset--color--accent);
}

/* ─────────────────────────────────────────────────────────────
   Pink footer
   ───────────────────────────────────────────────────────────── */

body.has-pink-footer .mood-site-footer {
    background-color: var(--wp--preset--color--accent);
    color: var(--wp--preset--color--base);
    border-top-color: transparent !important;
    border-top-width: 0 !important;
    margin-top: 0 !important;
}
body.has-pink-footer .mood-site-footer .mood-logo--dark { display: none !important; }
body.has-pink-footer .mood-site-footer .mood-logo--light { display: block !important; }
body.has-pink-footer .mood-site-footer,
body.has-pink-footer .mood-site-footer a,
body.has-pink-footer .mood-site-footer .wp-block-navigation a,
body.has-pink-footer .mood-site-footer .wp-block-navigation .wp-block-navigation-item__content {
    color: var(--wp--preset--color--base);
}
body.has-pink-footer .mood-site-footer a:hover,
body.has-pink-footer .mood-site-footer .wp-block-navigation a:hover {
    color: var(--wp--preset--color--contrast);
}

/* ─────────────────────────────────────────────────────────────
   Responsive columns — overrides core/columns layout at desktop
   (≥782px), tablet (600–781px), and mobile (≤599px) breakpoints.
   Set per block via the "Responsive columns" sidebar panel; the
   JS attaches `mood-desktop-cols-N` / `mood-tablet-cols-N` /
   `mood-mobile-cols-N` classes which flip the columns wrapper
   to CSS Grid with N tracks at that breakpoint.
   ───────────────────────────────────────────────────────────── */

@media (min-width: 782px) {
    .wp-block-columns[class*="mood-desktop-cols-"] {
        display: grid !important;
    }
    .wp-block-columns[class*="mood-desktop-cols-"] > .wp-block-column {
        flex-basis: auto !important;
        width: auto !important;
    }
    .wp-block-columns.mood-desktop-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-desktop-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-desktop-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-desktop-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)) !important; }
}

@media (min-width: 600px) and (max-width: 781px) {
    .wp-block-columns[class*="mood-tablet-cols-"] {
        display: grid !important;
    }
    .wp-block-columns[class*="mood-tablet-cols-"] > .wp-block-column {
        flex-basis: auto !important;
        width: auto !important;
    }
    .wp-block-columns.mood-tablet-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-tablet-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-tablet-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-tablet-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)) !important; }

    /* Force stacking when no tablet-cols class is set. Overrides
       WP's `is-not-stacked-on-mobile` flag (set by core's native
       "Stack on mobile" toggle being off — often inherited from a
       pattern) so mood's "Tablet — Default (stacked)" actually
       stacks instead of silently relying on a flag the user can't
       see from our sidebar. */
    .wp-block-columns:not([class*="mood-tablet-cols-"]) {
        flex-wrap: wrap !important;
    }
    .wp-block-columns:not([class*="mood-tablet-cols-"]) > .wp-block-column {
        flex-basis: 100% !important;
        width: 100% !important;
    }
}

@media (max-width: 599px) {
    /* Note: previously this block reset `--wp--style--block-gap` on
       every .wp-block-columns to spacing|20 so columns kept tight
       internal gaps at mobile. That had a side effect: because the
       reset sets the custom property on the Columns *block element*,
       (a) the Columns block's own sibling gap (which our printer's
       `margin-block-start: var(--wp--style--block-gap, …)` rule reads
       from the variable on the element it's applied to) shrank to
       spacing|20 instead of honoring the Mobile Block Spacing global,
       and (b) every descendant of the Columns block inherited
       spacing|20 too — breaking the mobile rhythm for any content
       sitting inside Columns. Removed. The mobile global now applies
       uniformly; tighten on a specific Columns instance via Block
       Spacing in its sidebar. */

    .wp-block-columns[class*="mood-mobile-cols-"] {
        display: grid !important;
        /* Read the (now correctly-cascaded) variable. Plain `var()`
           with a fallback — no `max()` floor — so per-column "None"
           genuinely means zero. NO `!important` here on purpose: the
           selector's specificity (0,2,0) already beats WP's
           `:root :where(.is-layout-flex)` global (0,1,0), and dropping
           `!important` lets the render_block filter's per-block
           !important override (`mood_columns_per_block_gap_override`
           in functions.php) win when the user has set Block Spacing
           on a specific Columns block. */
        gap: var(--wp--style--block-gap, var(--wp--preset--spacing--20));
    }
    .wp-block-columns[class*="mood-mobile-cols-"] > .wp-block-column {
        flex-basis: auto !important;
        width: auto !important;
    }
    .wp-block-columns.mood-mobile-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-mobile-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-mobile-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
    .wp-block-columns.mood-mobile-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)) !important; }

    /* Force stacking when no mobile-cols class is set — see the
       sibling rule in the tablet media query above for rationale.
       `gap` reads the inherited `--wp--style--block-gap` (mobile
       global from the wp_head printer, or per-Columns override from
       the block sidebar) with spacing|20 as the fallback for sites
       that haven't configured a Mobile Block Spacing default. */
    .wp-block-columns:not([class*="mood-mobile-cols-"]) {
        flex-wrap: wrap !important;
        /* No `!important` on gap — see the mood-mobile-cols sibling
           above for the rationale. */
        gap: var(--wp--style--block-gap, var(--wp--preset--spacing--20));
    }
    .wp-block-columns:not([class*="mood-mobile-cols-"]) > .wp-block-column {
        flex-basis: 100% !important;
        width: 100% !important;
    }

    /* Reverse stacked column order on mobile. Applies to the default
       flex-stack only; combining with `mood-mobile-cols-N` (grid) has
       no effect since grid follows source order. */
    .wp-block-columns.mood-mobile-reverse {
        flex-direction: column-reverse;
    }

    /* Make the columns block span edge-to-edge on mobile. Two parts:
       (1) escape the body's root padding via negative margins (the
       theme uses `useRootPaddingAwareAlignments`, so the visible side
       gutter comes from --wp--style--root--padding-*, not from padding
       on the block itself). Skip for `alignfull` since WP already
       escapes root padding there. (2) zero any block-instance padding
       set via the Block sidebar (inline-styled, hence the !important). */
    .wp-block-columns.mood-mobile-no-padding:not(.alignfull) {
        margin-left:  calc(-1 * var(--wp--style--root--padding-left));
        margin-right: calc(-1 * var(--wp--style--root--padding-right));
    }
    .wp-block-columns.mood-mobile-no-padding {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
    /* Also zero the child columns' own padding — without this, text
       inside a column stays inset by the column's instance padding
       (set via Block sidebar / theme.json) while alignfull images
       escape on their own. */
    .wp-block-columns.mood-mobile-no-padding > .wp-block-column {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
}

/* Vertically center a column's content inside its box. Toggle in the
   "Column layout" sidebar panel on a single Column block. */
.wp-block-column.mood-column-vcenter {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* Default block spacing (gap between columns) is set in theme.json
   via `styles.blocks.core/columns.spacing.blockGap = spacing|20`.
   WP generates a scoped style block that sets `--wp--style--block-gap`
   on each Columns instance, then `.is-layout-flex { gap: var(…) }`
   from core picks it up. Per-instance overrides from the Block
   Spacing sidebar take effect the same way (WP rewrites the variable
   for that specific block). No explicit `gap` rule needed here —
   adding one would override the user's Block Spacing selection. */

/* Section width — set via the "Section width" sidebar panel on a
   Columns block. Three options, each mapped 1:1 to a theme setting:
     • Default Content Width → Site Editor → Styles → Layout →
       Content Width.    No class emitted; WP's layout-constrained
       cascade in post-content handles it (max-width = content-size).
     • Wide Width → Site Editor → Styles → Layout → Wide Width.
       JS emits `alignwide`; WP's cascade gives max-width = wide-size.
     • Narrow Width → Appearance → Layout Settings → Narrow Width.
       JS emits `mood-section-narrow`; CSS below clamps to the
       --mood-narrow-width custom property.
   Legacy class aliases (`mood-section-wide`, `mood-section-full`)
   from earlier iterations are kept so older saved markup still
   renders sensibly until re-saved through the sidebar. */
.wp-block-columns.mood-section-narrow,
.wp-block-columns.mood-section-wide,
/* Editor wrapper: mood-section-narrow is added to .wp-block via the
   BlockListBlock filter so the editor display matches the frontend. */
.block-editor-block-list__layout .wp-block.mood-section-narrow {
    max-width: var(--mood-narrow-width, 800px) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

.wp-block-columns.mood-section-thin,
.block-editor-block-list__layout .wp-block.mood-section-thin {
    max-width: var(--mood-thin-width, 600px) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

.wp-block-columns.mood-section-extra-thin,
.block-editor-block-list__layout .wp-block.mood-section-extra-thin {
    max-width: var(--mood-extra-thin-width, 400px) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

/* Editor: cancel WP's `.alignwide → max-width: wide-size` cascade for
   Columns blocks that aren't *intentionally* Wide Width via mood's
   sidebar. The `mood-wide-confirmed` marker is added alongside
   `alignwide` by the BlockListBlock filter only when
   `moodSectionWidth === 'wide'`, so any other alignwide on a Columns
   wrapper is stale (left over by a legacy `attributes.align` we can't
   always clean) and should fall back to content-size. Narrow/Thin/
   Extra-Thin blocks are excluded so their own width rules above win
   even when a stale `.alignwide` is still present on the wrapper. */
.block-editor-block-list__layout .wp-block.alignwide:not(.mood-wide-confirmed):not(.mood-section-narrow):not(.mood-section-thin):not(.mood-section-extra-thin) {
    max-width: var(--wp--style--global--content-size) !important;
}
.wp-block-columns.mood-section-full {
    /* legacy alias for the previous "Wide Width" iteration. Mapped
       to wide-size to match the new Wide Width semantics. */
    max-width: var(--wp--style--global--wide-size, 100%) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

/* ─────────────────────────────────────────────────────────────
   Featured Articles block (mood/featured-articles) — asymmetric
   grid of 1–6 post cards with image, category badge, title, and
   author/date meta. Layout is selected by the count class emitted
   by render.php (`mood-featured-articles--count-{N}`). The wrapper
   uses aspect-ratio so the relative sizes of the cells stay
   consistent regardless of viewport width.
   ───────────────────────────────────────────────────────────── */

.mood-featured-articles {
    display: grid;
    gap: clamp(0.75rem, 1.2vw, 1.25rem);
}

/* 1 post — full-width hero. */
.mood-featured-articles--count-1 {
    grid-template-columns: 1fr;
    aspect-ratio: 2 / 1;
}

/* 2 posts — side-by-side equal squares. */
.mood-featured-articles--count-2 {
    grid-template-columns: 1fr 1fr;
    aspect-ratio: 2 / 1;
}

/* 3 posts — big-left + two stacked rectangles on the right. */
.mood-featured-articles--count-3 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    aspect-ratio: 2 / 1;
}
.mood-featured-articles--count-3 > :nth-child(1) {
    grid-column: 1;
    grid-row: 1 / span 2;
}
.mood-featured-articles--count-3 > :nth-child(2) {
    grid-column: 2;
    grid-row: 1;
}
.mood-featured-articles--count-3 > :nth-child(3) {
    grid-column: 2;
    grid-row: 2;
}

/* 4 posts — the canonical layout: big-left + wide-top-right +
   two squares below the wide rectangle. 4-column underlying grid
   makes the math work: post 1 spans cols 1–2 / both rows, post 2
   spans cols 3–4 / row 1, post 3 = col 3 row 2, post 4 = col 4 row 2. */
.mood-featured-articles--count-4 {
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 1fr 1fr;
    aspect-ratio: 2 / 1;
}
.mood-featured-articles--count-4 > :nth-child(1) {
    grid-column: 1 / span 2;
    grid-row: 1 / span 2;
}
.mood-featured-articles--count-4 > :nth-child(2) {
    grid-column: 3 / span 2;
    grid-row: 1;
}
.mood-featured-articles--count-4 > :nth-child(3) {
    grid-column: 3;
    grid-row: 2;
}
.mood-featured-articles--count-4 > :nth-child(4) {
    grid-column: 4;
    grid-row: 2;
}

/* 5 posts — 4-layout with post 2 split into two squares instead
   of one wide rectangle. */
.mood-featured-articles--count-5 {
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 1fr 1fr;
    aspect-ratio: 2 / 1;
}
.mood-featured-articles--count-5 > :nth-child(1) {
    grid-column: 1 / span 2;
    grid-row: 1 / span 2;
}
.mood-featured-articles--count-5 > :nth-child(2) { grid-column: 3; grid-row: 1; }
.mood-featured-articles--count-5 > :nth-child(3) { grid-column: 4; grid-row: 1; }
.mood-featured-articles--count-5 > :nth-child(4) { grid-column: 3; grid-row: 2; }
.mood-featured-articles--count-5 > :nth-child(5) { grid-column: 4; grid-row: 2; }

/* 6 posts — 3 × 2 uniform grid. */
.mood-featured-articles--count-6 {
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: 1fr 1fr;
    aspect-ratio: 3 / 2;
}

/* Card. The whole card is a single anchor so the entire surface
   is clickable. Image lives as a background on `.media`, gradient
   overlay is drawn by the link's ::after, content sits in `.content`
   above both via z-index. */
.mood-featured-article {
    position: relative;
    overflow: hidden;
    border-radius: clamp(0.5rem, 0.8vw, 0.875rem);
    background-color: #2a2a2a;
}
.mood-featured-article__link {
    display: block;
    position: relative;
    width: 100%;
    height: 100%;
    color: #fff;
    text-decoration: none;
}
.mood-featured-article__media {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    transition: transform 0.6s ease;
}
.mood-featured-article:hover .mood-featured-article__media {
    transform: scale(1.04);
}
.mood-featured-article__link::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.55) 100%);
    pointer-events: none;
}
.mood-featured-article__content {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: flex-start;
    gap: clamp(0.5rem, 1vw, 0.875rem);
    padding: clamp(1rem, 1.75vw, 1.75rem);
}
/* Typography on each text element reads custom properties with
   the original hardcoded values as fallbacks. Block sidebar →
   per-target typography panels set `--mood-fa-{target}-{prop}` on
   the block wrapper as inline style; per-category colors are set
   on each `__category` span individually (term meta wins, block
   fallback second). */
.mood-featured-article__category {
    background: var(--mood-fa-category-bg-color, rgba(255, 255, 255, 0.92));
    color:      var(--mood-fa-category-text-color, #1a1a1a);
    padding: 0.3em 0.85em;
    border-radius: 999px;
    font-family:    var(--mood-fa-category-font-family,    var(--wp--preset--font-family--josefin-sans));
    font-size:      var(--mood-fa-category-font-size,      clamp(0.75rem, 0.85vw, 0.9rem));
    font-weight:    var(--mood-fa-category-font-weight,    500);
    letter-spacing: var(--mood-fa-category-letter-spacing, 0.02em);
    line-height:    var(--mood-fa-category-line-height,    1.3);
    font-style:     var(--mood-fa-category-font-style,     normal);
}
.mood-featured-article__title {
    display: block;
    font-family:    var(--mood-fa-title-font-family,    var(--wp--preset--font-family--juana));
    font-size:      var(--mood-fa-title-font-size,      clamp(1.1rem, 1.8vw, 1.75rem));
    font-weight:    var(--mood-fa-title-font-weight,    600);
    line-height:    var(--mood-fa-title-line-height,    1.15);
    letter-spacing: var(--mood-fa-title-letter-spacing, normal);
    font-style:     var(--mood-fa-title-font-style,     normal);
    color: #fff;
    margin: 0;
}
/* `__meta` is the shared row container for author + date. Its
   font-family / size affect both unless overridden per child. */
.mood-featured-article__meta {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    color: rgba(255, 255, 255, 0.92);
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.75rem, 0.85vw, 0.9rem);
    line-height: 1.4;
}
.mood-featured-article__author {
    font-family:    var(--mood-fa-author-font-family,    inherit);
    font-size:      var(--mood-fa-author-font-size,      inherit);
    font-weight:    var(--mood-fa-author-font-weight,    inherit);
    line-height:    var(--mood-fa-author-line-height,    inherit);
    letter-spacing: var(--mood-fa-author-letter-spacing, inherit);
    font-style:     var(--mood-fa-author-font-style,     inherit);
}
.mood-featured-article__date {
    font-family:    var(--mood-fa-date-font-family,    inherit);
    font-size:      var(--mood-fa-date-font-size,      inherit);
    font-weight:    var(--mood-fa-date-font-weight,    inherit);
    line-height:    var(--mood-fa-date-line-height,    inherit);
    letter-spacing: var(--mood-fa-date-letter-spacing, inherit);
    font-style:     var(--mood-fa-date-font-style,     inherit);
}
.mood-featured-article__avatar {
    width: 1.75em;
    height: 1.75em;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}
.mood-featured-article__separator {
    opacity: 0.6;
}

/* First-post emphasis — bigger type for the hero card. */
.mood-featured-article--first .mood-featured-article__title {
    font-size: clamp(1.5rem, 2.8vw, 2.75rem);
    line-height: 1.1;
}
.mood-featured-article--first .mood-featured-article__category {
    font-size: clamp(0.85rem, 1vw, 1rem);
    padding: 0.4em 1em;
}
.mood-featured-article--first .mood-featured-article__meta {
    font-size: clamp(0.85rem, 1vw, 1rem);
}
.mood-featured-article--first .mood-featured-article__avatar {
    width: 2em;
    height: 2em;
}

/* Excerpt — opt-in via the "Show excerpt on first post" toggle.
   Only ever rendered on the first card by render.php, so we don't
   need a `--first` qualifier on the selector. */
.mood-featured-article__excerpt {
    display: block;
    color: rgba(255, 255, 255, 0.9);
    font-family:    var(--mood-fa-excerpt-font-family,    var(--wp--preset--font-family--josefin-sans));
    font-size:      var(--mood-fa-excerpt-font-size,      clamp(0.875rem, 1vw, 1.0625rem));
    font-weight:    var(--mood-fa-excerpt-font-weight,    normal);
    line-height:    var(--mood-fa-excerpt-line-height,    1.5);
    letter-spacing: var(--mood-fa-excerpt-letter-spacing, normal);
    font-style:     var(--mood-fa-excerpt-font-style,     normal);
    max-width: 38em;
}

/* Extra-large first-post — opt-in hero scale. Stacks on top of the
   default `--first` rules so we only override what needs to grow. */
.mood-featured-article--first-xl .mood-featured-article__title {
    font-size: clamp(2rem, 4.4vw, 4.25rem);
    line-height: 1.05;
}
.mood-featured-article--first-xl .mood-featured-article__category {
    font-size: clamp(0.95rem, 1.2vw, 1.15rem);
    padding: 0.45em 1.15em;
}
.mood-featured-article--first-xl .mood-featured-article__meta {
    font-size: clamp(0.95rem, 1.15vw, 1.15rem);
}
.mood-featured-article--first-xl .mood-featured-article__avatar {
    width: 2.5em;
    height: 2.5em;
}
.mood-featured-article--first-xl .mood-featured-article__excerpt {
    font-size: clamp(1rem, 1.25vw, 1.25rem);
    max-width: 44em;
}
.mood-featured-article--first-xl .mood-featured-article__content {
    gap: clamp(0.75rem, 1.4vw, 1.25rem);
    padding: clamp(1.25rem, 2.4vw, 2.5rem);
}

/* ─────────────────────────────────────────────────────────────
   Subscribe block (mood/subscribe) — inline email form that
   POSTs to /wp-json/mood/v1/subscribe and writes submissions to
   Flamingo's Address Book.
   ───────────────────────────────────────────────────────────── */

.mood-subscribe {
    display: flex;
    flex-direction: column;
    gap: clamp(0.75rem, 1.2vw, 1.25rem);
    max-width: 32rem;
}
.mood-subscribe.alignwide,
.mood-subscribe.alignfull {
    max-width: none;
}

/* Text-align toolbar control. Margin-auto centers the whole block
   (heading, description, pill row) when the wrapper has a max-width;
   text-align cascades to heading + description. Input text is left
   intact so typed emails don't shift around as the user types. */
.mood-subscribe--align-center {
    margin-inline: auto;
    text-align: center;
}
.mood-subscribe--align-right {
    margin-inline-start: auto;
    text-align: right;
}
.mood-subscribe--align-center .mood-subscribe__input,
.mood-subscribe--align-right .mood-subscribe__input {
    text-align: start;
}

.mood-subscribe__heading {
    margin: 0;
    font-family: var(--wp--preset--font-family--juana);
    font-size: clamp(1.5rem, 2.2vw, 2.25rem);
    font-weight: 600;
    line-height: 1.15;
}

.mood-subscribe__description {
    margin: 0;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.95rem, 1vw, 1.0625rem);
    line-height: 1.5;
    opacity: 0.85;
}

/* Single pill: input + button share one rounded border. The
   button is a nested pill sitting inside, flush against the
   right edge. Focus ring lives on the row so tabbing into the
   input highlights the whole pill, not just the inner field. */
.mood-subscribe__row {
    display: flex;
    align-items: center;
    gap: 0;
    border: 1px solid currentColor;
    border-radius: 999px;
    padding: 0.3em;
}
.mood-subscribe__row:focus-within {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

.mood-subscribe__label {
    flex: 1 1 0;
    display: block;
    margin: 0;
    min-width: 0;
}

.mood-subscribe__input {
    width: 100%;
    padding: 0.5em 1em;
    border: 0;
    background: transparent;
    color: inherit;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: 1rem;
    line-height: 1.3;
    appearance: none;
}
.mood-subscribe__input:focus { outline: 0; }
.mood-subscribe__input::placeholder {
    color: inherit;
    opacity: 0.55;
}

.mood-subscribe__button {
    flex: 0 0 auto;
    padding: 0.55em 1.4em;
    border: 1px solid currentColor;
    border-radius: 999px;
    /* Default to the theme's accent (pink) on the contrast text
       color (white in light theme, black in dark via WP's
       contrast-based base/contrast pair). The block sidebar's
       Button colors panel overrides via inline style. */
    background: var(--wp--preset--color--accent, currentColor);
    color: var(--wp--preset--color--base, #fff);
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
    transition: opacity 0.2s ease;
    white-space: nowrap;
}
.mood-subscribe__button:hover { opacity: 0.85; }
.mood-subscribe__button:disabled,
.mood-subscribe__button.is-busy {
    cursor: progress;
    opacity: 0.6;
}

.mood-subscribe__feedback {
    margin: 0;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.875rem, 0.95vw, 1rem);
    line-height: 1.4;
}
.mood-subscribe__feedback--success { color: var(--wp--preset--color--accent, currentColor); }
.mood-subscribe__feedback--error   { color: #c0392b; }

/* Editor preview — disable the real input + button so they don't
   distract from RichText editing, but keep them looking like the
   front end. The `disabled` attr on the editor markup handles
   interaction; this just visually softens them. */
.editor-styles-wrapper .mood-subscribe__input[disabled],
.editor-styles-wrapper .mood-subscribe__button[disabled] {
    opacity: 0.7;
    cursor: default;
}

/* Mobile — stack everything in a single column. Drop the wrapper
   aspect-ratio and let each card own its own. */
@media (max-width: 781px) {
    .mood-featured-articles,
    .mood-featured-articles[class*="mood-featured-articles--count-"] {
        grid-template-columns: 1fr !important;
        grid-template-rows: none !important;
        aspect-ratio: auto !important;
    }
    .mood-featured-articles > .mood-featured-article {
        grid-column: auto !important;
        grid-row: auto !important;
        aspect-ratio: 16 / 10;
    }
    /* First-post mobile aspect-ratio override — opt-in via the
       "First post mobile aspect ratio" select. Keeps the regular
       cards on 16/10 while letting the hero card stand taller (or
       wider). Order-in-source beats the rule above at equal
       specificity. */
    .mood-featured-articles > .mood-featured-article--first-mobile-landscape { aspect-ratio: 16 / 9; }
    .mood-featured-articles > .mood-featured-article--first-mobile-square    { aspect-ratio: 1 / 1; }
    .mood-featured-articles > .mood-featured-article--first-mobile-portrait  { aspect-ratio: 4 / 5; }
    .mood-featured-articles > .mood-featured-article--first-mobile-tall      { aspect-ratio: 3 / 4; }
    .mood-featured-articles > .mood-featured-article--first-mobile-xtall     { aspect-ratio: 2 / 3; }
    .mood-featured-articles > .mood-featured-article--first-mobile-story     { aspect-ratio: 9 / 16; }
}

/* ─────────────────────────────────────────────────────────────
   Page Links block (mood/page-links) — vertical stack of
   full-width page cards. Each card is an <a> with the target
   page's featured image as background and the page title
   centered on top. Aspect ratio is selectable per-card-set for
   desktop and mobile independently.
   ───────────────────────────────────────────────────────────── */

/* Sticky-stack layout: each card pins at the top of the viewport
   on scroll. Because cards are siblings in normal flow, later
   cards paint over earlier stuck cards as they scroll up — giving
   the "card 2 slides over card 1, sticks, card 3 slides over,
   etc." effect with no JS. Sticky needs `display: block` (not
   flex) on the parent: flex items participate in sticky, but the
   plain block layout keeps the math simpler.

   IMPORTANT: don't add `overflow: hidden` (or any non-visible
   overflow) to .mood-page-links or any ancestor — it kills
   position: sticky silently. */
.mood-page-links {
    display: block;
    width: 100%;
}

.mood-page-link {
    position: sticky;
    top: 0;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    background-color: #1a1a1a;
    background-size: cover;
    background-position: center;
    color: #fff;
    text-decoration: none;
    overflow: hidden;
}

/* Dim overlay — sits between the background image and the title.
   Inline `opacity` from render.php drives the dim amount; the
   element is omitted entirely when dim is 0. */
.mood-page-link__overlay {
    position: absolute;
    inset: 0;
    background: #000;
    z-index: 1;
    transition: opacity 0.3s ease;
    pointer-events: none;
}
.mood-page-link:hover .mood-page-link__overlay {
    opacity: 0.15 !important;
}

/* Title overlay. Every typography knob below is a CSS custom
   property the block sets inline on the wrapper (one per option
   in the "Title typography" sidebar panel). Each property has a
   fallback here so untouched blocks render with the theme's
   default look without needing inline overrides. */
.mood-page-link__title {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    align-items: var(--mood-title-align, center);
    justify-content: var(--mood-title-justify, center);
    padding: clamp(1rem, 4vw, 3rem);
    text-align: var(--mood-title-text-align, center);
    font-family: var(--mood-title-font-family, var(--wp--preset--font-family--juana));
    font-size: var(--mood-title-font-size, clamp(2rem, 5.5vw, 5rem));
    font-weight: var(--mood-title-font-weight, 600);
    line-height: var(--mood-title-line-height, 1.1);
    letter-spacing: var(--mood-title-letter-spacing, normal);
    text-transform: var(--mood-title-text-transform, none);
    color: var(--mood-title-color, inherit);
}

/* Space between cards — driven by the `--mood-page-links-gap`
   custom property the wrapper sets inline (resolved from the
   theme's spacingScale preset chosen in the block sidebar).
   Extra `margin-bottom` on each card except the last extends the
   scroll distance before the next card's top reaches the
   viewport-top sticky threshold, so the current card stays solo
   at the top for that gap before the next one slides up. */
.mood-page-links > .mood-page-link:not(:last-child) {
    margin-bottom: var(--mood-page-links-gap, 0);
}

/* Desktop aspect-ratio modifiers. */
.mood-page-link--ratio-wide      { aspect-ratio: 21 / 9; }
.mood-page-link--ratio-landscape { aspect-ratio: 16 / 9; }
.mood-page-link--ratio-classic   { aspect-ratio: 4 / 3; }
.mood-page-link--ratio-square    { aspect-ratio: 1 / 1; }
.mood-page-link--ratio-portrait  { aspect-ratio: 4 / 5; }
.mood-page-link--ratio-tall      { aspect-ratio: 3 / 4; }
.mood-page-link--ratio-xtall     { aspect-ratio: 2 / 3; }
.mood-page-link--ratio-story     { aspect-ratio: 9 / 16; }

/* Mobile overrides — same specificity as desktop modifiers, win
   by being later in source while the media query matches. */
@media (max-width: 781px) {
    .mood-page-link--mobile-ratio-wide      { aspect-ratio: 21 / 9; }
    .mood-page-link--mobile-ratio-landscape { aspect-ratio: 16 / 9; }
    .mood-page-link--mobile-ratio-classic   { aspect-ratio: 4 / 3; }
    .mood-page-link--mobile-ratio-square    { aspect-ratio: 1 / 1; }
    .mood-page-link--mobile-ratio-portrait  { aspect-ratio: 4 / 5; }
    .mood-page-link--mobile-ratio-tall      { aspect-ratio: 3 / 4; }
    .mood-page-link--mobile-ratio-xtall     { aspect-ratio: 2 / 3; }
    .mood-page-link--mobile-ratio-story     { aspect-ratio: 9 / 16; }
    .mood-page-link__title {
        font-size: var(--mood-title-font-size, clamp(1.75rem, 8vw, 3.25rem));
    }
}

/* Editor-only — the sidebar page picker list. Kept light, since
   the editor preview itself is rendered via ServerSideRender and
   inherits the front-end styles above. */
.mood-page-links-editor__list {
    list-style: none;
    margin: 0 0 12px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mood-page-links-editor__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    background: #fff;
}
.mood-page-links-editor__title {
    flex: 1 1 auto;
    font-size: 13px;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mood-page-links-editor__actions {
    flex: 0 0 auto;
    display: inline-flex;
    gap: 2px;
}
.mood-page-links-editor__hint {
    margin: 0 0 12px;
    font-size: 12px;
    color: #757575;
}

/* ─────────────────────────────────────────────────────────────
   Mobile font-size override (mood/mobile-font-size.js).
   The block extension injects a `mood-mobile-fs-<slug>` class
   onto core/paragraph and core/heading wrappers when the user
   picks a mobile size in the sidebar. These rules apply the
   chosen theme.json font-size preset on viewports ≤ 781px.

   `!important` is required because core's `has-<slug>-font-size`
   classes apply `font-size` with `!important`, and the desktop
   size needs to be beaten on narrow viewports.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 781px) {
    .mood-mobile-fs-x-small  { font-size: var(--wp--preset--font-size--x-small)  !important; }
    .mood-mobile-fs-small    { font-size: var(--wp--preset--font-size--small)    !important; }
    .mood-mobile-fs-medium   { font-size: var(--wp--preset--font-size--medium)   !important; }
    .mood-mobile-fs-large    { font-size: var(--wp--preset--font-size--large)    !important; }
    .mood-mobile-fs-x-large  { font-size: var(--wp--preset--font-size--x-large)  !important; }
    /* `2xl` slug starts with a digit — WP doesn't always generate
       `--wp--preset--font-size--2xl` for digit-prefixed slugs. Fall
       back to the theme.json size value so this option still works. */
    .mood-mobile-fs-2xl      { font-size: var(--wp--preset--font-size--2xl, 2.875rem) !important; }
    .mood-mobile-fs-xx-large { font-size: var(--wp--preset--font-size--xx-large) !important; }
    .mood-mobile-fs-display  { font-size: var(--wp--preset--font-size--display)  !important; }
}

/* ─────────────────────────────────────────────────────────────
   Hero slide — mobile element controls (hero-element-controls.js).
   Per-slide overrides for the inner wordmark image and subtitle
   paragraph at viewports ≤ 781px.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 781px) {
    /* Wordmark mobile width — overrides the default `max-width:
       90vw` from the base `.mood-hero .mood-hero-wordmark` rule.
       `!important` is required because the base rule uses it. */
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-40  { max-width: 40vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-50  { max-width: 50vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-60  { max-width: 60vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-70  { max-width: 70vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-80  { max-width: 80vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-90  { max-width: 90vw  !important; }
    .mood-hero .mood-hero-wordmark.mood-hero-wordmark--mobile-w-100 { max-width: 100vw !important; }

    /* Subtitle mobile letter spacing. */
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-tracking-tight  { letter-spacing: -0.02em; }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-tracking-normal { letter-spacing: 0;       }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-tracking-wide   { letter-spacing: 0.04em;  }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-tracking-wider  { letter-spacing: 0.1em;   }

    /* Subtitle mobile line height. */
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-leading-tight   { line-height: 1.05; }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-leading-snug    { line-height: 1.15; }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-leading-normal  { line-height: 1.3;  }
    .mood-hero .mood-hero-subtitle.mood-hero-subtitle--mobile-leading-relaxed { line-height: 1.5;  }
}

/* ─────────────────────────────────────────────────────────────
   Sticky Menu block (mood/sticky-menu) — invisible inline; the
   menu only shows up once the user scrolls past the block's
   original position.
     • Desktop (≥782px): slides in from the right (or left) edge,
       text rotated 90° so each item reads vertically.
     • Mobile (<782px): sticks horizontally to the top.

   The wrapper `<nav>` stays in normal document flow but renders
   nothing visible — only the zero-size sentinel inside it sits
   in flow as a scroll trigger. The `<ul>` is ALWAYS
   `position: fixed`, hidden off-screen via `transform`, and
   slides in when `.is-pinned` flips. This avoids:
     • Visible inline rendering at the block's spot
     • Layout shift / "content fluctuation" when pin toggles
       (the menu is never in flow, so its appearance/disappearance
       doesn't reflow document content)
     • The display: none → flex flash that breaks transitions

   Sentinel + IntersectionObserver in view.js drives the
   `.is-pinned` class — see comments in that file for details. */

.mood-sticky-menu {
    /* In-flow wrapper. Renders nothing visible — only the sentinel
       inside it occupies a (zero-height) spot in flow.

       `margin: 0 !important` is critical: WP's `.is-layout-flow > * + *`
       rule applies `margin-block-start: var(--wp--style--block-gap)`
       to every direct layout-flow child that has a preceding sibling
       — and to the wrapper's next sibling too. Without this override
       the invisible sticky-menu block ends up contributing a full
       `block-gap` of its own ON TOP of the next sibling's block-gap,
       so the visual gap between the surrounding content blocks
       doubles. Zeroing the wrapper's margin removes its contribution
       while leaving the natural gap between the surrounding blocks
       intact. */
    position: relative;
    display: block;
    margin: 0 !important;
    padding: 0 !important;
}
.mood-sticky-menu__sentinel {
    /* Zero-size scroll-trigger marker. Stays in document flow
       regardless of pinned state, so its `getBoundingClientRect`
       is a stable source of truth for "has the original block
       position scrolled past viewport-top?" */
    display: block;
    width: 0;
    height: 0;
    pointer-events: none;
}

/* The visible menu — always position: fixed, always rendered,
   hidden off-screen by default via a stacked hide:
     • opacity: 0 + visibility: hidden — guarantees invisibility
       regardless of where the transform places the box (handles
       quirks where transform alone might leave the list visible,
       e.g. an ancestor with `transform`/`filter` that creates a
       containing block, or zero-height intermediate states).
     • transform: translate… — handles the slide-in animation.

   Slide-in is purely a transform animation between the off-screen
   starting transform (set per-anchor in the media queries below)
   and translate(0). */
/* Sticky-menu theme-aware color vars. Default = base bg / contrast
   text (light-theme page). Flipped on `body.has-dark-theme` so the
   pinned bar matches the page beneath it. Same pattern as the
   mobile menu's `--mood-mobile-menu-bg-default` setup above. */
:root {
    --mood-sticky-menu-bg:    var(--wp--preset--color--base, #ffffff);
    --mood-sticky-menu-color: var(--wp--preset--color--contrast, #10131B);
}
body.has-dark-theme {
    --mood-sticky-menu-bg:    var(--wp--preset--color--contrast, #10131B);
    --mood-sticky-menu-color: var(--wp--preset--color--base, #ffffff);
}

.mood-sticky-menu__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    position: fixed;
    z-index: 50;
    gap: clamp(1rem, 2.5vw, 2rem);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    /* No transition until `.is-ready` is added (one RAF after
       init) so the very first paint doesn't animate from off-screen
       on a page that was loaded already scrolled. */
    transition: none;
}
.mood-sticky-menu.is-ready .mood-sticky-menu__list {
    transition:
        opacity 0.3s ease,
        transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
        visibility 0s linear 0.5s;
}
.mood-sticky-menu.is-pinned .mood-sticky-menu__list {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}
.mood-sticky-menu.is-pinned.is-ready .mood-sticky-menu__list {
    transition:
        opacity 0.3s ease,
        transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
        visibility 0s;
}
.mood-sticky-menu__item { margin: 0; padding: 0; }
.mood-sticky-menu__link {
    color: inherit;
    text-decoration: none;
    font-family: var(--wp--preset--font-family--josefin-sans);
    font-size: clamp(0.95rem, 1.1vw, 1.125rem);
    letter-spacing: 0.04em;
    transition: opacity 0.2s ease;
}
.mood-sticky-menu__link:hover { opacity: 0.65; }
/* "Current page" emphasis — single-letter underline on the first
   glyph, matching the reference (the underlined "h" in "hospitality"). */
.mood-sticky-menu__item--current .mood-sticky-menu__link::first-letter {
    text-decoration: underline;
    text-underline-offset: 0.18em;
    text-decoration-thickness: 0.05em;
}

/* ── Desktop ───────────────────────────────────────────────────
   Pinned to the anchor edge, vertical text. List starts off-screen
   via translateX; `.is-pinned` slides it in. */
@media (min-width: 782px) {
    .mood-sticky-menu__list {
        top: 0;
        height: 100vh;
        flex-direction: column;
        align-items: center;
        padding: clamp(1.5rem, 3vw, 2.5rem) clamp(0.75rem, 1.25vw, 1.25rem);
        gap: clamp(1rem, 1.5vw, 1.75rem);
    }
    .mood-sticky-menu__link {
        writing-mode: vertical-rl;
        text-orientation: mixed;
    }

    /* Anchor edges + off-screen starting transforms */
    .mood-sticky-menu--anchor-right .mood-sticky-menu__list {
        right: 0;
        transform: translateX(100%);
    }
    .mood-sticky-menu--anchor-left .mood-sticky-menu__list {
        left: 0;
        transform: translateX(-100%);
    }
    /* Slide in when pinned */
    .mood-sticky-menu.is-pinned.mood-sticky-menu--anchor-right .mood-sticky-menu__list,
    .mood-sticky-menu.is-pinned.mood-sticky-menu--anchor-left  .mood-sticky-menu__list {
        transform: translateX(0);
    }

    /* Vertical alignment on the pinned edge */
    .mood-sticky-menu--valign-top    .mood-sticky-menu__list { justify-content: flex-start; }
    .mood-sticky-menu--valign-center .mood-sticky-menu__list { justify-content: center;     }
    .mood-sticky-menu--valign-bottom .mood-sticky-menu__list { justify-content: flex-end;   }
}

/* ── Mobile ────────────────────────────────────────────────────
   Pinned to the top of the viewport, horizontal layout. List
   starts off-screen above via translateY. */
@media (max-width: 781px) {
    .mood-sticky-menu__list {
        top: 0;
        left: 0;
        right: 0;
        flex-direction: row;
        justify-content: center;
        gap: clamp(0.75rem, 3vw, 1.5rem);
        padding: 0.75rem var(--wp--style--root--padding-left, 1.25rem);
        background: var(--mood-sticky-menu-bg);
        color: var(--mood-sticky-menu-color);
        box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        transform: translateY(-100%);
    }
    .mood-sticky-menu.is-pinned .mood-sticky-menu__list {
        transform: translateY(0);
    }
    /* No admin-bar offset — the menu pins flush to viewport top on
       mobile, exactly the way it does for end-visitors. (Logged-in
       admins viewing mobile may see the WP toolbar overlap the very
       top of the menu, which is the same behavior as any other
       fixed-position element on the site.) */
}

/* Editor-only — show the items inline so the author can see the
   list in place and know exactly where the scroll trigger sits.
   view.js doesn't run in the editor, so `.is-pinned` never fires
   here anyway; we just need to override the always-fixed front-end
   styling. */
.mood-sticky-menu--editor {
    border: 1px dashed #ddd;
    padding: 1rem;
    border-radius: 4px;
}
.mood-sticky-menu--editor .mood-sticky-menu__sentinel { display: none; }
.mood-sticky-menu--editor .mood-sticky-menu__list {
    position: static !important;
    transform: none !important;
    transition: none !important;
    /* Counter the front-end hide stack so the editor preview is
       actually visible to the author. */
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    height: auto !important;
    padding: 0 !important;
    background: transparent !important;
    color: inherit !important;
    box-shadow: none !important;
    overflow: visible !important;
    justify-content: center !important;
}
.mood-sticky-menu--editor .mood-sticky-menu__link {
    writing-mode: horizontal-tb !important;
}
