/* ============================================================
   RetroTechCollection — retrotechcollection.com
   Hub landing page.

   The whole surface is one idea: a beige machine with a lit
   screen. `--case` tones are the plastic (edges, hairlines,
   chrome); `--phosphor` is the signal (anything the machine is
   telling you). Nothing is neon for its own sake.
   ============================================================ */

/* ---------- Tokens ---------- */
:root {
    /* Signal — blue CRT phosphor (#30aff8). Chosen inside sRGB: brighter
       blues at this chroma clip the blue channel and lose their hue. */
    --phosphor: oklch(0.72 0.15 240);
    --phosphor-dim: oklch(0.66 0.12 240);
    --phosphor-deep: oklch(0.5 0.1 240);
    --glow-soft: oklch(0.72 0.15 240 / 0.28);
    --glow-hard: oklch(0.72 0.15 240 / 0.55);

    /* Chassis — the plastic. Sampled from the mark (#D4BF9B / #847C6D). */
    --case: oklch(0.83 0.045 84);
    --case-edge: oklch(0.6 0.028 82);

    /* Ground */
    --void: oklch(0.155 0.008 240);
    --void-deep: oklch(0.115 0.008 240);
    --panel: oklch(0.205 0.01 240);
    --panel-lift: oklch(0.245 0.014 240);

    /* Ink — all verified ≥4.5:1 on --void, --panel and --panel-lift */
    --ink: oklch(0.96 0.006 90);
    --ink-2: oklch(0.79 0.01 90);
    /* Lifted from 0.66 so the smallest text still clears 4.5:1 even at the
       hottest point of the cursor bloom, not just against the flat ground. */
    --ink-3: oklch(0.71 0.01 90);

    /* Hairlines */
    --line: oklch(1 0 0 / 0.09);
    --line-warm: oklch(0.83 0.045 84 / 0.22);

    /* Type */
    --font-display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
    --font-mono: 'Martian Mono', ui-monospace, 'SF Mono', Menlo, monospace;

    /* Measure */
    --shell: 1080px;
    --gutter: clamp(1.25rem, 4vw, 2.5rem);
    --radius: 14px;
    --radius-sm: 8px;

    /* Motion — exponential ease-out only, no bounce */
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);

    /* Semantic z-scale */
    --z-canvas: 0;
    --z-crt: 1;
    --z-content: 2;
    --z-header: 20;
    --z-tooltip: 40;
}

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    min-height: 100svh;
    background: var(--void);
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(0.95rem, 0.9rem + 0.2vw, 1.0625rem);
    line-height: 1.65;
    font-synthesis-weight: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

img,
svg {
    display: block;
    max-width: 100%;
}

a {
    color: inherit;
    text-decoration: none;
}

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

::selection {
    background: var(--phosphor);
    color: var(--void-deep);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.skip-link {
    position: absolute;
    top: 0;
    left: 50%;
    z-index: var(--z-tooltip);
    transform: translate(-50%, -110%);
    padding: 0.7rem 1.2rem;
    border: 1px solid var(--phosphor);
    border-top: 0;
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    background: var(--void-deep);
    color: var(--phosphor);
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    transition: transform 0.25s var(--ease);
}

.skip-link:focus-visible {
    transform: translate(-50%, 0);
}

/* ============================================================
   CRT ATMOSPHERE
   Layered, not stacked at random: a phosphor dust canvas, then
   the shadow mask, then the rolling refresh bar, then the tube
   vignette. All are inert to pointer events.
   ============================================================ */

.crt-dust {
    position: fixed;
    inset: 0;
    z-index: var(--z-canvas);
    pointer-events: none;
}

.crt-layer {
    position: fixed;
    pointer-events: none;
    z-index: var(--z-crt);
}

/* ---------- Cursor bloom ----------
   Two blended discs that spring after the pointer (see main.js). They live
   at --z-crt, below the content layer, so they bloom up through the
   translucent panels but can never sit on top of text and dull it.
   JS removes both outright for coarse pointers and reduced motion. */
.cursor-glow {
    position: fixed;
    top: 0;
    left: 0;
    border-radius: 50%;
    pointer-events: none;
    z-index: var(--z-crt);
    opacity: 0;
    will-change: transform, opacity;
    transition: opacity 0.35s var(--ease);
}

/* Peak alphas are capped so the brightest point of the bloom still leaves
   body copy above 4.5:1. A screen-blended core much hotter than this makes
   --ink-2 unreadable wherever the cursor parks; measured, not guessed. */
.cursor-glow--outer {
    width: 520px;
    height: 520px;
    background: radial-gradient(circle,
        oklch(0.72 0.15 240 / 0.14) 0%,
        oklch(0.72 0.15 240 / 0.06) 30%,
        oklch(0.72 0.15 240 / 0.02) 50%,
        transparent 70%);
    filter: blur(30px);
    mix-blend-mode: color-dodge;
}

.cursor-glow--inner {
    width: 190px;
    height: 190px;
    background: radial-gradient(circle,
        oklch(0.72 0.15 240 / 0.2) 0%,
        oklch(0.72 0.15 240 / 0.1) 30%,
        transparent 60%);
    filter: blur(10px);
    mix-blend-mode: screen;
}

/* Aperture-grille shadow mask: fine vertical triads + scanlines. */
.crt-mask {
    inset: 0;
    opacity: 0.5;
    background:
        repeating-linear-gradient(90deg,
            oklch(0.72 0.15 240 / 0.028) 0 1px,
            transparent 1px 3px),
        repeating-linear-gradient(0deg,
            transparent 0 2px,
            oklch(0 0 0 / 0.22) 2px 4px);
}

/* The tube's refresh bar, drifting slowly down the glass. */
.crt-refresh {
    left: 0;
    right: 0;
    height: 46vh;
    background: linear-gradient(180deg,
        transparent 0%,
        oklch(0.72 0.15 240 / 0.013) 42%,
        oklch(0.72 0.15 240 / 0.032) 50%,
        oklch(0.72 0.15 240 / 0.013) 58%,
        transparent 100%);
    filter: blur(6px);
    animation: refresh-roll 14s linear infinite;
}

@keyframes refresh-roll {
    from { transform: translateY(-50vh); }
    to { transform: translateY(150vh); }
}

/* Curvature falloff — the corners of a real tube lose brightness. */
.crt-vignette {
    inset: 0;
    background:
        radial-gradient(120% 100% at 50% 0%,
            oklch(0.72 0.15 240 / 0.05) 0%,
            transparent 55%),
        radial-gradient(ellipse 105% 90% at 50% 50%,
            transparent 42%,
            oklch(0.115 0.008 240 / 0.55) 82%,
            oklch(0.09 0.006 240 / 0.85) 100%);
}

/* ---------- Shell ---------- */
.shell {
    position: relative;
    z-index: var(--z-content);
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* ============================================================
   HERO
   ============================================================ */

.hero {
    padding-block: clamp(3.5rem, 9vw, 6rem) clamp(2rem, 4.5vw, 3rem);
    text-align: center;
}

/* --- Logo lockup: vector mark + live-text wordmark --- */
.lockup {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(0.9rem, 2.4vw, 1.5rem);
    margin-bottom: clamp(1.5rem, 3.5vw, 2.25rem);
}

.lockup__mark {
    width: clamp(64px, 11vw, 104px);
    height: auto;
    /* The screen in the mark is lit, so it casts light. */
    filter: drop-shadow(0 0 28px var(--glow-soft))
        drop-shadow(0 2px 10px oklch(0 0 0 / 0.6));
    animation: mark-breathe 6s var(--ease-soft) infinite;
}

@keyframes mark-breathe {
    0%, 100% { filter: drop-shadow(0 0 22px oklch(0.72 0.15 240 / 0.2)) drop-shadow(0 2px 10px oklch(0 0 0 / 0.6)); }
    50% { filter: drop-shadow(0 0 34px oklch(0.72 0.15 240 / 0.34)) drop-shadow(0 2px 10px oklch(0 0 0 / 0.6)); }
}

.wordmark {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.06em;
    font-size: clamp(1.15rem, 3.6vw, 2rem);
    line-height: 0.98;
    text-align: left;
}

.wordmark span {
    display: block;
    font-variation-settings: 'wdth' 112;
    text-transform: uppercase;
    white-space: nowrap;
}

/* The mark carries the pixel voice; the wordmark answers it with
   one heavy line and two hairline ones, as in the printed logo. */
.wordmark__lead {
    font-weight: 800;
    letter-spacing: -0.005em;
    color: var(--ink);
}

.wordmark__tail {
    font-weight: 300;
    letter-spacing: 0.055em;
    color: var(--ink-2);
}

/* --- Tagline: the one tracked mono label on the page --- */
.tagline {
    font-family: var(--font-mono);
    font-size: clamp(0.6rem, 1.5vw, 0.72rem);
    font-weight: 500;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--phosphor);
    text-shadow: 0 0 18px var(--glow-soft);
    margin-bottom: clamp(1.1rem, 2.5vw, 1.5rem);
}

/* Wide tracking is the point of this line, but it must not wrap awkwardly
   on a phone — tighten it rather than let it break mid-phrase. */
@media (max-width: 560px) {
    .tagline {
        letter-spacing: 0.14em;
    }
}

.hero__lede {
    max-width: 44ch;
    margin-inline: auto;
    font-size: clamp(1rem, 0.94rem + 0.34vw, 1.2rem);
    font-weight: 400;
    line-height: 1.72;
    color: var(--ink-2);
    text-wrap: pretty;
}

.hero__lede strong {
    color: var(--ink);
    font-weight: 600;
}

/* --- Terminal prompt: points at the cards below --- */
.prompt {
    display: inline-flex;
    align-items: baseline;
    gap: 0.1em;
    margin-top: clamp(1.6rem, 3.5vw, 2.25rem);
    padding: 0.5rem 0.95rem;
    border: 1px solid var(--line-warm);
    border-radius: var(--radius-sm);
    background: oklch(0.115 0.008 240 / 0.6);
    box-shadow: inset 0 0 24px oklch(0.72 0.15 240 / 0.05);
    font-family: var(--font-mono);
    font-size: clamp(0.65rem, 1.6vw, 0.78rem);
    font-weight: 400;
    color: var(--phosphor);
    text-shadow: 0 0 12px var(--glow-soft);
}

.prompt__chevron {
    color: var(--phosphor-deep);
}

.prompt__caret {
    display: inline-block;
    width: 0.55em;
    height: 1.05em;
    translate: 0 0.16em;
    background: var(--phosphor);
    box-shadow: 0 0 10px var(--glow-hard);
    animation: caret-blink 1.1s steps(1) infinite;
}

@keyframes caret-blink {
    0%, 50% { opacity: 1; }
    50.01%, 100% { opacity: 0; }
}

/* ============================================================
   SECTIONS
   ============================================================ */

.section {
    padding-block: clamp(2rem, 5vw, 3rem);
}

.section__head {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    margin-bottom: clamp(1.25rem, 3vw, 1.75rem);
}

.section__head h2 {
    flex: none;
    font-size: clamp(1.1rem, 0.98rem + 0.6vw, 1.5rem);
    font-weight: 700;
    font-variation-settings: 'wdth' 105;
    letter-spacing: -0.015em;
    color: var(--ink);
    text-wrap: balance;
}

/* A drawn rule rather than a repeated eyebrow label. */
.section__rule {
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg,
        var(--line-warm),
        oklch(0.83 0.045 84 / 0.04) 70%,
        transparent);
}

.section__note {
    flex: none;
    font-family: var(--font-mono);
    font-size: 0.63rem;
    font-weight: 400;
    letter-spacing: 0.1em;
    color: var(--ink-3);
}

/* ============================================================
   DESTINATIONS — asymmetric: one feature panel, two beside it
   ============================================================ */

.destinations {
    display: grid;
    gap: clamp(0.85rem, 1.8vw, 1.1rem);
    grid-template-columns: 1fr;
}

/* The archive is the front door, so it spans every column at every width.
   Below 1020px the remaining three fall to two-up, and the odd one out
   takes the full row rather than sitting as a half-width orphan. */
@media (min-width: 720px) {
    .destinations {
        grid-template-columns: repeat(2, 1fr);
    }

    .panel--feature,
    .destinations > .panel:last-child {
        grid-column: 1 / -1;
    }
}

@media (min-width: 1020px) {
    .destinations {
        grid-template-columns: repeat(3, 1fr);
    }

    .destinations > .panel:last-child {
        grid-column: auto;
    }

    .panel--feature {
        grid-column: 1 / -1;
    }
}

/* ---------- Panel: the shared surface for every linked place ---------- */
.panel {
    --panel-accent: var(--phosphor);
    position: relative;
    display: flex;
    flex-direction: column;
    padding: clamp(1.35rem, 2.6vw, 1.85rem);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background:
        linear-gradient(180deg,
            oklch(0.245 0.014 240 / 0.55),
            oklch(0.205 0.01 240 / 0.9));
    isolation: isolate;
    overflow: hidden;
    transition:
        transform 0.4s var(--ease),
        border-color 0.4s var(--ease),
        box-shadow 0.4s var(--ease);
}

/* Specular hairline along the top edge — plastic catching the light. */
.panel::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        var(--line-warm) 18%,
        oklch(0.83 0.045 84 / 0.42) 50%,
        var(--line-warm) 82%,
        transparent);
    opacity: 0.8;
    transition: opacity 0.4s var(--ease);
}

/* Screen-glow bloom that rises from the panel floor on hover. */
.panel::after {
    content: '';
    position: absolute;
    inset: auto -30% -60% -30%;
    height: 120%;
    z-index: -1;
    background: radial-gradient(ellipse at 50% 100%,
        var(--panel-accent) 0%,
        transparent 62%);
    opacity: 0;
    transition: opacity 0.45s var(--ease);
}

.panel:hover,
.panel:focus-visible {
    transform: translateY(-3px);
    border-color: oklch(0.72 0.15 240 / 0.34);
    box-shadow:
        0 16px 40px -18px oklch(0 0 0 / 0.9),
        0 0 0 1px oklch(0.72 0.15 240 / 0.08);
}

.panel:hover::before,
.panel:focus-visible::before {
    opacity: 1;
}

.panel:hover::after,
.panel:focus-visible::after {
    opacity: 0.11;
}

.panel:active {
    transform: translateY(-1px);
}

/* ---------- Panel internals ---------- */
.panel__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: clamp(0.9rem, 2vw, 1.15rem);
}

.panel__icon {
    /* Explicit box: this span sits in a flex parent on the small panels and
       a block parent on the feature panel, and must size identically in both. */
    display: grid;
    place-items: center;
    flex: none;
    width: 46px;
    height: 46px;
    padding: 9px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: oklch(0.115 0.008 240 / 0.8);
    color: var(--panel-accent);
    box-shadow: inset 0 0 18px oklch(0.72 0.15 240 / 0.07);
    transition: color 0.4s var(--ease), border-color 0.4s var(--ease),
        box-shadow 0.4s var(--ease);
}

.panel:hover .panel__icon {
    border-color: oklch(0.72 0.15 240 / 0.3);
    box-shadow: inset 0 0 22px oklch(0.72 0.15 240 / 0.16),
        0 0 18px -6px var(--glow-soft);
}

.panel__icon svg {
    width: 100%;
    height: 100%;
}

.tag {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding: 0.3rem 0.6rem;
    border: 1px solid oklch(0.72 0.15 240 / 0.3);
    border-radius: 999px;
    background: oklch(0.72 0.15 240 / 0.09);
    color: var(--phosphor);
    font-family: var(--font-mono);
    font-size: 0.56rem;
    font-weight: 600;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    white-space: nowrap;
}

.tag--quiet {
    border-color: var(--line-warm);
    background: oklch(0.83 0.045 84 / 0.07);
    color: var(--case);
}

.tag__dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 8px currentColor;
    animation: dot-pulse 2.4s var(--ease-soft) infinite;
}

@keyframes dot-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.45; transform: scale(0.8); }
}

.panel__name {
    font-size: clamp(1.15rem, 1rem + 0.7vw, 1.5rem);
    font-weight: 700;
    font-variation-settings: 'wdth' 104;
    letter-spacing: -0.018em;
    line-height: 1.2;
    color: var(--ink);
    text-wrap: balance;
}

.panel__host {
    display: block;
    margin-top: 0.4rem;
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 400;
    letter-spacing: 0.02em;
    color: var(--phosphor-dim);
    overflow-wrap: anywhere;
}

.panel__desc {
    margin-top: 0.85rem;
    max-width: 52ch;
    font-size: 0.925rem;
    line-height: 1.7;
    color: var(--ink-2);
    text-wrap: pretty;
}

/* --- Feature panel: identity on the left, breadth on the right --- */
.panel--feature {
    gap: clamp(1.4rem, 3vw, 2.6rem);
}

.panel--feature .panel__name {
    font-size: clamp(1.4rem, 1.1rem + 1.2vw, 1.95rem);
}

.panel--feature .panel__desc {
    font-size: 0.97rem;
}

.feature__main {
    display: flex;
    flex-direction: column;
}

.feature__aside {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.feature__caption {
    display: block;
    margin-bottom: 0.75rem;
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--ink-3);
}

@media (min-width: 720px) {
    /* Two columns, two rows: copy above its CTA on the left, breadth on the
       right spanning both. Stacked, the DOM order already reads correctly. */
    .panel--feature {
        display: grid;
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
        grid-template-rows: 1fr auto;
    }

    .feature__main { grid-area: 1 / 1; }
    .feature__go { grid-area: 2 / 1; align-self: end; }

    /* Stretches across both rows so its hairline runs the panel's full
       height and the chips stay optically centred against the copy. */
    .feature__aside { grid-area: 1 / 2 / span 2 / 2; }

    /* Pin the badge to the panel's own top-right rather than letting it
       drift to the inner column's edge, where it reads as unattached. */
    .panel--feature .panel__top {
        display: block;
    }

    .panel--feature .panel__top .tag {
        position: absolute;
        top: clamp(1.35rem, 2.6vw, 1.85rem);
        right: clamp(1.35rem, 2.6vw, 1.85rem);
    }

    /* Hairline gutter between the two halves. */
    .feature__aside::before {
        content: '';
        position: absolute;
        top: 0;
        bottom: 0;
        left: calc(clamp(1.4rem, 3vw, 2.6rem) / -2);
        width: 1px;
        background: linear-gradient(180deg,
            transparent,
            var(--line-warm) 22%,
            var(--line-warm) 78%,
            transparent);
    }
}

/* Topic chips — only the archive has enough breadth to need them. */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    list-style: none;
}

.chips li {
    padding: 0.24rem 0.55rem;
    border: 1px solid var(--line);
    border-radius: 5px;
    background: oklch(0.115 0.008 240 / 0.55);
    font-family: var(--font-mono);
    font-size: 0.57rem;
    font-weight: 400;
    letter-spacing: 0.05em;
    color: var(--ink-3);
    transition: color 0.35s var(--ease), border-color 0.35s var(--ease);
}

.panel:hover .chips li {
    color: var(--ink-2);
    border-color: var(--line-warm);
}

.panel__go {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    margin-top: 1.35rem;
    font-family: var(--font-mono);
    font-size: 0.63rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--phosphor);
}

.panel__go svg {
    width: 13px;
    height: 13px;
    transition: transform 0.4s var(--ease);
}

.panel:hover .panel__go svg {
    transform: translate(3px, -3px);
}

/* In the feature panel the CTA sits on the floor, not under the copy. */
.panel--feature .panel__go {
    margin-top: auto;
    padding-top: 1.35rem;
}

/* ============================================================
   TOOLS — deliberately not cards. Ruled rows, closer to an index.
   ============================================================ */

.tools {
    border-top: 1px solid var(--line);
}

.tool {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: clamp(0.9rem, 2vw, 1.35rem);
    padding: clamp(1.15rem, 2.4vw, 1.5rem) clamp(0.4rem, 1.2vw, 0.85rem);
    border-bottom: 1px solid var(--line);
    transition: background 0.35s var(--ease);
}

.tool:hover,
.tool:focus-visible {
    background: linear-gradient(90deg,
        oklch(0.72 0.15 240 / 0.05),
        transparent 70%);
}

.tool__icon {
    width: 38px;
    height: 38px;
    margin-top: 2px;
    color: var(--case);
    transition: color 0.35s var(--ease), transform 0.45s var(--ease);
}

.tool:hover .tool__icon {
    color: var(--phosphor);
    transform: translateY(-2px);
}

.tool__name {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 0.7rem;
    font-size: 1.05rem;
    font-weight: 650;
    font-variation-settings: 'wdth' 102;
    letter-spacing: -0.012em;
    color: var(--ink);
}

.tool__host {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 400;
    letter-spacing: 0.02em;
    color: var(--phosphor-dim);
    overflow-wrap: anywhere;
}

.tool__desc {
    margin-top: 0.5rem;
    max-width: 62ch;
    font-size: 0.875rem;
    line-height: 1.65;
    color: var(--ink-2);
    text-wrap: pretty;
}

.tool__arrow {
    width: 18px;
    height: 18px;
    margin-top: 12px;
    color: var(--ink-3);
    transition: color 0.35s var(--ease), transform 0.4s var(--ease);
}

.tool:hover .tool__arrow {
    color: var(--phosphor);
    transform: translate(3px, -3px);
}

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

    .tool__arrow {
        display: none;
    }
}

/* ============================================================
   ELSEWHERE — icon row with hover/focus detail cards
   ============================================================ */

.elsewhere {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(0.7rem, 2vw, 1.1rem);
}

.spot {
    position: relative;
    display: grid;
    place-items: center;
    width: 58px;
    height: 58px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: oklch(0.205 0.01 240 / 0.75);
    color: var(--ink-2);
    transition:
        color 0.35s var(--ease),
        border-color 0.35s var(--ease),
        transform 0.4s var(--ease),
        box-shadow 0.4s var(--ease);
}

.spot:hover,
.spot:focus-visible {
    transform: translateY(-4px);
    border-color: oklch(0.72 0.15 240 / 0.4);
    color: var(--phosphor);
    box-shadow: 0 10px 26px -14px oklch(0 0 0 / 0.9),
        0 0 22px -10px var(--glow-soft);
}

.spot svg {
    width: 26px;
    height: 26px;
}

/* Opens downward: the icon row sits directly under its heading, and a
   card above would cover it every time. */
.spot__card {
    position: absolute;
    top: calc(100% + 12px);
    left: 50%;
    z-index: var(--z-tooltip);
    width: max-content;
    max-width: min(15rem, 62vw);
    translate: -50% -6px;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--line-warm);
    border-radius: var(--radius-sm);
    background: oklch(0.115 0.008 240 / 0.97);
    box-shadow: 0 14px 34px -16px oklch(0 0 0 / 0.95);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition:
        opacity 0.28s var(--ease),
        translate 0.28s var(--ease),
        visibility 0.28s;
}

.spot:hover .spot__card,
.spot:focus-visible .spot__card {
    opacity: 1;
    visibility: visible;
    translate: -50% 0;
}

.spot__title {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--phosphor);
}

.spot__desc {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--ink-2);
    text-wrap: pretty;
}

/* Cards are centred on their icon, which pushes the outermost two past the
   gutter on a phone. Anchor those to the row's edges instead. Hidden cards
   still contribute to scrollWidth, so this matters even before hover. */
.elsewhere > :first-child .spot__card {
    left: 0;
    translate: 0 -6px;
}

.elsewhere > :last-child .spot__card {
    left: auto;
    right: 0;
    translate: 0 -6px;
}

.elsewhere > :first-child:hover .spot__card,
.elsewhere > :first-child:focus-visible .spot__card,
.elsewhere > :last-child:hover .spot__card,
.elsewhere > :last-child:focus-visible .spot__card {
    translate: 0 0;
}

/* ============================================================
   FOOTER
   ============================================================ */

.footer {
    margin-top: clamp(1.75rem, 4vw, 2.75rem);
    padding-block: clamp(1.5rem, 3vw, 2rem) clamp(2rem, 5vw, 3rem);
    border-top: 1px solid var(--line);
}

.footer__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem 1.5rem;
}

.footer__nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0 0.5rem;
    margin-inline: -0.5rem;
    list-style: none;
}

/* Padded to a 24px-tall hit area — the label alone is only ~12px. */
.footer__nav a {
    display: inline-block;
    padding: 0.4rem 0.5rem;
    font-family: var(--font-mono);
    font-size: 0.64rem;
    letter-spacing: 0.05em;
    color: var(--ink-3);
    transition: color 0.3s var(--ease);
}

.footer__nav a:hover {
    color: var(--phosphor);
}

.footer__legal {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    color: var(--ink-3);
}

/* ============================================================
   ENTRANCE
   Content is visible by default; the animation only offsets it.
   If the script never runs (or JS is off), nothing is hidden.
   ============================================================ */

.js .reveal {
    opacity: 0;
    transform: translateY(14px);
}

.js .reveal.is-in {
    opacity: 1;
    transform: none;
    transition:
        opacity 0.7s var(--ease-soft) var(--reveal-delay, 0s),
        transform 0.7s var(--ease) var(--reveal-delay, 0s);
}

/* ============================================================
   REDUCED MOTION
   Everything resolves to its end state; nothing loops.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }

    .crt-refresh,
    .crt-dust,
    .cursor-glow {
        display: none;
    }

    .lockup__mark {
        animation: none;
        filter: drop-shadow(0 0 26px var(--glow-soft));
    }

    .prompt__caret {
        animation: none;
        opacity: 1;
    }

    .panel:hover,
    .spot:hover,
    .spot:focus-visible {
        transform: none;
    }

    .js .reveal {
        opacity: 1;
        transform: none;
    }
}
