/* The Canon: shell.css. The chrome every page shares: reset, base type,
   scrollbars, the sticky glass top bar, nav, buttons, back-to-top, and the site
   footer. Loaded after tokens.css and before the page's own stylesheet on every
   page, so these rules are defined exactly once. Every colour is a token, a color-mix()
   over a token, or an accent-tinted rgba() glow. */

/* ── Reset & base ─────────────────────────────────────────────────────────── */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scrollbar-color: color-mix(in srgb, var(--accent-primary) 55%, transparent) rgba(0, 0, 0, 0.32);
}

body {
    font-family: var(--font-ui);
    color: var(--text-primary);
    background: var(--canvas);
    line-height: 1.6;
    min-height: 100vh;
}

h1 {
    color: var(--text-primary);
    font-weight: 700;
    letter-spacing: -0.02em;
}

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

/* ── Scrollbars: traditional, always visible, wide enough to grab ──────────── */
::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.32);
}

::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--accent-primary) 45%, transparent);
    border-radius: var(--radius-pill);
    border: 2px solid transparent;
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--accent-primary) 75%, transparent);
    background-clip: padding-box;
}

/* ── Icons ────────────────────────────────────────────────────────────────── */
.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    line-height: 0;
}

.icon-svg {
    display: block;
}

/* ── Top bar: the one piece of chrome on every page ───────────────────────── */
.top-bar {
    position: sticky;
    top: var(--space-2);
    z-index: 80;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    max-width: 1440px;
    margin-top: var(--space-2);
    margin-inline: max(var(--space-4), calc((100% - 1440px) / 2));
    padding: var(--space-2) var(--space-3);
    background: var(--panel-fill-raised);
    backdrop-filter: blur(var(--panel-blur));
    -webkit-backdrop-filter: blur(var(--panel-blur));
    border: var(--border) solid color-mix(in srgb, var(--accent-primary) 30%, var(--panel-border));
    border-radius: var(--radius-md);
    box-shadow: var(--panel-lift), inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.wordmark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--text-primary);
    text-decoration: none;
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
    transition: transform var(--motion-hover) var(--ease-standard);
}

.wordmark:hover {
    transform: translateY(-1px);
}

.wordmark-mark {
    filter: drop-shadow(0 0 8px rgba(36, 224, 122, 0.55));
    transition: filter var(--motion-hover) var(--ease-standard);
}

.wordmark:hover .wordmark-mark {
    filter: drop-shadow(0 0 14px rgba(36, 224, 122, 0.85));
}

/* Search field: recessed into the bar (darker than its host, no lift). */
.top-search {
    flex: 1;
    display: flex;
    align-items: center;
    gap: var(--space-1);
    max-width: 480px;
    background: var(--panel-fill-sunken);
    border: var(--border) solid var(--panel-border);
    border-radius: var(--radius-pill);
    padding: 8px var(--space-2);
    transition: border-color var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard);
}

.top-search:focus-within {
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px var(--accent-primary-dim);
}

#searchBox {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: none;
    color: var(--text-primary);
    font-size: 0.9rem;
    font-family: inherit;
    padding: 4px 0;
}

#searchBox::placeholder {
    color: var(--text-secondary);
}

.search-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: transparent;
    border: none;
    padding: 2px;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-hover) var(--ease-standard),
        transform var(--motion-hover) var(--ease-standard);
}

.search-clear.visible {
    opacity: 0.8;
    pointer-events: auto;
}

.search-clear:hover {
    opacity: 1;
    transform: scale(1.12);
}

.search-clear:active {
    transform: scale(0.94);
}

/* ── Nav ──────────────────────────────────────────────────────────────────── */
.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-shrink: 0;
}

.nav-link {
    display: inline-flex;
    align-items: center;
    color: var(--accent-primary);
    text-decoration: none;
    padding: 8px 18px;
    border-radius: var(--radius-pill);
    font-weight: 600;
    font-size: 0.85rem;
    white-space: nowrap;
    border: var(--border) solid color-mix(in srgb, var(--accent-primary) 55%, transparent);
    transition: transform var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard),
        border-color var(--motion-hover) var(--ease-standard),
        background-color var(--motion-hover) var(--ease-standard),
        color var(--motion-hover) var(--ease-standard);
}

.nav-link:hover {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border-color: var(--accent-primary);
    transform: translateY(-2px);
    box-shadow: var(--panel-lift-high), 0 0 20px rgba(36, 224, 122, 0.35);
}

.nav-link:active {
    transform: translateY(0);
}

.nav-link--active {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border-color: var(--accent-primary);
    box-shadow: 0 0 18px rgba(36, 224, 122, 0.3);
    cursor: default;
    pointer-events: none;
}

/* ── Page title band (statistics, about) ──────────────────────────────────── */
.page-head {
    text-align: center;
    padding: var(--space-6) var(--space-3) var(--space-4);
}

.page-head h1 {
    font-size: clamp(2rem, 5vw, 3.2rem);
    line-height: 1.05;
    letter-spacing: -0.03em;
    margin-bottom: var(--space-2);
}

.page-head p {
    color: var(--text-secondary);
    font-size: 1.05rem;
    max-width: 56ch;
    margin: 0 auto;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    background: var(--accent-primary);
    color: var(--text-on-accent);
    padding: 12px 24px;
    border-radius: var(--radius-sm);
    border: none;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9rem;
    font-family: inherit;
    text-decoration: none;
    transition: transform var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard),
        filter var(--motion-hover) var(--ease-standard);
}

.btn:hover {
    transform: translateY(-2px);
    box-shadow: var(--panel-lift-high), 0 0 22px rgba(36, 224, 122, 0.35);
    filter: brightness(1.06);
}

.btn:active {
    transform: translateY(0) scale(0.985);
    box-shadow: var(--panel-lift);
}

.btn-secondary {
    background: var(--panel-fill-raised);
    color: var(--text-primary);
    border: var(--border) solid var(--panel-border);
}

.btn-secondary:hover {
    border-color: var(--panel-border-bright);
    box-shadow: var(--panel-lift-high);
}

.btn-small {
    padding: 8px 16px;
    font-size: 0.85rem;
}

/* Disabled controls read as inert rather than silently no-oping. */
.btn:disabled,
button:disabled,
select:disabled,
input:disabled {
    opacity: 0.45;
    filter: saturate(0.25);
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ── Back to top ──────────────────────────────────────────────────────────── */
.back-to-top {
    position: fixed;
    bottom: var(--space-4);
    right: var(--space-4);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border: none;
    border-radius: 50%;
    cursor: pointer;
    box-shadow: var(--panel-lift), 0 0 18px rgba(36, 224, 122, 0.3);
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
    transition: opacity var(--motion-base) var(--ease-standard),
        transform var(--motion-base) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard);
    z-index: 100;
}

.back-to-top.visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.back-to-top.visible:hover {
    transform: translateY(-3px);
    box-shadow: var(--panel-lift-high), 0 0 28px rgba(36, 224, 122, 0.55);
}

.back-to-top.visible:active {
    transform: translateY(0) scale(0.94);
}

/* ── Site footer ──────────────────────────────────────────────────────────── */
/* Quiet chrome. The hairline and the drop in type size are what keep it from
   competing with the last content block above it. */
.site-footer {
    margin-top: var(--space-8);
    border-top: var(--border) solid var(--panel-border);
    padding: var(--space-4) var(--space-3) var(--space-6);
    text-align: center;
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.7;
}

/* .back-to-top is fixed at the viewport's bottom-right and only the browse page
   carries one, so only that page pays for the clearance. At the end of that
   document the puck floats over this band, and anything short of (its offset +
   its height) leaves the footer's last line running under it at the narrow
   widths where the links wrap toward the right edge. */
body[data-page="home"] .site-footer {
    padding-bottom: calc(var(--space-4) + 44px + var(--space-1));
}

.footer-inner {
    max-width: 860px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.footer-brand {
    color: var(--text-primary);
    font-weight: 600;
    letter-spacing: -0.01em;
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
}

/* --accent-secondary on canvas measures 6.8:1, clear of the 4.5:1 floor at
   this size. It is the token tokens.css reserves for links. */
.footer-links a {
    color: var(--accent-secondary);
    text-decoration: none;
    transition: color var(--motion-hover) var(--ease-standard);
}

.footer-links a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

.footer-link--active {
    color: var(--text-secondary);
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .top-bar {
        flex-wrap: wrap;
        margin-left: var(--space-2);
        margin-right: var(--space-2);
    }

    .top-search {
        order: 3;
        flex-basis: 100%;
        max-width: none;
    }

    /* min-width:0 lets the nav shrink below its min-content width and wrap
       instead of pushing the sticky bar past the viewport, which took the whole
       page's horizontal scroll with it. flex-wrap is what it then does with the
       overflow: the pills stack rather than spilling off the right edge. */
    .site-nav {
        flex: 1;
        min-width: 0;
        flex-wrap: wrap;
        justify-content: flex-end;
    }

    .page-head {
        padding: var(--space-4) var(--space-2) var(--space-3);
    }
}

@media (max-width: 480px) {
    .top-bar {
        margin-left: var(--space-1);
        margin-right: var(--space-1);
        gap: var(--space-2);
    }

    .nav-link {
        padding: 8px 14px;
    }

    .back-to-top {
        bottom: var(--space-2);
        right: var(--space-2);
        width: 40px;
        height: 40px;
    }

    /* The sides stay at --space-3 rather than dropping with the rest of the
       page: at this width the disclosure very nearly fills its 62ch measure and
       would otherwise sit against the viewport edges. */
    .site-footer {
        margin-top: var(--space-6);
        padding: var(--space-3) var(--space-3) var(--space-4);
    }

    /* Same derivation as above against the 40px puck this breakpoint uses. */
    body[data-page="home"] .site-footer {
        padding-bottom: calc(var(--space-2) + 40px + var(--space-1));
    }
}

/* ── Family switcher ──────────────────────────────────────────────────────── */
/* The four Marcsplained sites, rendered by site-shell.js immediately after
   .site-nav inside the top bar. Canonical text: identical on all four sites,
   resolving against whichever palette tokens.css binds, so the switcher is one
   shared control rather than four lookalikes.

   It has to read as a different kind of control from .nav-link, which is an
   accent-coloured pill offering a destination inside this site. These are plain
   text at --text-secondary, one weight lighter, with no border and no accent
   until the cursor arrives: page navigation first, sibling sites second. The
   hairline is what divides the two clusters. */
.site-switcher {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-shrink: 0;
    /* Matches .top-bar's own gap, so the hairline sits centred in its gutter
       rather than 24px from the nav and 16px from the first site name. */
    padding-left: var(--space-3);
    border-left: var(--border) solid var(--panel-border);
}

.site-link {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
    transition: color var(--motion-hover) var(--ease-standard),
        transform var(--motion-hover) var(--ease-standard);
}

/* The same lift the rest of the shell uses, at the wordmark's amplitude rather
   than the nav pill's: this is a text link in the bar, and the nearest thing to
   it already moves 1px. */
.site-switcher a.site-link:hover {
    color: var(--accent-secondary);
    transform: translateY(-1px);
}

.site-switcher a.site-link:active {
    transform: translateY(0);
}

/* Inert: it labels where you are rather than offering a destination, so it
   never lifts and never takes an accent. Dimmed by recession rather than by
   colour: the sunken fill reads as cut into the bar, the way an input does,
   while the label itself stays at full --text-secondary. Knocking the token
   back with alpha instead would composite into the mid-grey band the legibility
   floor rejects. Held at rest rather than on hover, so it survives touch. */
.site-link--active {
    background: var(--panel-fill-sunken);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
    cursor: default;
}

@media (max-width: 768px) {
    /* Its own full-width row beneath the search rather than wrapping into
       .site-nav, which is where a shrinking bar would otherwise push it. The
       hairline moves from the left edge to the top so the division survives the
       reflow. */
    .site-switcher {
        order: 4;
        flex-basis: 100%;
        justify-content: center;
        padding-left: 0;
        padding-top: var(--space-2);
        border-left: none;
        border-top: var(--border) solid var(--panel-border);
    }
}

@media (max-width: 480px) {
    /* Type size holds; only the gaps close. Below roughly 340px the four names
       wrap to a second centred row inside the switcher's own band. */
    .site-switcher {
        flex-wrap: wrap;
        justify-content: center;
        gap: 4px;
        padding-top: var(--space-1);
    }

    .site-link {
        padding: 4px 8px;
    }
}
