/* ==========================================================================
   Theme
   ==========================================================================
   Everything in this file is about COLOR AND SHAPE, never about position or
   spacing (that's assets/css/site.css). Two kinds of rules live here:

   1. The couple of plain CSS rules a page needs regardless of components
      (link color, the <m3e-theme> host itself).

   2. Component re-skinning, done the way M3E is designed to be re-skinned:
      every component reads its colors from small, component-scoped CSS
      custom properties (e.g. --m3e-app-bar-container-color), each one
      falling back to a shared Material role token (e.g.
      --md-sys-color-surface) if you don't set it. Redefining one of
      those custom properties on an ancestor is enough to re-theme every
      instance below it - no need to fight the component's Shadow DOM,
      because custom properties are inherited straight through it.

      The exact property names below (--m3e-app-bar-*, --m3e-button-*,
      --m3e-icon-button-*) come straight from M3E's own source
      (packages/web/src/.../styles/...Token.ts on
      https://github.com/matraic/m3e) - if a future M3E upgrade renames
      one of these, that's the first place to check.
   ========================================================================== */

/* ==========================================================================
   Raw color tokens
   ==========================================================================
   Every literal color value used anywhere in this file - brand colors,
   plain black/white - is declared exactly once here, under a plain,
   easy-to-scan name. Nothing below this block ever writes a hex code (or
   a bare `white`/`black` keyword) directly into a rule again - it only
   ever references one of these by name, the same discipline the M3
   system tokens (--md-sys-color-*) already follow one layer up. Two
   concrete wins from that: a color only ever needs to change in one
   place, and this block alone IS the site's entire literal-color
   surface - grep it once, nothing is hiding three sections down inside a
   color-mix().
   --color-ivory is a plain hex like every other entry here, not a
   color-mix() result kept in a variable - #edeef0, white with only the
   faintest cool tinge of the brand slate (92/8), computed once by hand
   instead of asking the browser to recompute that same fixed blend on
   every paint. Deliberately mixed with slate, not cream - an earlier
   version leaned on cream instead and read as visibly yellow for a
   color meant to be "the light scheme's white/light-gray surface"; a
   whisper of the cool, near-neutral slate keeps it reading as white/
   light gray instead.
   --color-frost (#e9eeff) is a pale, cool near-white with a whisper of
   blue - freely chosen, not derived. No longer used by the light
   scheme's own block3-end (below), which moved on to a slate/ivory
   color-mix() a few revisions back; kept declared since nothing else on
   the site has replaced its specific look yet.
   --color-gold-dark (#8a6d1f) is a muted, desaturated dark gold/amber -
   freely chosen to match the site's own generally muted palette rather
   than a bright, saturated gold. Used in a small color-mix() nudge on
   the light scheme's own block3-end (below), never referenced directly
   anywhere else.
   --color-graphite (#2e2e2e) is a true hue-less neutral gray, picked at
   roughly --color-slate's own perceived lightness - it only ever feeds
   --color-slate-muted, below, never referenced directly anywhere else.
   --color-slate-muted is slate itself pulled toward graphite (currently
   35% slate, 65% graphite - nudged up from 20%, then 28%, in small steps
   on request, each time pulling a little more of slate's own blue-violet
   back in) - not a fresh hand-picked color, a genuine color-mix() of the
   two above, so it drifts if either of its ingredients ever does. Used in
   place of --color-slate for every dark-scheme surface-family role
   (background, surface, surface-dim/bright/variant, every surface-
   container step, outline/outline-variant, below) so the ENTIRE family
   - including things like the mobile nav popup's own background, which
   reads one of those same container roles - shifts together and keeps
   reading as one consistent surface, rather than some of those roles
   staying on slate's full blue accent while only background/surface
   moved off it. Kept as a separate token from plain --color-slate
   rather than overwriting that anchor's own value, since slate keeps
   its original, undiluted role elsewhere - the light scheme's tertiary
   accent group, further down, still wants the real, fully blue slate. */
:root {
    --color-white: #ffffff;
    --color-black: #000000;
    --color-slate: #212742;
    --color-graphite: #2e2e2e;
    --color-slate-muted: color-mix(
        in srgb,
        var(--color-slate) 35%,
        var(--color-graphite) 65%
    );
    --color-cream: #f7ecc4;
    --color-amethyst: #7884d1;
    --color-iris: #8066c2;
    --color-ivory: #edeef0;
    --color-frost: #e9eeff;
    --color-gold-dark: #8a6d1f;
}

/* ==========================================================================
   Custom color anchors
   ==========================================================================
   m3e-theme (_layouts/default.html) generates the site's whole Material
   color system - primary, secondary, tertiary, every surface/container/
   outline role, for both light AND dark - from the single seed color
   passed as its `color` attribute (#818dc0), using the standard M3
   dynamic-color (HCT) algorithm. That's still exactly where
   --md-sys-color-primary and everything derived from it (on-primary,
   primary-container, secondary, ...) comes from below - already correct,
   untouched here.

   What that algorithm can't do on its own is anchor the SURFACE and
   TERTIARY role groups to two further, specific brand colors instead of
   whatever it would otherwise derive by rotating that same single seed
   hue - m3e-theme only ever takes one seed color, so the other two below
   are anchored by hand instead:
     - --color-slate       - the dark scheme's surface/background group.
     - --color-cream       - the dark scheme's tertiary (accent) group.
   (The seed itself, #818dc0 above, has no CSS variable of its own here -
   it's only ever read from that HTML attribute, never referenced from a
   CSS rule, so it never earned a place in the raw color tokens block.)
   The light scheme (freely chosen) reuses the same two colors with their
   roles SWAPPED - slate reused as light's own tertiary accent - so the
   two schemes read as two sides of one design instead of unrelated
   palettes, with primary constant across both. The light scheme's own
   SURFACE group, however, anchors to --color-ivory rather than
   --color-cream directly - see that variable's own comment above for
   why.

   Every "on-X"/"X-container" role below is hand-derived from its anchor
   with color-mix() for comfortable contrast, rather than a true HCT
   tonal palette - computing exact Material tonal steps needs the same
   color-science this library itself runs in JS, and this project has no
   build step to run that kind of computation ahead of time.

   Every rule below needs !important, and has to target m3e-theme
   directly (not :root): m3e-theme recomputes its entire palette into a
   real stylesheet (a CSSStyleSheet, adopted onto the document) every
   time its color/scheme/contrast properties change - confirmed in its
   source - and per the Constructable Stylesheets spec, an adopted
   stylesheet cascades AFTER the document's own <link> stylesheets
   (this one included) regardless of selector specificity, so a plain
   override would silently lose to the library's own freshly-generated
   value every time it recomputes. And since a role like
   --md-sys-color-surface is set BY THE LIBRARY directly on the
   m3e-theme element itself, a value merely inherited from an ancestor
   like :root would still lose to it too - a value set directly on an
   element always wins over one it only inherited, independent of
   specificity. Targeting m3e-theme directly, with !important, is what
   actually wins both of those fights.

   Each color is repeated once for the automatic case (OS preference,
   under scheme="auto" - the default) and once for an explicit user
   choice (the theme toggle in assets/js/app.js sets scheme="light"/"dark"
   directly, which should apply regardless of the OS's own preference).
   ========================================================================== */

@media (prefers-color-scheme: dark) {
    m3e-theme:not([scheme="light"]) {
        --md-sys-color-background: var(--color-slate-muted) !important;
        --md-sys-color-on-background: color-mix(
            in srgb,
            var(--color-cream) 12%,
            var(--color-white) 88%
        ) !important;
        --md-sys-color-surface: var(--color-slate-muted) !important;
        --md-sys-color-on-surface: color-mix(
            in srgb,
            var(--color-cream) 12%,
            var(--color-white) 88%
        ) !important;
        --md-sys-color-surface-dim: color-mix(
            in srgb,
            var(--color-slate-muted) 85%,
            var(--color-black) 15%
        ) !important;
        --md-sys-color-surface-bright: color-mix(
            in srgb,
            var(--color-slate-muted) 85%,
            var(--color-white) 15%
        ) !important;
        --md-sys-color-surface-variant: color-mix(
            in srgb,
            var(--color-slate-muted) 75%,
            var(--color-black) 25%
        ) !important;
        --md-sys-color-on-surface-variant: color-mix(
            in srgb,
            var(--color-slate-muted) 15%,
            var(--color-white) 85%
        ) !important;
        --md-sys-color-surface-container-lowest: color-mix(
            in srgb,
            var(--color-slate-muted) 82%,
            var(--color-black) 18%
        ) !important;
        --md-sys-color-surface-container-low: color-mix(
            in srgb,
            var(--color-slate-muted) 92%,
            var(--color-black) 8%
        ) !important;
        --md-sys-color-surface-container: var(--color-slate-muted) !important;
        --md-sys-color-surface-container-high: color-mix(
            in srgb,
            var(--color-slate-muted) 88%,
            var(--color-white) 12%
        ) !important;
        --md-sys-color-surface-container-highest: color-mix(
            in srgb,
            var(--color-slate-muted) 76%,
            var(--color-white) 24%
        ) !important;
        --md-sys-color-outline: color-mix(
            in srgb,
            var(--color-slate-muted) 45%,
            var(--color-white) 55%
        ) !important;
        --md-sys-color-outline-variant: color-mix(
            in srgb,
            var(--color-slate-muted) 68%,
            var(--color-white) 32%
        ) !important;
        --md-sys-color-tertiary: var(--color-cream) !important;
        --md-sys-color-on-tertiary: color-mix(
            in srgb,
            var(--color-slate) 88%,
            var(--color-black) 12%
        ) !important;
        --md-sys-color-tertiary-container: var(--color-amethyst) !important;
        /* Was a flat var(--color-white) - the one dark-scheme text role
           still using pure stark white while on-background/on-surface
           right above both already use this exact cream-tinted-white
           color-mix() instead. .app-titlebar (site.css) and this
           panel's own name/description (.profile-panel__name/
           __description, site.css - both already read this same token,
           not a literal white) now land on the same softer off-white
           as the rest of the page's dark-mode text instead of standing
           out as the one pure-white surface on it. */
        --md-sys-color-on-tertiary-container: color-mix(
            in srgb,
            var(--color-cream) 12%,
            var(--color-white) 88%
        ) !important;
        --color-block3-end: color-mix(
            in srgb,
            var(--md-sys-color-primary-container) 82%,
            var(--color-black) 18%
        );
        --color-block3-glow: var(--color-iris);
    }
}

m3e-theme[scheme="dark"] {
    --md-sys-color-background: var(--color-slate-muted) !important;
    --md-sys-color-on-background: color-mix(
        in srgb,
        var(--color-cream) 12%,
        var(--color-white) 88%
    ) !important;
    --md-sys-color-surface: var(--color-slate-muted) !important;
    --md-sys-color-on-surface: color-mix(
        in srgb,
        var(--color-cream) 12%,
        var(--color-white) 88%
    ) !important;
    --md-sys-color-surface-dim: color-mix(
        in srgb,
        var(--color-slate-muted) 85%,
        var(--color-black) 15%
    ) !important;
    --md-sys-color-surface-bright: color-mix(
        in srgb,
        var(--color-slate-muted) 85%,
        var(--color-white) 15%
    ) !important;
    --md-sys-color-surface-variant: color-mix(
        in srgb,
        var(--color-slate-muted) 75%,
        var(--color-black) 25%
    ) !important;
    --md-sys-color-on-surface-variant: color-mix(
        in srgb,
        var(--color-slate-muted) 15%,
        var(--color-white) 85%
    ) !important;
    --md-sys-color-surface-container-lowest: color-mix(
        in srgb,
        var(--color-slate-muted) 82%,
        var(--color-black) 18%
    ) !important;
    --md-sys-color-surface-container-low: color-mix(
        in srgb,
        var(--color-slate-muted) 92%,
        var(--color-black) 8%
    ) !important;
    --md-sys-color-surface-container: var(--color-slate-muted) !important;
    --md-sys-color-surface-container-high: color-mix(
        in srgb,
        var(--color-slate-muted) 88%,
        var(--color-white) 12%
    ) !important;
    --md-sys-color-surface-container-highest: color-mix(
        in srgb,
        var(--color-slate-muted) 76%,
        var(--color-white) 24%
    ) !important;
    --md-sys-color-outline: color-mix(
        in srgb,
        var(--color-slate-muted) 45%,
        var(--color-white) 55%
    ) !important;
    --md-sys-color-outline-variant: color-mix(
        in srgb,
        var(--color-slate-muted) 68%,
        var(--color-white) 32%
    ) !important;
    --md-sys-color-tertiary: var(--color-cream) !important;
    --md-sys-color-on-tertiary: color-mix(
        in srgb,
        var(--color-slate) 88%,
        var(--color-black) 12%
    ) !important;
    --md-sys-color-tertiary-container: var(--color-amethyst) !important;
    --md-sys-color-on-tertiary-container: var(--color-white) !important;
    --color-block3-end: color-mix(
        in srgb,
        var(--md-sys-color-primary-container) 82%,
        var(--color-black) 18%
    );
    --color-block3-glow: var(--color-iris);
}

@media (prefers-color-scheme: light) {
    m3e-theme:not([scheme="dark"]) {
        --md-sys-color-background: var(--color-ivory) !important;
        --md-sys-color-on-background: color-mix(
            in srgb,
            var(--color-slate) 85%,
            var(--color-black) 15%
        ) !important;
        --md-sys-color-surface: var(--color-ivory) !important;
        --md-sys-color-on-surface: color-mix(
            in srgb,
            var(--color-slate) 85%,
            var(--color-black) 15%
        ) !important;
        --md-sys-color-surface-dim: color-mix(
            in srgb,
            var(--color-slate) 12%,
            var(--color-ivory) 88%
        ) !important;
        --md-sys-color-surface-bright: var(--color-ivory) !important;
        --md-sys-color-surface-variant: color-mix(
            in srgb,
            var(--color-slate) 12%,
            var(--color-ivory) 88%
        ) !important;
        --md-sys-color-on-surface-variant: color-mix(
            in srgb,
            var(--color-slate) 65%,
            var(--color-black) 10%
        ) !important;
        --md-sys-color-surface-container-lowest: var(--color-white) !important;
        --md-sys-color-surface-container-low: color-mix(
            in srgb,
            var(--color-slate) 4%,
            var(--color-ivory) 96%
        ) !important;
        --md-sys-color-surface-container: var(--color-ivory) !important;
        --md-sys-color-surface-container-high: color-mix(
            in srgb,
            var(--color-slate) 9%,
            var(--color-ivory) 91%
        ) !important;
        --md-sys-color-surface-container-highest: color-mix(
            in srgb,
            var(--color-slate) 15%,
            var(--color-ivory) 85%
        ) !important;
        --md-sys-color-outline: color-mix(
            in srgb,
            var(--color-slate) 55%,
            var(--color-ivory) 45%
        ) !important;
        --md-sys-color-outline-variant: color-mix(
            in srgb,
            var(--color-slate) 28%,
            var(--color-ivory) 72%
        ) !important;
        --md-sys-color-tertiary: var(--color-slate) !important;
        --md-sys-color-on-tertiary: var(--color-cream) !important;
        /* Was its own pale slate/ivory mix - .app-titlebar (site.css)
           and this panel share their fill (tertiary-container) with
           dark scheme too (see the comment on m3e-theme[scheme="dark"]
           below), so both schemes now paint that strip in the exact
           same --color-amethyst rather than two different colors that
           only happened to play the same ROLE. on-tertiary-container
           follows suit - a mid-tone purple needs light text either way,
           so light scheme now reads with the same off-white the dark
           scheme's own text already uses here, not the dark ink that
           made sense against the old, much paler fill. */
        --md-sys-color-tertiary-container: var(--color-amethyst) !important;
        --md-sys-color-on-tertiary-container: color-mix(
            in srgb,
            var(--color-cream) 12%,
            var(--color-white) 88%
        ) !important;
        --color-block3-end: color-mix(
            in srgb,
            color-mix(
                    in srgb,
                    color-mix(in srgb, var(--color-slate) 45%, var(--color-ivory) 55%)
                        73%,
                    var(--color-gold-dark) 27%
                )
                58%,
            var(--color-white) 42%
        );
        --color-block3-glow: var(--md-sys-color-primary-container);
    }
}

m3e-theme[scheme="light"] {
    --md-sys-color-background: var(--color-ivory) !important;
    --md-sys-color-on-background: color-mix(
        in srgb,
        var(--color-slate) 85%,
        var(--color-black) 15%
    ) !important;
    --md-sys-color-surface: var(--color-ivory) !important;
    --md-sys-color-on-surface: color-mix(
        in srgb,
        var(--color-slate) 85%,
        var(--color-black) 15%
    ) !important;
    --md-sys-color-surface-dim: color-mix(
        in srgb,
        var(--color-slate) 12%,
        var(--color-ivory) 88%
    ) !important;
    --md-sys-color-surface-bright: var(--color-ivory) !important;
    --md-sys-color-surface-variant: color-mix(
        in srgb,
        var(--color-slate) 12%,
        var(--color-ivory) 88%
    ) !important;
    --md-sys-color-on-surface-variant: color-mix(
        in srgb,
        var(--color-slate) 65%,
        var(--color-black) 10%
    ) !important;
    --md-sys-color-surface-container-lowest: var(--color-white) !important;
    --md-sys-color-surface-container-low: color-mix(
        in srgb,
        var(--color-slate) 4%,
        var(--color-ivory) 96%
    ) !important;
    --md-sys-color-surface-container: var(--color-ivory) !important;
    --md-sys-color-surface-container-high: color-mix(
        in srgb,
        var(--color-slate) 9%,
        var(--color-ivory) 91%
    ) !important;
    --md-sys-color-surface-container-highest: color-mix(
        in srgb,
        var(--color-slate) 15%,
        var(--color-ivory) 85%
    ) !important;
    --md-sys-color-outline: color-mix(
        in srgb,
        var(--color-slate) 55%,
        var(--color-ivory) 45%
    ) !important;
    --md-sys-color-outline-variant: color-mix(
        in srgb,
        var(--color-slate) 28%,
        var(--color-ivory) 72%
    ) !important;
    --md-sys-color-tertiary: var(--color-slate) !important;
    --md-sys-color-on-tertiary: var(--color-cream) !important;
    --md-sys-color-tertiary-container: var(--color-amethyst) !important;
    --md-sys-color-on-tertiary-container: color-mix(
        in srgb,
        var(--color-cream) 12%,
        var(--color-white) 88%
    ) !important;
    --color-block3-end: color-mix(
        in srgb,
        color-mix(
                in srgb,
                color-mix(in srgb, var(--color-slate) 45%, var(--color-ivory) 55%)
                    73%,
                var(--color-gold-dark) 27%
            )
            58%,
        var(--color-white) 42%
    );
    --color-block3-glow: var(--md-sys-color-primary-container);
}

a {
    color: var(--md-sys-color-primary);
}

/* m3e-theme wraps the entire page (see _layouts/default.html once step 2
   wires Jekyll back in). It already paints background/text color once
   the custom element upgrades; this just avoids a flash of an unstyled,
   zero-height page before that happens. */
m3e-theme {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background-color: var(--md-sys-color-background);
    color: var(--md-sys-color-on-background);
}

/* ==========================================================================
   Nav bar: transparent over the header banner
   ==========================================================================
   "Transparent" means the bar shows the header's own banner image through
   it instead of painting its usual solid surface color - both at rest and
   once scrolling would otherwise switch it to --container-color-on-scroll
   (m3e-app-bar's built-in scroll-elevation behavior, see the `for`
   attribute in its docs). Buttons/icons inside default to on-surface(-
   variant) colors, made for a solid surface - re-pointed to white here so
   they stay legible over an arbitrary photo.
   ========================================================================== */

/* Shared "resting state" fallback for every button/icon-button variant
   used anywhere over the banner photo - the nav bar's text buttons and
   icon buttons (menu/toc/theme toggles) below, AND the header's own tag
   buttons (.app-header__tags, in .app-header__content - a sibling of
   .app-header__bar, not a descendant of it, hence setting this on their
   common ancestor instead of repeating it in both places). See
   ButtonVariantToken.ts and IconButtonVariantToken.ts - every variant-
   specific token falls back to one of these before falling back to the
   theme's own default (on-surface, made for a plain surface - wrong over
   an arbitrary photo). Hover/focus state-layer color is white too, so a
   "borderless" text-variant button (the tag buttons) still shows a
   visible, translucent-white wash on hover instead of nothing at all.
   Label/icon color is pinned white for every interaction state a text
   button has (idle, unselected, hover, focus, pressed) - each one is
   its own separate token with its own separate default (confirmed in
   m3e-web's own source), so leaving any single one unset would have let
   the nav-link text/icon flash to that state's own default color the
   moment that state became active, even though the state-layer
   backgrounds above (hover/focus) are still deliberately left free to
   change for interaction feedback - only the text/icon color itself is
   frozen. */
.app-header {
    --m3e-button-label-text-color: var(--color-white);
    --m3e-button-icon-color: var(--color-white);
    --m3e-button-unselected-label-text-color: var(--color-white);
    --m3e-button-unselected-icon-color: var(--color-white);
    --m3e-button-hover-label-text-color: var(--color-white);
    --m3e-button-hover-icon-color: var(--color-white);
    --m3e-button-focus-label-text-color: var(--color-white);
    --m3e-button-focus-icon-color: var(--color-white);
    --m3e-button-pressed-label-text-color: var(--color-white);
    --m3e-button-pressed-icon-color: var(--color-white);
    --m3e-button-hover-state-layer-color: var(--color-white);
    --m3e-button-focus-state-layer-color: var(--color-white);
    --m3e-icon-button-icon-color: var(--color-white);
    --m3e-icon-button-unselected-icon-color: var(--color-white);
}

/* [Mobile] The three icon-buttons unique to the mobile bar (table of
   contents, search, hamburger menu) plus .theme-toggle (shown at every
   width, not just mobile, but needing the exact same fix). The rule
   above only ever covers these at REST: hover/focus/pressed each read
   from their OWN separate icon-color token (confirmed in
   m3e-icon-button's source), which falls back to the library's own
   default - tuned for a plain surface, not this photo backdrop - the
   moment any of those states become active. On mobile that "moment" is
   every single tap (a touch interaction passes through hover AND
   pressed before the click even registers), so the icon visibly flashed
   to a different, wrong color on every tap without this. --selected here
   also covers the menu button (id="nav-toggle") staying white once
   opened, and the theme-toggle icon staying white regardless of which of
   its two icons (dark_mode/light_mode, swapped by assets/js/app.js) is showing. */
.app-header__toc-toggle,
.app-header__search-toggle,
.app-header__menu-toggle,
.theme-toggle {
    --m3e-icon-button-hover-icon-color: var(--color-white);
    --m3e-icon-button-hover-selected-icon-color: var(--color-white);
    --m3e-icon-button-hover-unselected-icon-color: var(--color-white);
    --m3e-icon-button-focus-icon-color: var(--color-white);
    --m3e-icon-button-focus-selected-icon-color: var(--color-white);
    --m3e-icon-button-focus-unselected-icon-color: var(--color-white);
    --m3e-icon-button-pressed-icon-color: var(--color-white);
    --m3e-icon-button-pressed-selected-icon-color: var(--color-white);
    --m3e-icon-button-pressed-unselected-icon-color: var(--color-white);
    --m3e-icon-button-selected-icon-color: var(--color-white);
}

.app-header__bar {
    --m3e-app-bar-container-color: transparent;
    --m3e-app-bar-container-color-on-scroll: transparent;
    --m3e-app-bar-container-elevation: none;
    --m3e-app-bar-container-elevation-on-scroll: none;
    --m3e-app-bar-title-text-color: var(--color-white);
    --m3e-app-bar-subtitle-text-color: var(--color-white);
}

/* Search bar: transparent background everywhere, rather than the filled
   pill it draws by default - it then blends into whatever surface it's
   placed on (the header banner on desktop, the mobile search popup's own
   surface color below) instead of floating on top of it as a separate
   box. */
m3e-search-bar {
    --m3e-search-bar-container-color: transparent;
}

/* Sitting directly on the header's banner photo, the input/placeholder/
   icon colors (tuned for a plain surface) need to flip to white for the
   same legibility reason as the surrounding bar's own buttons/icons
   above. With a fully transparent fill, the field would otherwise have
   no visible boundary at all over a busy photo - m3e-search-bar has no
   built-in outlined variant (confirmed in its source: it only exposes a
   container *color*, not a border/outline token), so the outline here is
   a plain CSS border added from outside, in the same white the rest of
   the bar's content already uses, sized to match the field's own fully-
   rounded pill shape. */
.app-header__bar-search m3e-search-bar {
    --m3e-search-bar-input-color: var(--color-white);
    --m3e-search-bar-supporting-text-color: color-mix(
        in srgb,
        var(--color-white) 80%,
        transparent
    );
    --m3e-search-bar-leading-icon-color: var(--color-white);
    --m3e-search-bar-trailing-icon-color: var(--color-white);
    border: 0.0625rem solid
        color-mix(in srgb, var(--color-white) 70%, transparent);
    border-radius: var(--md-sys-shape-corner-full, 999px);
}

/* Once the page has scrolled, the banner image is no longer right behind
   the bar - a solid fill reads much better there than a flat transparent
   strip over arbitrary scrolled-past content. m3e-app-bar does track its
   own scroll state internally (for the --m3e-app-bar-container-color-on-
   scroll swap above), but that state stays private to its shadow DOM -
   there's no CSS part or reflected attribute for it. assets/js/app.js keeps
   that state anyway (see comment there), applied here as a plain host-
   element class.
   Text/icons are fixed white here too, same as .app-header/.app-header
   __bar's own resting-state defaults above. No color custom properties
   need redeclaring here any more: .app-header's white fallback already
   applies underneath this class regardless, so there's nothing to
   override.
   tertiary-container, not a translucent dark wash - the same flat color
   .app-titlebar (site.css) fills its own strip with, so the bar reads as
   one consistent surface with the titlebar the moment it appears rather
   than a blurred, semi-transparent view of whatever content happens to
   be scrolled past underneath it. No blur/backdrop-filter here any more
   for the same reason: a fully opaque fill has nothing to blur - there's
   no longer any scrolled-past content showing through to soften. */
.app-header__bar--scrolled {
    background-color: var(--md-sys-color-tertiary-container);
}

/* ==========================================================================
   Sidebar panel
   ==========================================================================
   The only surface on the page with genuinely square corners (everything
   else - cards, chips, buttons - keeps M3's default rounding). Reads as a
   flush, full-height rail rather than a floating card; see
   .app-body__sidebar in site.css for its (square, edge-to-edge) geometry.
   ========================================================================== */

/* THREE independent pieces this time, split across the element and two
   pseudos specifically so each can solve its own problem without
   fighting the others:
   1) THIS element - a flat fill plus grain, nothing else. Since it's a
      plain background-color (not a gradient with a 0%-stop that merely
      HAPPENS to equal the target color), the top edge is unconditionally
      --md-sys-color-tertiary-container, pixel-identical to .app-titlebar,
      regardless of whatever the pieces above it are doing - the
      simplest possible way to guarantee that invariant. Grain: the same
      inline-SVG turbulence tile used elsewhere on this surface, tiled
      small and blended at low opacity via "overlay" - no network
      request, and what keeps the wash below from reading as flat,
      plasticky color.
   2) ::before - the calm wash that actually solves "still looks good on
      a long post": FOUR color stops so a several-screens-tall column
      keeps crossing distinct hues start to finish instead of resolving
      into one flat color for most of the scroll. Angled at 200deg, not
      180deg/"to bottom" - a deliberately NOT-perfectly-horizontal fade,
      its iso-color lines run diagonally instead of stacking as flat
      horizontal bands. A mask fades it in only a few rem down, so this
      pseudo contributes nothing whatsoever near the top edge, whatever
      angle it's drawn at - simpler and more robust than trying to prove
      a tilted gradient's 0%-stop stays flat across the entire top edge
      width by construction (it doesn't, once you tilt it - the two top
      corners sit at different points along a diagonal gradient line).
   3) ::after - a hand-drawn S-curve ribbon (see git history for the
      several shapes tried here first: a straight-line zigzag, a single
      circular arc, and - at various points - img/sign.svg standing in
      for it entirely or sharing this box alongside it, before landing
      back on a plain drawn curve alone, always shown across the panel's
      full height).
      A clip-path polygon was the very first attempt at this shape - a
      polygon is a FIXED, finite list of points - stretch it (percentage
      Y) and short panels squash the angle; give it fixed-rem Y instead
      and it holds its angle but now simply runs out of points on a tall
      desktop column, ending well short of the real bottom edge either
      way. Neither version can cover "however tall this box turns out to
      be" on its own. A repeating MASK is what actually does that: the
      arc is tiled with mask-repeat: repeat-y at mask-size: 100% 16rem -
      CSS's own tiling machinery repeats that one bend for exactly as
      many 16rem increments as the box turns out to be tall, however
      tall that is, the same way background-repeat already tiles the
      grain tile elsewhere on this surface - no finite point list to run
      out of.
      Its own background-image is a second, independent diagonal
      gradient (165deg) spanning that whole box top-to-bottom - the mask
      decides WHERE the ribbon is, this gradient decides what color
      shows through it at each point, so the ribbon's color genuinely
      shifts as it descends. Both stops are color-mix()ed toward
      --md-sys-color-tertiary-container rather than left fully saturated
      - a fully saturated --color-cream mid-stop, painted solid, could
      land directly behind the panel's own description text
      (.profile-panel__description, on-tertiary-container - white in
      dark scheme) with genuinely poor contrast wherever the ribbon
      happened to cross it. Muting the color and letting it modulate the
      surface instead of replacing it keeps the ribbon visible as a
      shifting accent without ever producing a patch saturated enough to
      fight foreground text.
      (The ::before wash still fades in from 3rem down on its own -
      unrelated to this pseudo - so the flat tertiary-container still
      reads first at the very top corners; only the ribbon's own thin
      stroke touches y0, and softened as above, that's no longer a
      visible mismatch against .app-titlebar the way a fully saturated
      color would be.)
   None of --color-block3-glow/--color-cream/--color-block3-end ever
   overlaps --md-sys-color-secondary/-secondary-container, what
   m3e-icon-button's tonal variant uses (confirmed in its source) for the
   social buttons in .profile-panel__links on this same panel - those
   buttons stay a distinct color against whatever sits behind them.
   Both pseudos: z-index: 0, behind .profile-panel's own z-index: 1
   (site.css) - the real avatar/name/buttons always render in front.
   position: relative on the element itself (no overflow: hidden ON IT)
   for the usual reason: it's also .profile-panel's own positioning
   ancestor, and overflow != visible HERE would hijack its desktop
   sticky behavior, a regression that happened once before. */
.app-body__sidebar,
.app-body__mobile-profile {
    position: relative;
    background-color: var(--md-sys-color-tertiary-container);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
    background-repeat: repeat;
    background-size: 100px 100px;
    background-blend-mode: overlay;
    color: var(--md-sys-color-on-tertiary-container);
}

/* Experimental: a big soft radial glow layered on top of the wash, on
   request, to see how it reads - fixed rem radius (not a percentage of
   the box) anchored a fixed distance down, same reasoning as the halo
   tried earlier in this rule's history: a percentage/farthest-corner
   radius balloons into a huge, nearly-flat wash of its own on a very
   tall long-post column, which is exactly the "flat color" problem this
   whole panel exists to avoid. --color-block3-glow (already the wash's
   own accent token, scheme-reactive) keeps it part of the same palette
   rather than adding a new one-off color; soft-light so it modulates the
   wash under it instead of sitting on top as a flat disc.
   A third, topmost layer levels out the BOTTOM of the wash: the 200deg
   tilt that makes the wash read as diagonal rather than flat horizontal
   bands (deliberate, see the wash's own comment above) means the panel's
   two bottom corners reach the 100%-stop color at slightly different
   points along the gradient's own axis - a visible diagonal seam right
   at the bottom edge on a wide panel. A plain "to bottom" gradient has
   no such tilt by construction: transparent for the first 65%, so it
   still contributes nothing near the top and the diagonal wash reads as
   intended there, then a long, dilated fade into a flat solid
   --color-block3-end by 100% - a color with itself has no way to look
   diagonal - gradually overtaking the diagonal wash beneath it rather
   than snapping to solid abruptly right at the edge. */
.app-body__sidebar::before,
.app-body__mobile-profile::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image:
        linear-gradient(
            to bottom,
            transparent 0%,
            transparent 65%,
            var(--color-block3-end) 100%
        ),
        radial-gradient(
            circle 18rem at 50% 8rem,
            color-mix(in srgb, var(--color-block3-glow) 70%, transparent) 0%,
            transparent 70%
        ),
        linear-gradient(
            200deg,
            var(--md-sys-color-tertiary-container) 0%,
            color-mix(
                    in srgb,
                    var(--color-block3-glow) 55%,
                    var(--md-sys-color-tertiary-container)
                )
                50%,
            var(--color-block3-end) 100%
        );
    background-blend-mode: normal, soft-light, normal;
    mask-image: linear-gradient(
        to bottom,
        transparent 0,
        transparent 3rem,
        black 7rem
    );
    -webkit-mask-image: linear-gradient(
        to bottom,
        transparent 0,
        transparent 3rem,
        black 7rem
    );
}

/* Light-scheme-only recolor of the wash above - same angle, same stop
   positions, same color-mix() shape, ONLY the source tokens differ.
   Nudged one step darker from the first, paler pass at this: this
   panel's text (.profile-panel__name/__description, site.css) reads
   --md-sys-color-on-tertiary-container, which is now the same near-
   white both schemes use for .app-titlebar's own text (see
   m3e-theme[scheme="light"] above) - fine against the 0%-stop's
   --color-amethyst (a real mid-tone), but the too-pale accent stops
   tried first left near-white text sitting on near-white background
   for most of the panel's height. Still deliberately softer than the
   fully saturated --color-iris/--color-slate first attempt (this is a
   light touch, not a reversal) - just enough darker to read.
   Down to 3 stops, not 4 - the mid-point is --md-sys-color-primary (the
   site's own blue, same token `a { color }` uses site-wide) mixed with
   --color-ivory, the sole accent between start and end now that the
   separate --color-iris stop tried right before this is gone. No radial
   glow here (there was one, matching the shared/dark rule above) - removed
   on request: it read as a light patch near the top of the panel in this
   scheme, not the subtle depth cue it is against the dark scheme's own
   darker backdrop. Dark scheme is untouched - only the light-scheme
   selectors below exist. Same bottom-leveling layer as the shared/dark
   rule above (see its own comment) - added again here since this whole
   background-image list is a full override, not a merge. */
@media (prefers-color-scheme: light) {
    m3e-theme:not([scheme="dark"]) .app-body__sidebar::before,
    m3e-theme:not([scheme="dark"]) .app-body__mobile-profile::before {
        background-image:
            linear-gradient(
                to bottom,
                transparent 0%,
                transparent 65%,
                var(--color-block3-end) 100%
            ),
            linear-gradient(
                200deg,
                var(--md-sys-color-tertiary-container) 0%,
                color-mix(
                        in srgb,
                        var(--md-sys-color-primary) 60%,
                        var(--color-ivory) 40%
                    )
                    50%,
                var(--color-block3-end) 100%
            );
    }
}

m3e-theme[scheme="light"] .app-body__sidebar::before,
m3e-theme[scheme="light"] .app-body__mobile-profile::before {
    background-image:
        linear-gradient(
            to bottom,
            transparent 0%,
            transparent 65%,
            var(--color-block3-end) 100%
        ),
        linear-gradient(
            200deg,
            var(--md-sys-color-tertiary-container) 0%,
            color-mix(
                    in srgb,
                    var(--md-sys-color-primary) 60%,
                    var(--color-ivory) 40%
                )
                50%,
            var(--color-block3-end) 100%
        );
}

/* The S-curve ribbon. The path itself went through two shapes at explicit request. First a
   single C-bulge (M18, then M36 once centering the endpoints alone
   turned out not to be enough - see git history): one arc from (x,0) to
   (x,200) always bulges to the same side, so centering had to target
   the bulge's own bounding box, not just its two endpoints. The current
   S-curve sidesteps that entirely: two stacked half-height arcs sharing
   the SAME x (50, the viewBox's true horizontal center - 100 wide,
   stretched to the element's own width by preserveAspectRatio='none')
   at y=0/100/200, with opposite sweep-flags (1 then 0) so the second
   half bends back the other way instead of continuing the first's
   curve. Symmetric by construction - bulges +14.2 then -14.2 off x=50
   (R95 over each 100-tall half-chord) - so it's centered without
   needing an off-center anchor point the way the single arc did.
   stroke-width 5 (was 8) is the "slightly thinner" ask - still visible
   against the gradient beneath it, just lighter-handed. filter:
   blur(0.5px) is the "softer" ask - mask-image's edges are otherwise
   perfectly crisp (no native SVG stroke-antialiasing softness survives
   rasterization to a mask), so a small blur feathers the line's edges
   after the fact instead. */
.app-body__sidebar::after,
.app-body__mobile-profile::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 200' preserveAspectRatio='none'%3E%3Cpath d='M50,0 A95,95 0 0 1 50,100 A95,95 0 0 0 50,200' fill='none' stroke='white' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E");
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 200' preserveAspectRatio='none'%3E%3Cpath d='M50,0 A95,95 0 0 1 50,100 A95,95 0 0 0 50,200' fill='none' stroke='white' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E");
    mask-repeat: repeat-y;
    -webkit-mask-repeat: repeat-y;
    mask-size: 100% 16rem;
    -webkit-mask-size: 100% 16rem;
    filter: blur(0.5px);
    background-image: linear-gradient(
        165deg,
        color-mix(
                in srgb,
                var(--color-block3-glow) 70%,
                var(--md-sys-color-tertiary-container)
            )
            0%,
        color-mix(
                in srgb,
                var(--color-cream) 55%,
                var(--md-sys-color-tertiary-container)
            )
            50%,
        color-mix(
                in srgb,
                var(--color-block3-glow) 70%,
                var(--md-sys-color-tertiary-container)
            )
            100%
    );
    mix-blend-mode: soft-light;
}

/* ==========================================================================
   Main content
   ==========================================================================
   A single soft radial glow, anchored at the top of the main column -
   deliberately simple (one gradient, one color, no mask, no texture, no
   blend mode) compared to the sidebar's own multi-layer wash: this sits
   behind real reading content (post cards, an article's prose pane),
   which already provide their own visual interest, so it only ever
   needs to break up the flat background showing through the gaps/
   padding AROUND that content, not carry the whole surface on its own
   the way the sidebar's background does. --md-sys-color-primary at low
   alpha (12%, so it reads as a soft ambient tint rather than a visible
   colored patch) - the same accent color `a { color }` already uses
   site-wide, not a new one-off pick. background-repeat: no-repeat is
   explicit (gradients don't visibly tile as long as their own fade
   completes within one tile, but this makes that intent unambiguous
   rather than relying on that coincidence). */
.app-body__main {
    background-image: radial-gradient(
        circle at top center,
        color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent) 0%,
        transparent 60%
    );
    background-repeat: no-repeat;
}

/* ==========================================================================
   Footer
   ==========================================================================
   Plain flat color, no texture image, no overlay. --color-block3-end -
   the same token the sidebar's own wash (::before, above) fades INTO at
   its 100% stop - so the footer reads as the color the sidebar's
   gradient would eventually settle on if it kept going, rather than an
   unrelated pick that merely happens to look fine. Scheme-reactive for
   free since it's the same variable, already declared once per scheme
   in the custom color anchors above (primary-container in dark, a
   slate/ivory color-mix() - a somewhat dark gray - in light) - nothing
   new to add here. */

.app-footer {
    background-color: var(--color-block3-end);
}

/* ==========================================================================
   Sign marks
   ==========================================================================
   Two small marks share this one rule - .footer-sign (before the back-
   to-top mascot, footer.html) and .app-header__bar-sign (the mobile
   bar's own title slot, below 52.5em, navbar.html) - identical mask
   mechanics in both spots (see each one's own site.css rule for its
   size/alignment, which does differ - this rule is only ever about
   color/shape). img/sign.svg, masked (mask-mode: alpha, not the default
   luminance - the file's own dark, saturated fill color would otherwise
   mute the mask into something dimmer than a crisp, fully opaque mark).
   currentColor, not a role token, on both - .app-footer's own text and
   .app-header's own text/icons are each a fixed literal white
   (deliberately not theme-reactive, site.css/theme.css), so this mark
   just inherits whichever one it's sitting inside rather than needing
   its own copy of the same literal value repeated a second/third time. */
.footer-sign,
.app-header__bar-sign {
    mask-image: url("../img/sign.svg");
    -webkit-mask-image: url("../img/sign.svg");
    mask-mode: alpha;
    -webkit-mask-mode: alpha;
    mask-repeat: no-repeat;
    -webkit-mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-position: center;
    mask-size: contain;
    -webkit-mask-size: contain;
    background-color: currentColor;
}

/* .footer-sign's own currentColor (above) already resolves correctly -
   .app-footer sets a plain, inherited color (site.css), which reaches
   every descendant through normal CSS cascade. .app-header__bar-sign
   sits inside m3e-app-bar's title SLOT instead: --m3e-app-bar-title-
   text-color (the custom property .app-header__bar sets, above) is only
   ever read by the component's OWN shadow-DOM styling of its default
   slot content, not something a plain, unrelated light-DOM element
   dropped into that same slot can rely on inheriting - explicit here
   rather than assuming the component's internal ::slotted() rules
   happen to reach this element too. */
.app-header__bar-sign {
    color: var(--color-white);
}
