/* ==========================================================================
   /clanning — SERVICE RECORD

   The page does not scroll. The record is a drum of entries turning on a
   horizontal axis in front of the viewer, and the wheel drives its angle.
   Everything else is a hairline: two rails, one gauge, no boxes, no cards.

   Layers, back to front:
     #void       WebGL — the figure, its orbiting emblems, drifting dust
     #stage      the drum, in CSS 3D, and the gauge beside it
     #vignette   sinks the corners
     #grain      film
     rails       masthead and status
   ========================================================================== */

:root {
    --void: #050405;
    --bone: #ece7de;
    --dim: #6b635e;
    --deep: #453d41;
    --faint: #221d20;
    --crimson: #b21620;
    --gold: #c9a227;

    --ease: cubic-bezier(0.22, 0.8, 0.18, 1);
    --pad-x: clamp(1.25rem, 5vw, 5rem);
    --pad-y: clamp(1.1rem, 2.4vw, 1.8rem);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}

body {
    background: var(--void);
    color: var(--bone);
    font-family: 'Inter', system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

::selection { background: var(--crimson); color: var(--bone); }

/* ---------- the void ---------------------------------------------------- */

#void {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    z-index: 0;
}

/* The flat Roblox render stands in wherever the mesh cannot: no WebGL, or no
   Studio export on disk. The page adds .flat when that happens. */
#figure-still {
    position: fixed;
    top: 50%;
    left: 73.5%;
    width: min(30vw, 30vh);
    transform: translate(-50%, -50%);
    opacity: 0;
    filter: grayscale(0.35) contrast(1.05) drop-shadow(0 0 60px rgba(178, 22, 32, 0.45));
    transition: opacity 1.2s var(--ease);
    z-index: 1;
    pointer-events: none;
}

body.flat #figure-still { opacity: 0.9; }

/* The type has to win. This pours the void back over the half of the screen it
   occupies, so the figure stays a presence rather than a background image. */
#scrim {
    position: fixed;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(to right,
            var(--void) 0%,
            rgba(5, 4, 5, 0.92) 26%,
            rgba(5, 4, 5, 0.55) 44%,
            rgba(5, 4, 5, 0) 62%);
}

#vignette {
    position: fixed;
    inset: 0;
    z-index: 7;
    pointer-events: none;
    background:
        radial-gradient(125% 95% at 50% 50%, transparent 38%, rgba(0, 0, 0, 0.62) 100%);
}

#grain {
    position: fixed;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    z-index: 8;
    pointer-events: none;
    opacity: 0.05;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='300' height='300'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 300px 300px;
    animation: grain 1.1s steps(5) infinite;
    will-change: transform;
}

@keyframes grain {
    0%   { transform: translate3d(0, 0, 0); }
    20%  { transform: translate3d(-3%, -4%, 0); }
    40%  { transform: translate3d(2%, -2%, 0); }
    60%  { transform: translate3d(-1%, 3%, 0); }
    80%  { transform: translate3d(4%, 1%, 0); }
    100% { transform: translate3d(0, 0, 0); }
}

/* ---------- rails ------------------------------------------------------- */

.rail {
    position: fixed;
    left: 0;
    right: 0;
    z-index: 6;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1.5rem;
    padding: var(--pad-y) var(--pad-x);
    font-size: 0.615rem;
    font-weight: 500;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--dim);
}

.rail--top { top: 0; }
.rail--bot { bottom: 0; }

/* Hairlines inset to the same gutter as everything else. */
.rail::after {
    content: "";
    position: absolute;
    left: var(--pad-x);
    right: var(--pad-x);
    height: 1px;
    background: var(--faint);
}

.rail--top::after { bottom: 0; }
.rail--bot::after { top: 0; }

.mark {
    color: var(--bone);
    text-decoration: none;
    transition: color 0.25s var(--ease);
}

.mark span { color: var(--dim); }
.mark:hover { color: var(--crimson); }

.rail-mid {
    flex: 1;
    text-align: center;
    color: var(--dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rail-end {
    color: var(--gold);
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 34vw;
}

.counter {
    font: inherit;
    background: none;
    border: 0;
    padding: 0;
    color: var(--bone);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.25s var(--ease);
}

.counter:hover { color: var(--crimson); }
.counter em { font-style: normal; color: var(--dim); }

.hint {
    display: flex;
    align-items: baseline;
    gap: 1.1rem;
    white-space: nowrap;
    overflow: hidden;
}

.hint > span { display: inline-flex; gap: 0.4rem; align-items: baseline; }
.hint-act.no-act { display: none; }

.hint kbd {
    font: inherit;
    color: var(--bone);
    border-bottom: 1px solid var(--faint);
    padding-bottom: 1px;
}

.hint i { font-style: normal; }

#typed {
    color: var(--crimson);
    min-width: 0;
    max-width: 12ch;
    overflow: hidden;
    letter-spacing: 0.2em;
}

#typed:not(:empty) { margin-right: 0.4rem; }

/* ---------- stage ------------------------------------------------------- */

#stage {
    position: fixed;
    inset: 0;
    z-index: 3;
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    align-items: center;
    gap: clamp(1.1rem, 2.6vw, 2.6rem);
    padding: 0 var(--pad-x);
    cursor: crosshair;
    touch-action: none;

    /* Entries dissolve into the void instead of hitting the rails. */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22%, #000 80%, transparent 100%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 22%, #000 80%, transparent 100%);
}

#stage.is-dragging { cursor: grabbing; }

/* ---------- gauge ------------------------------------------------------- */

.gauge {
    position: relative;
    width: 30px;
    height: min(56vh, 470px);
}

.gauge-line {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: linear-gradient(to bottom, transparent, var(--faint) 12%, var(--faint) 88%, transparent);
}

.gauge-ticks i {
    position: absolute;
    left: 0;
    width: 7px;
    height: 1px;
    background: var(--faint);
    transform-origin: left center;
    transition: width 0.45s var(--ease), background-color 0.45s var(--ease);
}

/* The first entry of each section gets a longer tick, so the record's shape
   is readable before you have turned through any of it. */
.gauge-ticks i { background: #2e282c; }
.gauge-ticks i.sec { width: 15px; background: var(--deep); }
.gauge-ticks i.on  { width: 26px; background: var(--crimson); }

.gauge-head {
    position: absolute;
    left: -1px;
    top: 0;
    width: 3px;
    height: 15px;
    margin-top: -7px;
    background: var(--bone);
}

/* ---------- the drum ---------------------------------------------------- */

.reel-col {
    position: relative;
    width: min(100%, 44rem);
    height: min(78vh, 660px);
    perspective: var(--perspective, 1400px);
    perspective-origin: 50% 50%;
}

.reel {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
}

.slot {
    position: absolute;
    left: 0;
    top: 50%;
    width: 100%;
    height: 104px;
    margin-top: -52px;
    display: flex;
    align-items: center;
    gap: clamp(0.8rem, 1.6vw, 1.5rem);
    transform-origin: 50% 50%;
    backface-visibility: hidden;
    will-change: transform, opacity;
}

.slot-idx {
    flex: none;
    width: 2.4ch;
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    color: var(--faint);
    font-variant-numeric: tabular-nums;
    transition: color 0.5s var(--ease);
    align-self: flex-start;
    padding-top: 0.45rem;
}

.slot-body {
    position: relative;
    min-width: 0;
    padding-bottom: 0.55rem;
}

/* A hairline that draws itself under whatever is in focus. */
.slot-body::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 1px;
    width: 0;
    background: linear-gradient(to right, var(--crimson), rgba(178, 22, 32, 0));
    transition: width 0.65s var(--ease);
}

.slot-sub {
    display: block;
    font-size: 0.575rem;
    font-weight: 500;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--deep);
    margin-bottom: 0.32rem;
    transition: color 0.5s var(--ease);
}

.slot-name {
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 600;
    font-size: clamp(1.05rem, 2.15vw, 1.85rem);
    line-height: 1.06;
    letter-spacing: 0.045em;
    text-transform: uppercase;
    text-wrap: balance;
    color: var(--deep);
    transition: color 0.5s var(--ease);
}

.slot-meta {
    display: block;
    margin-top: 0.42rem;
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--dim);
    opacity: 0;
    transform: translateY(3px);
    transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}

.slot.is-focus .slot-idx { color: var(--crimson); }
.slot.is-focus .slot-sub { color: var(--gold); }
.slot.is-focus .slot-name { color: var(--bone); }
.slot.is-focus .slot-meta { opacity: 1; transform: none; }
.slot.is-focus .slot-body::after { width: 100%; }

/* Only the entry in focus is a target; the rest just turn past. */
.slot:not(.is-focus):hover .slot-name { color: var(--dim); }

.slot--identity .slot-name { font-size: clamp(1.5rem, 3.4vw, 3rem); letter-spacing: 0.14em; }
.slot--link .slot-name { letter-spacing: 0.2em; }

/* Chromatic split, scaled by how fast the drum is turning. The page writes
   --split in pixels; at rest it is zero and this costs nothing. */
.slot.is-focus .slot-name {
    text-shadow:
        calc(var(--split, 0px) * -1) 0 rgba(178, 22, 32, 0.55),
        var(--split, 0px) 0 rgba(70, 170, 210, 0.35);
}

.live {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}

/* ---------- index ------------------------------------------------------- */

.index {
    position: fixed;
    inset: 0;
    z-index: 20;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: rgba(5, 4, 5, 0.94);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    animation: indexIn 0.4s var(--ease);
}

.index[hidden] { display: none; }

@keyframes indexIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.index-inner {
    max-width: 52rem;
    margin: 0 auto;
    padding: clamp(3rem, 9vh, 6rem) var(--pad-x) 6rem;
}

.index h2 {
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 600;
    font-size: 0.68rem;
    letter-spacing: 0.34em;
    text-transform: uppercase;
    color: var(--dim);
    margin-bottom: 1.6rem;
}

.index ol { list-style: none; }

.index li {
    position: relative;
    border-bottom: 1px solid var(--faint);
}

.index li.sec-start { margin-top: 2.2rem; }

.index li.sec-start::before {
    content: attr(data-section);
    display: block;
    font-size: 0.575rem;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--crimson);
    padding-bottom: 0.7rem;
}

.index button.row {
    display: grid;
    grid-template-columns: 3ch minmax(0, 1fr) minmax(0, 17rem);
    align-items: baseline;
    gap: 1.2rem;
    width: 100%;
    padding: 0.85rem 0;
    background: none;
    border: 0;
    text-align: left;
    color: inherit;
    font: inherit;
    cursor: pointer;
    outline: none;
}

/* The entry the drum is currently parked on, so the index says where you are
   as well as where you can go. */
.index li.here .row-idx { color: var(--crimson); }
.index li.here .row-name { color: var(--crimson); }
.index li.here::after {
    content: "";
    position: absolute;
    left: -1.1rem;
    top: 50%;
    width: 0.55rem;
    height: 1px;
    background: var(--crimson);
}

.index button.row:focus-visible {
    outline: 1px solid var(--crimson);
    outline-offset: 3px;
}

.index .row-idx {
    font-size: 0.6rem;
    color: var(--faint);
    font-variant-numeric: tabular-nums;
}

.index .row-name {
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 500;
    font-size: 0.98rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--bone);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: color 0.2s var(--ease);
}

.index .row-meta {
    font-size: 0.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--dim);
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.index button.row:hover .row-name,
.index button.row:focus-visible .row-name { color: var(--crimson); }

#index-close {
    margin-top: 2.5rem;
    background: none;
    border: 1px solid var(--faint);
    color: var(--dim);
    font: inherit;
    font-size: 0.6rem;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    padding: 0.7rem 1.6rem;
    cursor: pointer;
    transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

#index-close:hover { border-color: var(--crimson); color: var(--bone); }

/* ---------- boot -------------------------------------------------------- */

#boot {
    position: fixed;
    inset: 0;
    z-index: 30;
    background: var(--void);
    display: grid;
    place-items: center;
    transition: opacity 0.9s var(--ease);
}

#boot.out {
    opacity: 0;
    pointer-events: none;
}

.boot-inner {
    width: min(70vw, 44rem);
    text-align: left;
}

.boot-line {
    display: block;
    height: 1px;
    background: linear-gradient(to right, var(--crimson), var(--faint));
    transform: scaleX(0);
    transform-origin: left center;
    animation: bootLine 0.75s var(--ease) forwards;
}

@keyframes bootLine {
    to { transform: scaleX(1); }
}

.boot-name {
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 600;
    font-size: clamp(1.9rem, 7vw, 4.4rem);
    letter-spacing: 0.28em;
    text-transform: uppercase;
    line-height: 1.1;
    color: var(--bone);
    margin-top: 1.1rem;
}

.boot-sub {
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--dim);
    margin-top: 0.5rem;
    min-height: 1em;
}

/* Everything behind the boot screen arrives together, once. */
#stage, .rail, #void, #figure-still { transition: opacity 1.1s var(--ease), transform 1.1s var(--ease), filter 1.1s var(--ease); }

body:not(.ready) #stage {
    opacity: 0;
    transform: scale(0.93);
    filter: blur(7px);
}

body:not(.ready) .rail { opacity: 0; }
body:not(.ready) #void { opacity: 0; }

/* ---------- no script --------------------------------------------------- */

.fallback {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: var(--void);
    display: grid;
    align-content: center;
    gap: 1rem;
    padding: var(--pad-x);
    font-size: 0.85rem;
    line-height: 1.7;
    color: var(--dim);
}

.fallback h1 {
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 600;
    font-size: 1.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bone);
}

.fallback a { color: var(--gold); }

/* ---------- narrow ------------------------------------------------------ */

@media (max-width: 760px) {
    #stage {
        grid-template-columns: 14px minmax(0, 1fr);
        gap: 0.9rem;
        align-items: end;
        padding-bottom: 12vh;
    }

    /* No room beside the type here — the figure moves above it and the scrim
       goes flat, so the drum reads against the void rather than against armour. */
    #scrim {
        background: linear-gradient(to bottom,
                rgba(5, 4, 5, 0.25) 0%,
                rgba(5, 4, 5, 0.55) 34%,
                rgba(5, 4, 5, 0.9) 52%,
                var(--void) 70%);
    }

    .slot-idx { display: none; }

    .gauge { width: 16px; height: min(50vh, 380px); }
    .gauge-ticks i { width: 5px; }
    .gauge-ticks i.sec { width: 10px; }
    .gauge-ticks i.on { width: 16px; }

    .reel-col { height: min(72vh, 520px); }
    .slot { height: 84px; margin-top: -42px; }

    #figure-still { left: 50%; width: min(52vw, 34vh); }
    body.flat #figure-still { opacity: 0.32; }

    .rail-end { display: none; }
    .hint > span { display: none; }
    .hint::after { content: "swipe · tap to open"; }
}

@media (max-width: 460px) {
    .rail-mid { text-align: right; }
}

/* ---------- reduced motion ---------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    #grain { animation: none; }
    .boot-line { animation: none; transform: scaleX(1); }

    #stage, .rail, #void, .slot, .slot-body::after, .slot-meta, .gauge-ticks i {
        transition-duration: 0.01ms !important;
    }
}
