/* ================================================================
   Fonts (bundled — no CDN)
   ================================================================ */
@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 600 700;
    font-display: swap;
    src: url('fonts/fraunces-latin.woff2') format('woff2');
}

@font-face {
    font-family: 'Public Sans';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('fonts/public-sans-latin.woff2') format('woff2');
}

@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('fonts/jetbrains-mono-latin.woff2') format('woff2');
}

/* ================================================================
   Tokens — dark is the default theme
   ================================================================ */
:root {
    /* Brand palette — fixed in both themes, for graphics (ribbons, strips) */
    --c-red: #a63d40;
    --c-gold: #e9b872;
    --c-green: #90a959;
    --c-blue: #6494aa;

    /* Surfaces & text */
    --bg: #151515;
    --surface: #1d1c1a;
    --surface-2: #262421;
    --border: #35322d;
    --text: #e8e4dd;
    --text-muted: #a49d91;

    /* Text-safe accent roles (contrast-checked per theme) */
    --accent: var(--c-gold);       /* primary interactive */
    --accent-ink: #151515;         /* text on accent */
    --info: #8fb6c9;
    --positive: #a9c17a;
    --danger: #d98c8e;             /* raw red fails contrast on dark */

    --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
    --font-body: 'Public Sans', 'Segoe UI', system-ui, sans-serif;
    --font-mono: 'JetBrains Mono', Consolas, 'Cascadia Mono', monospace;

    --radius: 6px;

    /* Belt & rank colors — fixed, sport-defined constants, not theme tokens
       (docs/adr/0002-belt-colors-are-fixed-constants.md). Identical in both
       themes: a black belt must render as black regardless of the visitor's
       light/dark preference or the owner's brand-color choices. */
    --belt-black: #0c0c0c;
    --belt-white: #e8e4dd;
    --rank-white: #e6dfd0;
    --rank-blue: #2b4c8c;
    --rank-purple: #5a3d8a;
    --rank-brown: #6b4423;
    --rank-black: #0c0c0c;

    /* Layout constant for the pinned site header: its height plus a small
       gap, in the header's own unit mix (2 x 0.9rem inner padding + the
       38px burger + the 1px border, plus a 0.5rem gap) so it tracks the real
       height at any root font size. Not a theme token (ThemeRules.Tokens is
       untouched): html uses it as scroll-padding-top so anchor jumps and
       keyboard focus land below the bar, and the admin editors' sticky
       preview panel uses it to clear the bar. */
    --header-h: calc(2.3rem + 39px);

    color-scheme: dark;
}

:root[data-theme='light'] {
    --bg: #f6f3ec;
    --surface: #fdfbf6;
    --surface-2: #ece7db;
    --border: #d8d1c2;
    --text: #24211c;
    --text-muted: #6b6459;

    --accent: #8a6520;
    --accent-ink: #fdfbf6;
    --info: #3f6e86;
    --positive: #5c7a35;
    --danger: #8f3538;
    color-scheme: light;
}

/* ================================================================
   Base
   ================================================================ */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
    scroll-padding-top: var(--header-h);
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.01em;
}

a {
    color: var(--accent);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

a:hover {
    text-decoration-thickness: 2px;
}

:focus-visible {
    outline: 2px solid var(--c-blue);
    outline-offset: 2px;
    border-radius: 2px;
}

/* FocusOnNavigate moves programmatic focus to the page heading for screen
   readers; scoped to tabindex="-1" so deliberately keyboard-focusable
   headings keep their focus ring. */
h1[tabindex='-1']:focus {
    outline: none;
}

::selection {
    background: var(--c-gold);
    color: #151515;
}

img {
    max-width: 100%;
}

code,
pre {
    font-family: var(--font-mono);
}

.container {
    width: min(1080px, 92vw);
    margin-inline: auto;
}

main {
    min-height: 65vh;
}

/* Screen-reader-only text (fieldset legends, etc.) — the standard clip
   pattern, never `display: none`, which VoiceOver/NVDA also skip. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ================================================================
   Header / nav
   ================================================================ */
.site-header {
    position: sticky;
    top: 0;
    /* Above page content and .site-nav's own z-index: 50 (which lives inside
       this stacking context); below #blazor-error-ui's 1000. */
    z-index: 100;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
}

.site-header .inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-block: 0.9rem;
}

.brand {
    display: inline-flex;
    align-items: center;
    color: var(--text);
    text-decoration: none;
}

.brand-logo {
    height: 28px;
    width: auto;
}

.nav-burger {
    display: none;
    place-items: center;
    width: 38px;
    height: 38px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    cursor: pointer;
    padding: 0;
}

.nav-burger:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.site-nav {
    display: flex;
    align-items: center;
    gap: 1.4rem;
}

.site-nav a {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-decoration: none;
    padding-block: 0.35rem;
    border-bottom: 2px solid transparent;
}

.site-nav a:hover,
.site-nav a.active {
    color: var(--text);
    border-bottom-color: var(--c-gold);
}

.theme-toggle {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0;
}

.theme-toggle:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.theme-toggle .icon-moon { display: none; }
:root[data-theme='light'] .theme-toggle .icon-moon { display: block; }
:root[data-theme='light'] .theme-toggle .icon-sun { display: none; }

/* ================================================================
   Hero
   ================================================================ */
.hero {
    position: relative;
    padding: 6.5rem 0 5rem;
}

.ribbons {
    position: absolute;
    top: 0;
    right: 6%;
    display: flex;
    gap: 12px;
    /* Above the owner photo so the stripes pin its top edge. */
    z-index: 2;
}

.ribbons i {
    width: 10px;
    border-radius: 0 0 3px 3px;
    transform-origin: top;
    animation: ribbon-drop 0.7s cubic-bezier(0.2, 0.7, 0.3, 1) backwards;
}

.ribbons i:nth-child(1) { background: var(--c-red);   height: 110px; animation-delay: 0.05s; }
.ribbons i:nth-child(2) { background: var(--c-gold);  height: 170px; animation-delay: 0.15s; }
.ribbons i:nth-child(3) { background: var(--c-green); height: 85px;  animation-delay: 0.25s; }
.ribbons i:nth-child(4) { background: var(--c-blue);  height: 140px; animation-delay: 0.35s; }

@keyframes ribbon-drop {
    from { transform: scaleY(0); }
}

/* !important is deliberate on every declaration below: this accessibility
   override must beat any later or more specific animation/transition rule
   in the file (a later selector wins on source order alone, and the
   era-indexed .row.era-N rules outrank these on specificity too), so the
   per-selector listing stays honest as the file grows instead of silently
   losing the cascade. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto !important; }
    .ribbons i, .belt-bar i { animation: none !important; }
    .gp-node a, .gp-node::after, .gp-node::before { transition: none !important; }
    .belt-band, .road-table .swatch, .row { transition: none !important; }
    .row .belt-band, .row .swatch, .road-table tr.row { animation: none !important; }
    .photo-tile { transition: none !important; }
}

.hero h1 {
    margin: 0.4rem 0 1rem;
    font-size: clamp(2.75rem, 7vw, 4.75rem);
    letter-spacing: -0.015em;
}

.hero .tagline {
    max-width: 36rem;
    margin: 0;
    font-size: clamp(1.05rem, 2vw, 1.3rem);
    color: var(--text-muted);
}

.hero .actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    margin-top: 2.25rem;
}

/* Owner photo: the hero only becomes a grid when a photo resolves, so the
   photo-less page renders exactly as before. The photo track must be a
   definite size — an auto track sizes from the image's natural width
   (percentages are indefinite there) and crushes the text column to its
   min-content. */
.hero .container.has-photo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 2.5rem;
    align-items: start;
}

.owner-photo {
    width: 100%;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    border-radius: var(--radius);
    /* Sits under the ribbon stripes; the offset lets them overlap its top edge. */
    position: relative;
    z-index: 1;
    margin-top: 3rem;
}

/* ================================================================
   Buttons
   ================================================================ */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 1.15rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: 0.85rem;
    text-decoration: none;
    cursor: pointer;
}

.btn-primary {
    background: var(--accent);
    color: var(--accent-ink);
    font-weight: 500;
}

.btn-primary:hover {
    filter: brightness(1.08);
}

.btn-ghost {
    border-color: var(--border);
    color: var(--text);
}

.btn-ghost:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Inline SVG glyphs (Icon.razor) — sized by the surrounding text. */
.icon {
    width: 1em;
    height: 1em;
    flex: none;
}

/* ================================================================
   Sections
   ================================================================ */
.section {
    padding: 3.5rem 0;
    border-top: 1px solid var(--border);
}

.eyebrow {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent);
}

.eyebrow::before {
    content: '';
    width: 22px;
    height: 3px;
    border-radius: 2px;
    background: linear-gradient(90deg,
        var(--c-red) 0 25%, var(--c-gold) 25% 50%,
        var(--c-green) 50% 75%, var(--c-blue) 75% 100%);
}

.section h2 {
    margin: 0.8rem 0 1.2rem;
    font-size: 1.9rem;
}

.about-grid {
    display: grid;
    grid-template-columns: 1.6fr 1fr;
    gap: 3rem;
}

.about-text p {
    max-width: 62ch;
    margin: 0 0 1rem;
}

.skills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0;
    margin: 0;
    list-style: none;
    align-content: start;
}

.skills li {
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--text-muted);
}

.skills li::before {
    content: '●';
    margin-right: 0.45rem;
    font-size: 0.6rem;
    vertical-align: 1px;
}

.skills li:nth-child(4n + 1)::before { color: var(--c-gold); }
.skills li:nth-child(4n + 2)::before { color: var(--c-green); }
.skills li:nth-child(4n + 3)::before { color: var(--c-blue); }
.skills li:nth-child(4n + 4)::before { color: var(--c-red); }

@media (max-width: 720px) {
    .about-grid {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .hero {
        padding-top: 4.5rem;
    }

    .ribbons {
        right: 4%;
        gap: 8px;
    }

    .ribbons i {
        width: 7px;
    }

    /* Photo first and centered; capped so the heading stays near the fold. */
    .hero .container.has-photo {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .owner-photo {
        order: -1;
        width: min(60vw, 260px);
        justify-self: center;
        margin-top: 2rem;
    }

    /* Collapse the nav behind a hamburger; the panel drops below the header. */
    .nav-burger {
        display: grid;
    }

    .site-nav {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 50;
        flex-direction: column;
        align-items: flex-start;
        gap: 0.9rem;
        padding: 1rem 4vw 1.3rem;
        background: var(--surface);
        border-bottom: 1px solid var(--border);
        box-shadow: 0 12px 24px rgb(0 0 0 / 0.25);
    }

    .site-nav.open {
        display: flex;
    }

    .site-nav a,
    .signout {
        font-size: 0.9rem;
    }
}

/* ================================================================
   Landing (BJJ flavor)
   ================================================================ */
.hero .eyebrow {
    margin-bottom: 0.4rem;
}

.gp-red { --node: var(--c-red); }
.gp-gold { --node: var(--c-gold); }
.gp-green { --node: var(--c-green); }
.gp-blue { --node: var(--c-blue); }

.game-plan {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0;
    list-style: none;
    margin: 2.75rem 0 0;
    padding: 0;
}

.gp-node {
    position: relative;
    padding-right: 34px;
}

.gp-node:last-child {
    padding-right: 0;
}

.gp-node a {
    display: block;
    height: 100%;
    padding: 1rem 1.1rem 1.1rem;
    border: 1px solid var(--border);
    border-top: 3px solid var(--node);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.gp-node .term {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.gp-node .read {
    display: block;
    margin-top: 0.3rem;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.15rem;
    line-height: 1.2;
}

.gp-node .how {
    display: block;
    margin-top: 0.4rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.gp-node::after {
    content: '';
    position: absolute;
    top: 50%;
    right: 8px;
    width: 20px;
    height: 2px;
    background: var(--border);
    transform: translateY(-50%);
    transition: background 0.2s ease;
}

.gp-node::before {
    content: '';
    position: absolute;
    top: 50%;
    right: 4px;
    border: 5px solid transparent;
    border-left: 7px solid var(--border);
    transform: translateY(-50%);
    transition: border-left-color 0.2s ease;
}

.gp-node:last-child::after,
.gp-node:last-child::before {
    display: none;
}

.gp-node a:hover,
.gp-node a:focus-visible {
    border-color: var(--node);
    transform: translateY(-3px);
}

.gp-node:has(a:hover)::after,
.gp-node:has(a:focus-visible)::after {
    background: var(--node);
}

.gp-node:has(a:hover)::before,
.gp-node:has(a:focus-visible)::before {
    border-left-color: var(--node);
}

.gp-node:has(a:hover) + .gp-node a,
.gp-node:has(a:focus-visible) + .gp-node a {
    transform: translateY(-3px);
    border-color: var(--node);
}

.hero-plan {
    grid-column: 1 / -1;
    margin-top: 1.5rem;
}

.rank-bar {
    margin: 0;
    padding: 0 0 3rem;
}

.rank-bar .belt {
    display: flex;
    height: 12px;
}

.belt-body {
    flex: 1;
    background: var(--belt-black);
    border: 1px solid var(--border);
    border-right: 0;
    border-radius: 3px 0 0 3px;
}

.belt-bar {
    display: flex;
    align-items: stretch;
    gap: 6px;
    width: 112px;
    padding: 0 10px;
}

.belt-bar i {
    width: 4px;
    background: var(--belt-white);
    transform-origin: left;
    animation: stripe-on 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) backwards;
}

.belt-bar i:nth-child(1) { animation-delay: 0.45s; }
.belt-bar i:nth-child(2) { animation-delay: 0.6s; }
.belt-bar i:nth-child(3) { animation-delay: 0.75s; }
.belt-bar i:nth-child(4) { animation-delay: 0.9s; }
.belt-bar i:nth-child(5) { animation-delay: 1.05s; }
.belt-bar i:nth-child(6) { animation-delay: 1.2s; }

.belt-tip {
    width: 44px;
    background: var(--belt-black);
    border: 1px solid var(--border);
    border-left: 0;
    border-radius: 0 3px 3px 0;
}

@keyframes stripe-on {
    from { transform: scaleX(0); }
}

.rank-bar figcaption {
    margin-top: 0.7rem;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.principles {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2.5rem;
    margin-top: 1.4rem;
}

.principle h3 {
    margin: 0 0 0.5rem;
    font-size: 1.35rem;
}

.principle p {
    margin: 0;
    max-width: 30ch;
    color: var(--text-muted);
}

/* Long Road: belt ladder (white to black, left to right) above a dated
   table of belts, gyms, locations and roles (BR-8) */
.road {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.8rem;
    margin-top: 1.4rem;
}

.ladder {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 12px;
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

.rung {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.ladder .name {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.belt-band {
    position: relative;
    height: 16px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--rank);
    overflow: hidden;
}

.belt-band.white { --rank: var(--rank-white); }
.belt-band.blue { --rank: var(--rank-blue); }
.belt-band.purple { --rank: var(--rank-purple); }
.belt-band.brown { --rank: var(--rank-brown); }
.belt-band.black { --rank: var(--rank-black); }

.belt-band .bar {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 22px;
    width: 64px;
    display: flex;
    gap: 5px;
    padding: 0 7px;
    background: var(--belt-black);
}

.belt-band.black .bar { background: var(--c-red); }

.belt-band .bar i {
    width: 3px;
    background: var(--belt-white);
}

/* The table: mono uppercase headers like the admin tables */
.road-table {
    width: 100%;
    border-collapse: collapse;
}

.road-table .rowbelt {
    display: none;
}

.road-table th {
    padding: 0 1rem 0.6rem 0;
    text-align: left;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border);
}

.road-table td {
    padding: 0.85rem 1rem 0.85rem 0;
    vertical-align: top;
    border-bottom: 1px solid var(--border);
    font-size: 0.95rem;
}

.road-table th:last-child,
.road-table td:last-child {
    padding-right: 0;
}

.road-table .year {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.road-table .belt {
    white-space: nowrap;
}

.road-table .swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-right: 0.5rem;
    border-radius: 2px;
    border: 1px solid var(--border);
    background: var(--rank);
    vertical-align: -1px;
}

.road-table .gym,
.road-table .place {
    white-space: nowrap;
}

.road-table .work {
    color: var(--text-muted);
}

.row[data-belt='white'] { --rank: var(--rank-white); }
.row[data-belt='blue'] { --rank: var(--rank-blue); }
.row[data-belt='purple'] { --rank: var(--rank-purple); }
.row[data-belt='brown'] { --rank: var(--rank-brown); }
.row[data-belt='black'] { --rank: var(--rank-black); }

/* Hover-linked glow: a belt lights its row, a row lights its belt
   (decoration only; every row is readable at rest) */
.belt-band,
.road-table .swatch,
.row {
    transition: box-shadow 0.15s ease, outline-color 0.15s ease, background-color 0.15s ease;
}

.belt-band.glow,
.belt-band:hover {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.row.glow,
.row:hover {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.row.glow .swatch,
.row:hover .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.row.glow .work,
.row:hover .work {
    color: var(--text);
}

.road:has(.belt-band.white:hover) .row[data-belt='white'] {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.road:has(.belt-band.white:hover) .row[data-belt='white'] .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.white:hover) .row[data-belt='white'] .work {
    color: var(--text);
}

.road:has(.row[data-belt='white']:hover) .belt-band.white {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.blue:hover) .row[data-belt='blue'] {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.road:has(.belt-band.blue:hover) .row[data-belt='blue'] .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.blue:hover) .row[data-belt='blue'] .work {
    color: var(--text);
}

.road:has(.row[data-belt='blue']:hover) .belt-band.blue {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.purple:hover) .row[data-belt='purple'] {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.road:has(.belt-band.purple:hover) .row[data-belt='purple'] .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.purple:hover) .row[data-belt='purple'] .work {
    color: var(--text);
}

.road:has(.row[data-belt='purple']:hover) .belt-band.purple {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.brown:hover) .row[data-belt='brown'] {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.road:has(.belt-band.brown:hover) .row[data-belt='brown'] .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.brown:hover) .row[data-belt='brown'] .work {
    color: var(--text);
}

.road:has(.row[data-belt='brown']:hover) .belt-band.brown {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.black:hover) .row[data-belt='black'] {
    background: var(--surface-2);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.road:has(.belt-band.black:hover) .row[data-belt='black'] .swatch {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 10px var(--accent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 55%, transparent);
}

.road:has(.belt-band.black:hover) .row[data-belt='black'] .work {
    color: var(--text);
}

.road:has(.row[data-belt='black']:hover) .belt-band.black {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 14px var(--accent);
    box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}

.row td:first-child {
    padding-left: 0.5rem;
}

.road-table th:first-child {
    padding-left: 0.5rem;
}

.now {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.5rem;
    margin: 1.4rem 0 0;
}

.now div {
    padding: 1rem 1.1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.now dt {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.now dd {
    margin: 0.35rem 0 0;
}

/* Shared BJJ device (also usable outside this flavor): a two-option
   fieldset styled as a pill switch (shared.css) */
.pill-switch {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

.pill-switch input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.pill-switch label {
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    cursor: pointer;
}

.pill-switch input:checked + label {
    border-color: var(--accent);
    color: var(--accent);
}

.pill-switch input:focus-visible + label {
    outline: 2px solid var(--c-blue);
    outline-offset: 2px;
}

/* Portrait switch: the hero's second photo slot (Unit 10 Phase 4). With one
   photo the hero renders today's single .owner-photo image instead; this
   stack only appears once both slots resolve. */
.photo-slot {
    position: relative;
    z-index: 1;
}

.photo-stack {
    position: relative;
    width: 100%;
    aspect-ratio: 4 / 5;
    margin-top: 3rem;
}

/* The desk tile's <img> deliberately carries no .owner-photo class: that rule's
   margin-top: 3rem would stack with .photo-stack's own inside this absolutely
   positioned, overflow-hidden tile and clip the image; the tile and .photo-tile img
   supply the radius, sizing and object-fit instead (see LandingSections.razor). */
.photo-tile {
    position: absolute;
    inset: 0;
    border-radius: var(--radius);
    overflow: hidden;
    transition: opacity 0.25s ease;
}

.photo-tile.mat {
    opacity: 0;
}

.hero:has(#ph-mat:checked) .photo-tile.mat {
    opacity: 1;
}

.hero:has(#ph-mat:checked) .photo-tile.desk {
    opacity: 0;
}

.photo-switch {
    margin-top: 0.8rem;
}

.photo-tile img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hero .container.has-photo .photo-slot {
    align-self: start;
}

@media (max-width: 720px) {
    .photo-slot {
        order: -1;
        justify-self: center;
        width: min(60vw, 260px);
    }

    .photo-stack {
        margin-top: 2rem;
        width: 100%;
    }

    .photo-switch {
        justify-content: center;
    }

    .game-plan {
        grid-template-columns: 1fr;
        gap: 26px;
    }

    .gp-node {
        padding-right: 0;
    }

    .gp-node::after {
        top: auto;
        bottom: -16px;
        left: 24px;
        right: auto;
        width: 2px;
        height: 12px;
        transform: none;
    }

    .gp-node::before {
        top: auto;
        bottom: -22px;
        left: 20px;
        right: auto;
        border: 5px solid transparent;
        border-top: 7px solid var(--border);
        transform: none;
    }

    .gp-node:has(a:hover)::before,
    .gp-node:has(a:focus-visible)::before {
        border-left-color: transparent;
        border-top-color: var(--node);
    }

    .hero-plan {
        margin-top: 0.5rem;
    }

    .rank-bar .belt {
        height: 9px;
    }

    .belt-bar {
        width: 84px;
        gap: 5px;
        padding: 0 8px;
    }

    .belt-bar i {
        width: 3px;
    }

    .belt-tip {
        width: 30px;
    }

    .principles {
        grid-template-columns: 1fr;
        gap: 1.6rem;
    }

    .ladder {
        gap: 8px;
    }

    .ladder .name {
        font-size: 0.62rem;
        letter-spacing: 0.08em;
    }

    .road-table thead {
        display: none;
    }

    .road-table,
    .road-table tbody {
        display: block;
    }

    .road-table tr {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.5rem 1rem;
        padding: 0.9rem 0;
        border-bottom: 1px solid var(--border);
    }

    .ladder {
        display: none;
    }

    .road-table .rowbelt {
        display: block;
        grid-column: 1 / -1;
        padding: 0 0 0.4rem;
    }

    .road-table .rowbelt::before {
        display: none;
    }

    .road-table .rowbelt .belt-band {
        display: block;
        height: 14px;
    }

    .road-table .rowbelt .belt-band,
    .road-table .swatch {
        outline: 2px solid transparent;
    }

    .road-table .rowbelt .belt-band {
        outline-offset: 3px;
    }

    /* Scroll-driven glow: the row passing through the middle of the screen
       lights up with its belt. Timeline names are index-based (era-1..era-8,
       refinement 5) instead of per-belt, so two eras sharing a belt never
       share a timeline; rows past the eighth stay static (no timeline). Eight
       was chosen, not MaxEras (12): named timelines are enumerated by hand
       here (one rule pair per index), a realistic ladder runs five or six
       eras, eight leaves headroom without writing twelve rule pairs, and
       rows past the eighth still keep the anonymous view() row glow (below)
       so only the per-row belt-band glow stops for them. */
    @supports (animation-timeline: view()) {
        .road-table {
            timeline-scope: --era-1, --era-2, --era-3, --era-4, --era-5, --era-6, --era-7, --era-8;
        }

        .row.era-1 {
            view-timeline-name: --era-1;
        }

        .row.era-1 .belt-band,
        .row.era-1 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-1;
            animation-range: cover 15% cover 85%;
        }

        .row.era-2 {
            view-timeline-name: --era-2;
        }

        .row.era-2 .belt-band,
        .row.era-2 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-2;
            animation-range: cover 15% cover 85%;
        }

        .row.era-3 {
            view-timeline-name: --era-3;
        }

        .row.era-3 .belt-band,
        .row.era-3 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-3;
            animation-range: cover 15% cover 85%;
        }

        .row.era-4 {
            view-timeline-name: --era-4;
        }

        .row.era-4 .belt-band,
        .row.era-4 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-4;
            animation-range: cover 15% cover 85%;
        }

        .row.era-5 {
            view-timeline-name: --era-5;
        }

        .row.era-5 .belt-band,
        .row.era-5 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-5;
            animation-range: cover 15% cover 85%;
        }

        .row.era-6 {
            view-timeline-name: --era-6;
        }

        .row.era-6 .belt-band,
        .row.era-6 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-6;
            animation-range: cover 15% cover 85%;
        }

        .row.era-7 {
            view-timeline-name: --era-7;
        }

        .row.era-7 .belt-band,
        .row.era-7 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-7;
            animation-range: cover 15% cover 85%;
        }

        .row.era-8 {
            view-timeline-name: --era-8;
        }

        .row.era-8 .belt-band,
        .row.era-8 .swatch {
            animation: band-glow linear both;
            animation-timeline: --era-8;
            animation-range: cover 15% cover 85%;
        }

        .road-table tr.row {
            animation: row-glow linear both;
            animation-timeline: view();
            animation-range: cover 15% cover 85%;
        }
    }

    .road-table td {
        display: block;
        padding: 0;
        border: 0;
    }

    .road-table td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 0.1rem;
        font-family: var(--font-mono);
        font-size: 0.62rem;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: var(--text-muted);
    }

    .road-table .gym,
    .road-table .place {
        white-space: normal;
    }

    .road-table .work {
        grid-column: 1 / -1;
    }

    .now {
        grid-template-columns: 1fr 1fr;
    }
}

@keyframes row-glow {
    0%, 100% { background-color: transparent; }
    30%, 70% { background-color: color-mix(in srgb, var(--accent) 9%, transparent); }
}
@keyframes band-glow {
    0%, 100% { outline-color: transparent; box-shadow: 0 0 0 transparent; }
    30%, 70% { outline-color: var(--accent); box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 55%, transparent); }
}

/* ================================================================
   Auth & admin
   ================================================================ */
.narrow {
    max-width: 560px;
}

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

.alert {
    padding: 0.7rem 1rem;
    border: 1px solid var(--danger);
    border-radius: var(--radius);
    color: var(--danger);
    font-size: 0.95rem;
}

.provider-list {
    display: grid;
    gap: 0.7rem;
    margin-top: 1.5rem;
}

.provider-btn {
    justify-content: center;
}

.logout-form {
    display: inline;
    margin: 0;
}

.signout {
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 0.35rem 0;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    cursor: pointer;
}

.signout:hover {
    color: var(--text);
    border-bottom-color: var(--c-gold);
}

.card {
    padding: 1.2rem 1.4rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.card h3 {
    margin: 0 0 0.4rem;
    font-size: 1.15rem;
}

.card p {
    margin: 0;
    font-size: 0.92rem;
}

.admin-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1rem;
    margin-top: 1.5rem;
}

.notfound .btn {
    margin-top: 1rem;
}

/* ================================================================
   Blog
   ================================================================ */
.page-head {
    padding-bottom: 1.5rem;
    border-top: none;
}

.page-head h1 {
    margin: 0.4rem 0 0;
    font-size: clamp(2rem, 4.5vw, 3rem);
}

.post-list {
    padding-bottom: 3rem;
}

.post-card {
    padding: 1.4rem 0;
    border-top: 1px solid var(--border);
}

.blog-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 1.2rem;
}

.blog-filters input[type='text'] {
    flex: 1;
    min-width: 200px;
}

.blog-filters select {
    width: auto;
}

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1rem;
}

.filter-chip {
    padding: 0.2rem 0.7rem;
    border: 1px solid var(--accent);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    text-decoration: none;
}

.filter-chip.clear-all {
    border-color: var(--border);
    color: var(--text-muted);
}

.pager {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 1.6rem;
}

.pager-link {
    display: inline-grid;
    place-items: center;
    min-width: 34px;
    height: 34px;
    padding: 0 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: 0.82rem;
    color: var(--text-muted);
    text-decoration: none;
}

a.pager-link:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.pager-link.current {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}

.pager-link.disabled {
    opacity: 0.45;
}

button.pager-link {
    background: transparent;
    cursor: pointer;
    font: inherit;
    font-family: var(--font-mono);
    font-size: 0.82rem;
}

button.pager-link:disabled {
    opacity: 0.45;
    cursor: default;
}

button.pager-link:not(:disabled):hover {
    color: var(--accent);
    border-color: var(--accent);
}

.show-more {
    margin-top: 0.5rem;
}

.tags li a {
    color: inherit;
    text-decoration: none;
}

.tags li a:hover {
    color: var(--accent);
}

.post-card.has-image {
    display: grid;
    grid-template-columns: 1fr 200px;
    gap: 1.5rem;
    align-items: start;
}

.post-card-thumb {
    display: block;
    text-decoration: none;
}

.post-card-thumb img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    display: block;
}

.edit-post-link {
    margin-top: 0.9rem;
}

@media (max-width: 720px) {
    .post-card.has-image {
        grid-template-columns: 1fr;
        gap: 0.8rem;
    }

    /* Thumbnail leads on mobile, like a social card. */
    .post-card-thumb {
        order: -1;
    }
}

.post-card h2 {
    margin: 0 0 0.35rem;
    font-size: 1.35rem;
}

.post-card h2 a {
    color: var(--text);
    text-decoration: none;
}

.post-card h2 a:hover {
    color: var(--accent);
}

.post-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 0.5rem;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--text-muted);
}

.post-summary {
    max-width: 62ch;
    margin: 0 0 0.6rem;
    color: var(--text-muted);
}

.tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding: 0;
    margin: 0;
    list-style: none;
}

.tags li {
    padding: 0.15rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--positive);
}

.post-head {
    padding-bottom: 1rem;
}

.post-hero-image {
    width: 100%;
    max-height: 420px;
    object-fit: cover;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

/* Rendered markdown */
.prose {
    max-width: 72ch;
    padding-bottom: 3rem;
}

.prose h2 { font-size: 1.6rem; margin: 2.2rem 0 0.8rem; }
.prose h3 { font-size: 1.25rem; margin: 1.8rem 0 0.6rem; }

.prose p,
.prose ul,
.prose ol {
    margin: 0 0 1.1rem;
}

.prose blockquote {
    margin: 1.4rem 0;
    padding: 0.4rem 0 0.4rem 1.1rem;
    border-left: 3px solid var(--c-gold);
    color: var(--text-muted);
}

.prose code {
    padding: 0.15em 0.4em;
    background: var(--surface-2);
    border-radius: 4px;
    font-size: 0.9em;
}

.prose pre {
    padding: 1rem 1.2rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
    line-height: 1.55;
}

.prose pre code {
    padding: 0;
    background: none;
    font-size: 0.88rem;
}

.prose img {
    border-radius: var(--radius);
}

.prose table {
    border-collapse: collapse;
    margin: 0 0 1.1rem;
}

.prose th,
.prose td {
    padding: 0.45rem 0.8rem;
    border: 1px solid var(--border);
    text-align: left;
}

.prose hr {
    height: 3px;
    margin: 2rem 0;
    border: none;
    border-radius: 2px;
    background: linear-gradient(90deg,
        var(--c-red) 0 25%, var(--c-gold) 25% 50%,
        var(--c-green) 50% 75%, var(--c-blue) 75% 100%);
    max-width: 120px;
}

/* Compact rendered markdown for user-generated content (comments, inboxes).
   Doubled class outranks the pre-wrap on .comment-body/.inbox-text. */
.prose.prose-sm {
    padding-bottom: 0;
    white-space: normal;
    font-size: 0.95rem;
}

.prose.prose-sm h1,
.prose.prose-sm h2,
.prose.prose-sm h3,
.prose.prose-sm h4,
.prose.prose-sm h5,
.prose.prose-sm h6 {
    font-size: 1.05rem;
    margin: 1rem 0 0.4rem;
}

.prose.prose-sm p,
.prose.prose-sm ul,
.prose.prose-sm ol,
.prose.prose-sm table {
    margin: 0 0 0.55rem;
}

.prose.prose-sm blockquote {
    margin: 0.7rem 0;
}

.prose.prose-sm pre {
    padding: 0.6rem 0.8rem;
}

.prose.prose-sm > :last-child {
    margin-bottom: 0;
}

/* Prism token colors mapped to the theme */
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: var(--text-muted); }
.token.punctuation { color: var(--text-muted); }
.token.keyword, .token.atrule { color: var(--info); }
.token.string, .token.char, .token.attr-value { color: var(--positive); }
.token.function, .token.class-name, .token.selector, .token.attr-name { color: var(--c-gold); }
.token.number, .token.boolean, .token.constant, .token.symbol { color: var(--danger); }
.token.operator, .token.entity, .token.url { color: var(--text); }
.token.important, .token.bold { font-weight: 700; }
.token.italic { font-style: italic; }

:root[data-theme='light'] .token.function,
:root[data-theme='light'] .token.class-name,
:root[data-theme='light'] .token.selector,
:root[data-theme='light'] .token.attr-name { color: var(--accent); }

/* ================================================================
   Projects carousel
   ================================================================ */
.projects {
    padding-bottom: 3rem;
}

.carousel-wrap {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.carousel {
    display: flex;
    gap: 1.2rem;
    padding: 0.4rem 0.2rem 1rem;
    margin: 0;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
    flex: 1;
}

.carousel-btn {
    flex: none;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
}

.carousel-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.project-card {
    position: relative;
    flex: 0 0 min(320px, 80vw);
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.project-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
    border-bottom: 1px solid var(--border);
}

.project-image-fallback {
    display: grid;
    place-items: center;
    background: linear-gradient(135deg,
        var(--c-red) 0 25%, var(--c-gold) 25% 50%,
        var(--c-green) 50% 75%, var(--c-blue) 75% 100%);
}

.project-image-fallback span {
    font-family: var(--font-display);
    font-size: 2.6rem;
    font-weight: 700;
    color: #151515;
}

.project-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 1rem 1.2rem 1.2rem;
}

.project-body h2 {
    margin: 0 0 0.4rem;
    font-size: 1.25rem;
}

.project-body p {
    margin: 0 0 0.8rem;
    font-size: 0.92rem;
    color: var(--text-muted);
}

.project-links {
    display: flex;
    gap: 0.6rem;
    margin-top: auto !important;
    font-family: var(--font-mono);
    font-size: 0.8rem;
}

/* Admin-only: a stretched overlay makes the whole card open the editor;
   the real Homepage/Repo links sit above it. */
.project-links a {
    position: relative;
    z-index: 2;
}

.project-edit-link {
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: var(--radius);
    text-decoration: none;
}

/* Inset ring instead of an outer glow — the card clips overflow. Keyed to
   the card hover so the ring stays lit while the pointer is on the raised
   Homepage/Repo links; matches nothing for non-admins (no overlay exists). */
.project-card:hover .project-edit-link,
.project-edit-link:focus-visible {
    box-shadow: inset 0 0 0 1px var(--accent), inset 0 0 24px -14px var(--accent);
}

/* The inset ring + badge are the focus indicator. Transparent (not none):
   forced-colors mode repaints the outline, so keyboard focus stays visible
   there even though box-shadow is suppressed. */
.project-edit-link:focus-visible {
    outline-color: transparent;
}

.project-edit-badge {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: var(--accent);
    color: var(--accent-ink);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    opacity: 0;
    transition: opacity 0.15s ease;
}

.project-card:hover .project-edit-badge,
.project-edit-link:focus-visible .project-edit-badge {
    opacity: 1;
}

.projects-cta {
    margin-top: 1.5rem;
}

.order-cell {
    white-space: nowrap;
}

.narrow-form {
    max-width: 640px;
}

@media (max-width: 720px) {
    .carousel-btn {
        display: none;
    }
}

/* ================================================================
   Avatars & profile
   ================================================================ */
.avatar {
    width: 32px;
    height: 32px;
    border-radius: 999px;
    object-fit: cover;
    flex: none;
}

.avatar-sm {
    width: 24px;
    height: 24px;
}

.avatar-lg {
    width: 96px;
    height: 96px;
    font-size: 2.2rem;
}

.avatar-fallback {
    display: inline-grid;
    place-items: center;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--accent);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.9rem;
}

.avatar-sm.avatar-fallback {
    font-size: 0.72rem;
}

.avatar-anon {
    color: var(--text-muted);
}

.nav-profile {
    display: inline-flex;
    text-decoration: none;
}

.nav-profile:hover .avatar-fallback,
.nav-profile:hover .avatar {
    border-color: var(--accent);
    outline: 1px solid var(--accent);
}

.profile-avatar-row {
    display: flex;
    align-items: center;
    gap: 1.2rem;
    margin: 1.2rem 0 1.6rem;
}

.avatar-upload {
    position: relative;
    overflow: hidden;
    margin-right: 0.6rem;
}

.avatar-upload input[type='file'] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}

/* Owner-photo controls on the admin site-content page; same hidden-input
   trick as .avatar-upload. */
.photo-upload {
    position: relative;
    overflow: hidden;
}

.photo-upload input[type='file'] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}

.owner-photo-preview {
    display: block;
    width: min(200px, 100%);
    aspect-ratio: 4 / 5;
    object-fit: cover;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    margin: 0.4rem 0 0.8rem;
}

.saved-note {
    color: var(--positive);
    font-size: 0.95rem;
}

.nav-profile,
.site-nav .nav-admin {
    position: relative;
}

.unread-badge {
    position: absolute;
    top: -6px;
    right: -8px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    display: grid;
    place-items: center;
    background: var(--c-red);
    color: #fff;
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    line-height: 1;
}

.report-form {
    margin-top: 0.8rem;
    padding: 1rem 1.2rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.quoted-comment {
    margin: 0.6rem 0;
    padding: 0.5rem 0.9rem;
    border-left: 3px solid var(--c-red);
    background: var(--surface-2);
    border-radius: 0 var(--radius) var(--radius) 0;
    color: var(--text-muted);
    font-size: 0.92rem;
    overflow-wrap: anywhere;
}

.report-response {
    padding: 0.6rem 0;
    border-top: 1px solid var(--border);
}

.badge-banned {
    border: 1px solid var(--danger);
    color: var(--danger);
    margin-left: 0.4rem;
}

.profile-nav {
    font-size: 0.92rem;
}

.profile-nav span {
    color: var(--text-muted);
    margin: 0 0.3rem;
}

.comment-you {
    padding: 0.05rem 0.5rem;
    border: 1px solid var(--c-blue);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--info);
}

/* ================================================================
   Comments
   ================================================================ */
.comments {
    max-width: 72ch;
}

.comment-list {
    padding: 0;
    margin: 1rem 0 1.5rem;
    list-style: none;
}

.comment {
    padding: 1rem 0;
    border-top: 1px solid var(--border);
}

.comment-head {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    flex-wrap: wrap;
}

.comment-author {
    font-weight: 700;
    font-size: 0.95rem;
}

.comment-date {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--text-muted);
}

.comment-delete,
.link-button {
    background: none;
    border: none;
    padding: 0;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--text-muted);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.comment-delete:hover,
.link-button:hover {
    color: var(--danger);
}

.link-button {
    margin-right: 0.8rem;
}

.link-button.danger {
    color: var(--danger);
}

.pinned-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 1rem 0 0;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.pinned-comments .comment-list {
    margin-bottom: 0;
}

.pinned-divider {
    border: none;
    border-top: 2px solid var(--border);
    margin: 0;
}

.pinned-divider + .comment-list {
    margin-top: 0;
}

.pinned-divider + .comment-list .comment:first-child {
    border-top: none;
}

.comment-pin {
    background: none;
    border: none;
    padding: 0;
    color: var(--text-muted);
    cursor: pointer;
    line-height: 0;
}

.comment-pin:hover,
.comment-pin.pinned {
    color: var(--accent);
}

.comment-pin.pinned .icon {
    fill: currentColor;
}

.comment-body {
    margin: 0.4rem 0 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.comment-form {
    margin-top: 1rem;
}

.comment-preview {
    min-height: 7rem;
    margin: 0 0 0.9rem;
    padding: 0.6rem 0.8rem;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
}

.comment-signin {
    padding-top: 1rem;
    border-top: 1px solid var(--border);
    color: var(--text-muted);
}

.comment-body-cell {
    display: block;
    max-width: 48ch;
    overflow-wrap: anywhere;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.row-hidden td {
    opacity: 0.55;
}

.pin-indicator {
    margin-left: 0.4rem;
    color: var(--accent);
}

.pin-indicator .icon {
    fill: currentColor;
    vertical-align: -0.1em;
}

/* ================================================================
   Forms & admin editor
   ================================================================ */
input[type='text'],
input[type='email'],
input[type='url'],
textarea,
select {
    width: 100%;
    padding: 0.55rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.95rem;
}

input:focus,
textarea:focus,
select:focus {
    outline: none;
    border-color: var(--accent);
}

/* Live markdown composer: a styled mirror sits under a glyph-transparent
   textarea. The two layers must share identical glyph metrics — same mono
   font, size, line height, padding, and wrap rules — or the caret drifts
   off the visible text (mono keeps advance widths fixed under bold/italic;
   the body font would not). */
.md-input {
    position: relative;
}

.md-input textarea,
.md-input .md-input-mirror {
    font-family: var(--font-mono);
    font-size: 0.9rem;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.md-input .md-input-mirror {
    position: absolute;
    inset: 0;
    padding: 0.55rem 0.75rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    overflow: hidden;
    pointer-events: none;
}

.md-input textarea {
    position: relative;
    z-index: 1;
    display: block;
}

/* Classic (non-overlay) scrollbars reserve a gutter that narrows the
   content box and shifts soft-wrap points away from the mirror's. Hiding
   the bar keeps both layers gutterless and wrap-identical — the box still
   scrolls by wheel, keys, and caret drag. Live mode only: the fallback
   plain textarea has no mirror to align with and keeps its native bar. */
.md-input.md-live textarea {
    scrollbar-width: none;
}

.md-input.md-live textarea::-webkit-scrollbar {
    display: none;
}

.md-input.md-live textarea {
    color: transparent;
    caret-color: var(--text);
    background: transparent;
}

.md-input .mdt-syntax { color: var(--text-muted); }
.md-input .mdt-bold { font-weight: 700; }
.md-input .mdt-italic { font-style: italic; }
.md-input .mdt-strike { text-decoration: line-through; }

.md-input .mdt-code,
.md-input .mdt-fence {
    background: var(--surface-2);
    border-radius: 3px;
}

.md-input .mdt-link { color: var(--accent); }
.md-input .mdt-url { color: var(--text-muted); }
.md-input .mdt-quote { color: var(--text-muted); }
.md-input .mdt-heading { font-weight: 700; }

.field {
    display: block;
    margin-bottom: 1.1rem;
}

.field > span {
    display: block;
    margin-bottom: 0.35rem;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text);
}

.field > span .muted {
    text-transform: none;
    letter-spacing: normal;
}

.check-field {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1.1rem;
    font-size: 0.95rem;
}

.check-field input {
    accent-color: var(--c-green);
    width: 1.05rem;
    height: 1.05rem;
}

.mono-small {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.75rem;
}

.admin-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.2rem;
}

.admin-head h1 {
    margin: 0.4rem 0 0;
}

.table-wrap {
    overflow-x: auto;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92rem;
}

.admin-table th {
    padding: 0.6rem 0.8rem;
    border-bottom: 2px solid var(--border);
    text-align: left;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.admin-table td {
    padding: 0.7rem 0.8rem;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}

.admin-table .actions {
    white-space: nowrap;
}

.admin-table .actions a {
    margin-right: 0.8rem;
}

/* Sortable column headers — buttons that inherit the th / sort-bar
   typography so they look identical until interacted with. */
.sort-header {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: inherit;
}

.sort-header.active {
    color: var(--text);
}

/* After .active so the accent glow also wins on the active column. */
.sort-header:hover,
.sort-header:focus-visible {
    color: var(--accent);
    text-shadow: 0 0 12px var(--accent);
    text-shadow: 0 0 12px color-mix(in srgb, var(--accent) 55%, transparent);
}

/* Reserved width so the arrow appearing never shifts the label. */
.sort-arrow {
    min-width: 1em;
    font-size: 0.7em;
    color: var(--accent);
}

/* Table-style header bar above the Messages / Reports inboxes; reuses the
   .inbox-from / .inbox-subject flex slots so labels align with the rows. */
.inbox-sort-bar {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.4rem;
    border-bottom: 2px solid var(--border);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.inbox-sort-bar .inbox-subject {
    display: inline-flex;
    gap: 1.2rem;
}

.badge {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.72rem;
}

.badge-toggle {
    background: transparent;
    cursor: pointer;
}

.badge-published {
    border: 1px solid var(--positive);
    color: var(--positive);
}

.badge-draft {
    border: 1px solid var(--c-gold);
    color: var(--accent);
}

.badge-danger {
    border: 1px solid var(--danger);
    color: var(--danger);
}

/* Admin stats page */
.stat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: 1rem;
    margin: 1.5rem 0 2rem;
}

.stat-tile {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1rem 1.25rem;
}

.stat-value {
    font-family: var(--font-mono);
    font-size: 1.6rem;
}

.stat-label {
    font-size: 0.82rem;
}

.stats-sort-bar,
.stats-row {
    display: grid;
    grid-template-columns: 1fr 6rem 6rem;
    align-items: center;
    gap: 0.5rem;
}

.stats-row {
    padding: 0.5rem 0.75rem;
}

.stats-count {
    font-family: var(--font-mono);
    text-align: right;
}

.stats-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 2rem;
    margin-top: 2rem;
}

.stats-columns .stats-row {
    grid-template-columns: 1fr 6rem;
}

.editor-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
    align-items: start;
}

.editor-body {
    font-family: var(--font-mono);
    font-size: 0.88rem;
    line-height: 1.55;
}

.editor-preview {
    position: sticky;
    top: var(--header-h);
    padding: 1rem 1.4rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    max-height: 80vh;
    overflow-y: auto;
}

.preview-label {
    margin: 0 0 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
}

.editor-preview .prose {
    padding-bottom: 0;
}

/* ================================================================
   Theme editor (/admin/theme)
   ================================================================ */
fieldset.token-group {
    margin: 0 0 1.6rem;
    padding: 0;
    border: none;
}

.token-group legend {
    margin-bottom: 0.6rem;
    padding: 0;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text);
}

.token-group legend .muted {
    text-transform: none;
    letter-spacing: normal;
}

.token-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.45rem;
}

/* Override the global 100% input width; hex values are 7 mono characters. */
.token-row .hex-input {
    width: 7.5rem;
    font-family: var(--font-mono);
}

.token-row .token-label {
    font-size: 0.9rem;
    color: var(--text-muted);
}

.swatch {
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    flex: none;
    cursor: pointer;
}

.swatch:disabled {
    cursor: default;
}

.preview-mode-toggle {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.8rem;
}

.theme-warnings {
    margin: 0 0 0.8rem;
    padding-left: 1.1rem;
    font-size: 0.85rem;
    color: var(--danger);
}

.theme-warnings li {
    margin-bottom: 0.25rem;
}

/* The frame must paint --bg itself — on the real page body does it. Its
   inline style carries the full previewed-mode token set, so everything
   inside resolves against those values instead of the page theme. */
.theme-preview-frame {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

/* Neutralize the 92vw page container inside the half-width column; the
   clamp() typography then reads like the mobile landing page. */
.theme-preview-frame .container {
    width: 100%;
    padding-inline: 1rem;
}

.theme-preview-frame .hero {
    padding: 3rem 0 2.5rem;
}

/* Color-picker dialog (opened from the token swatches). */
.theme-picker {
    width: min(19rem, calc(100vw - 2rem));
    padding: 1rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.theme-picker::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
}

/* The saturation/brightness field: white→hue horizontally, transparent→black
   vertically; colorpicker.js drives --picker-hue. */
.picker-sv {
    position: relative;
    height: 11rem;
    border-radius: var(--radius);
    background:
        linear-gradient(to top, #000, transparent),
        linear-gradient(to right, #fff, hsl(var(--picker-hue, 0) 100% 50%));
    touch-action: none;
    user-select: none;
    cursor: crosshair;
}

.picker-thumb {
    position: absolute;
    width: 14px;
    height: 14px;
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgb(0 0 0 / 0.6);
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.picker-hue {
    width: 100%;
    margin: 0.8rem 0 0;
    accent-color: var(--accent);
}

.picker-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.8rem 0;
}

.picker-swatch {
    width: 1.9rem;
    height: 1.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    flex: none;
}

.picker-row .picker-hex {
    width: 7.5rem;
    font-family: var(--font-mono);
}

.picker-actions {
    display: flex;
    gap: 0.6rem;
    justify-content: flex-end;
}

.editor-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.8rem;
}

.btn-danger {
    border-color: var(--danger);
    color: var(--danger);
}

.btn-danger:hover {
    border-color: var(--danger);
    color: var(--danger);
    filter: brightness(1.15);
}

.confirm-delete {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.9rem;
    color: var(--danger);
}

.upload-preview {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    margin-bottom: 0.5rem;
}

.upload-preview img {
    max-height: 70px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

/* Admin header-image crop tool: the image sits in a stage and a movable,
   corner-resizable 16:9 box selects the region that gets saved. */
.crop-hidden {
    display: none;
}

/* Closed by default via class, not the hidden attribute — the UA's
   [hidden] { display: none } would lose to an author display rule. */
.crop-panel {
    display: none;
}

.crop-panel.open {
    display: grid;
    gap: 0.6rem;
    margin-top: 0.4rem;
}

.crop-stage {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    max-height: 420px;
    overflow: hidden;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: repeating-conic-gradient(var(--surface) 0% 25%, var(--surface-2) 0% 50%)
        0 0 / 22px 22px;
    touch-action: none;
    user-select: none;
}

.crop-stage.pannable {
    cursor: grab;
}

.crop-stage.panning {
    cursor: grabbing;
}

.crop-stage img {
    position: absolute;
    max-width: none;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
}

.crop-frame {
    position: absolute;
    border: 1.5px solid var(--accent);
    /* Dims everything outside the selection; the stage clips the spread. */
    box-shadow: 0 0 0 9999px rgba(21, 21, 21, 0.62);
    cursor: move;
    /* Rule-of-thirds guides */
    background-image:
        linear-gradient(to right, transparent calc(33.333% - 0.5px), rgba(255, 255, 255, 0.22) calc(33.333% - 0.5px), rgba(255, 255, 255, 0.22) calc(33.333% + 0.5px), transparent calc(33.333% + 0.5px)),
        linear-gradient(to right, transparent calc(66.666% - 0.5px), rgba(255, 255, 255, 0.22) calc(66.666% - 0.5px), rgba(255, 255, 255, 0.22) calc(66.666% + 0.5px), transparent calc(66.666% + 0.5px)),
        linear-gradient(to bottom, transparent calc(33.333% - 0.5px), rgba(255, 255, 255, 0.22) calc(33.333% - 0.5px), rgba(255, 255, 255, 0.22) calc(33.333% + 0.5px), transparent calc(33.333% + 0.5px)),
        linear-gradient(to bottom, transparent calc(66.666% - 0.5px), rgba(255, 255, 255, 0.22) calc(66.666% - 0.5px), rgba(255, 255, 255, 0.22) calc(66.666% + 0.5px), transparent calc(66.666% + 0.5px));
}

.crop-handle {
    position: absolute;
    width: 13px;
    height: 13px;
    background: var(--accent);
    border: 2px solid var(--accent-ink);
    border-radius: 2px;
}

.crop-handle::after {
    /* Bigger invisible hit area for touch */
    content: '';
    position: absolute;
    inset: -9px;
}

.crop-handle[data-h="nw"] { left: -7px; top: -7px; cursor: nwse-resize; }
.crop-handle[data-h="ne"] { right: -7px; top: -7px; cursor: nesw-resize; }
.crop-handle[data-h="sw"] { left: -7px; bottom: -7px; cursor: nesw-resize; }
.crop-handle[data-h="se"] { right: -7px; bottom: -7px; cursor: nwse-resize; }

.crop-hero-guide {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    /* height set by crop.js from the hero band fraction */
    border-top: 1px dashed rgba(255, 255, 255, 0.75);
    border-bottom: 1px dashed rgba(255, 255, 255, 0.75);
    pointer-events: none;
}

.crop-hero-guide span {
    position: absolute;
    right: 6px;
    top: 4px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.75);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}

.crop-controls {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.crop-controls input[type="range"] {
    flex: 1 1 140px;
    accent-color: var(--accent);
}

.crop-zoom-value {
    min-width: 3.2em;
    text-align: right;
    color: var(--text-muted);
}

.crop-readout {
    margin: 0;
    color: var(--text-muted);
}

.crop-previews {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.8rem;
    align-items: start;
}

@media (max-width: 560px) {
    .crop-previews {
        grid-template-columns: 1fr;
    }
}

.crop-preview-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.6rem;
}

.crop-preview-card p {
    margin: 0 0 0.4rem;
}

.crop-preview-card canvas {
    display: block;
    width: 100%;
    border-radius: 4px;
    background: var(--surface-2);
}

.card-link {
    display: block;
    text-decoration: none;
    color: var(--text);
}

.card-link:hover {
    border-color: var(--accent);
}

@media (max-width: 900px) {
    .editor-grid {
        grid-template-columns: 1fr;
    }

    .editor-preview {
        position: static;
        max-height: none;
    }
}

/* ================================================================
   Contact & inbox
   ================================================================ */
.contact {
    padding-bottom: 3rem;
}

.contact-grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: 3rem;
    align-items: start;
}

.hp-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.sent-note h2 {
    margin-top: 0;
}

.contact-aside .contact-links {
    padding: 0;
    margin: 0.8rem 0 0;
    list-style: none;
}

.contact-links li {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border);
}

.contact-links a {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

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

.inbox-item {
    border-bottom: 1px solid var(--border);
}

.inbox-summary {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    flex-wrap: wrap;
    width: 100%;
    padding: 0.9rem 0.4rem;
    background: none;
    border: none;
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.95rem;
    text-align: left;
    cursor: pointer;
}

.inbox-summary:hover {
    background: var(--surface);
}

.inbox-item.unread .inbox-from,
.inbox-item.unread .inbox-subject {
    font-weight: 700;
}

.inbox-from {
    flex: 0 0 12ch;
}

.inbox-subject {
    flex: 1;
    min-width: 200px;
}

.inbox-date {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--text-muted);
}

.inbox-body {
    padding: 0.4rem 0.4rem 1.2rem;
}

.inbox-text {
    max-width: 70ch;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

@media (max-width: 720px) {
    .contact-grid {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }
}

/* ================================================================
   Footer
   ================================================================ */
.site-footer {
    margin-top: 4rem;
}

.footer-strip {
    height: 4px;
    background: linear-gradient(90deg,
        var(--c-red) 0 25%, var(--c-gold) 25% 50%,
        var(--c-green) 50% 75%, var(--c-blue) 75% 100%);
}

.site-footer .inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-block: 1.6rem;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 1.2rem;
}

.footer-links a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--text-muted);
    text-decoration: none;
}

.footer-links a:hover {
    color: var(--accent);
}

.sponsor-link .icon {
    color: var(--c-red);
}

.footer-legal {
    font-size: 0.82rem;
}

.legal {
    padding-bottom: 3rem;
}

.legal h2 {
    font-size: 1.3rem;
}

/* ================================================================
   Forms & framework chrome
   ================================================================ */
.validation-message {
    color: var(--danger);
    font-size: 0.85rem;
}

.invalid {
    outline: 1px solid var(--danger);
}

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 0.8rem 1.2rem;
    background: var(--surface-2);
    color: var(--text);
    border-top: 3px solid var(--c-red);
    box-shadow: 0 -2px 12px rgb(0 0 0 / 0.4);
}

#blazor-error-ui .dismiss {
    position: absolute;
    right: 1rem;
    top: 0.6rem;
    cursor: pointer;
}
