/*!
 * ss-sim.css  v1.0.0
 * Shared chrome for every simulation page on seriouslyscientific.com
 * (/voyager/, /solar-eclipse-2026/, /moon-phase/, and whatever comes next).
 *
 * WHY THIS FILE EXISTS
 *   Before it, three simulation pages each reinvented the same 24
 *   concepts under their own prefix (ecl-, vg-, mn-). Measured drift
 *   across those shared concepts: only .container and .live-dot were
 *   byte-identical. .btn differed on 15 of 15 properties, .module on
 *   11 of 11, .telemetry on 10 of 10, .controls and .link-card on 9 of
 *   9. Three answers to every question and no source of truth. Fixing
 *   the button treatment or the missing gap above the module meant
 *   three edits and would have meant four with the next simulation.
 *
 * HOW IT IS MEANT TO BE USED
 *   Structure lives here, colour does not. Every page sets its own
 *   tokens on its own wrapper, so Moon can be cold black and turquoise
 *   while Voyager and Eclipse stay warm, with no structural fork.
 *   Load order: seriously-scientific-style, then ss-sim, then the
 *   page file for genuinely unique parts only.
 *
 * IDs ARE DELIBERATELY UNTOUCHED
 *   voyager.js and eclipse.js hook almost entirely on prefixed IDs
 *   (vg-module, ecl-canvas and so on), so those stay exactly as they
 *   are and the scripts keep working. Only two class selectors in the
 *   live scripts need updating alongside this file:
 *     voyager.js  .vg-tl-item  -> .ss-sim-tl-item
 *                 vg-visible   -> is-visible
 *     eclipse.js  .ecl-info    -> .ss-sim-info
 *
 * NOT AN EM DASH IN SIGHT, PER HOUSE STYLE.
 */

/* ================================================================
   TOKENS
   Defaults are the cold palette. A page overrides any of these on
   its own wrapper; nothing below hard-codes a brand colour.
   ================================================================ */

.ss-sim {
    /* Blue and yellow across every simulation. Blue reads as
       navigation, links and the live signal; yellow as interactive
       state. On the warm pages this deliberately contrasts against the
       Cosmic Rust background rather than blending into it, which is
       what an orange control on an orange page did.
       Orange remains page identity: backgrounds, frames, section
       kickers. It is simply not the control colour. */
    --sim-accent:        var(--nebula-turquoise, #4A9FD4);
    --sim-link:          var(--nebula-turquoise, #4A9FD4);
    --sim-live:          var(--nebula-turquoise, #4A9FD4);
    --sim-frame:         250, 219, 103;      /* rgb triplet, site yellow */
    --sim-active:        var(--highlight-yellow, #fadb67);
    --sim-text:          var(--starlight, #F7FAFC);
    --sim-text-muted:    var(--starlight-muted, #E2E8F0);
    --sim-dim:           #9AA7B2;
    --sim-dim-bright:    #C9D3DA;
    --sim-module-bg:     #000;
    --sim-card-bg:       rgba(20, 20, 24, .5);
    --sim-card-border:   rgba(154, 167, 178, .3);
    --sim-rule:          rgba(154, 167, 178, .22);
    --sim-spine-from:    var(--sim-accent);
    --sim-spine-to:      rgba(154, 167, 178, .25);

    --sim-shadow:        0 1px 12px rgba(0, 0, 0, .92);
    --sim-shadow-strong:
        0 0 3px rgba(0, 0, 0, 1),
        0 0 7px rgba(0, 0, 0, .98),
        0 1px 4px rgba(0, 0, 0, 1),
        0 2px 22px rgba(0, 0, 0, .9);

    display: block;
}

/* ================================================================
   THE MODULE
   ================================================================ */

/* The gap above the module.
   header.php ends by opening <main class="site-main">, and style.css
   sets .site-main { padding-top: 0 } explicitly. Regular pages get
   their breathing room from .main-content-new, which simulation pages
   do not use, so without this rule the module butts straight into the
   header. Visible on Voyager and Eclipse today, not just Moon. */
.ss-sim .ss-sim-module {
    position: relative;
    width: 100%;
    max-width: var(--content-w, 1320px);
    margin: 1.5rem auto 2rem;
    overflow: hidden;
    height: clamp(600px, 88vh, 760px);
    border-radius: 14px;
    background: var(--sim-module-bg);
    isolation: isolate;
    /* Faint yellow trace: the quieter sibling of the retro-tv.css
       treatment. Same yellow so the simulations read as part of the
       same site, but a 1px ring and a short bloom rather than the
       TV's 2px ring and 70px halo, which overpowers a full-bleed
       render. */
    box-shadow:
        0 0 0 1px rgba(var(--sim-frame), .55),
        0 0 14px rgba(var(--sim-frame), .12);
}

.ss-sim .ss-sim-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    z-index: 0;
    touch-action: none;
}

.ss-sim .ss-sim-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 2.75rem 1.25rem 0;
    pointer-events: none;
}

.ss-sim .ss-sim-overlay > * { pointer-events: auto; }
.ss-sim .ss-sim-head { width: 100%; max-width: 780px; }

/* ---- kicker ---- */

.ss-sim .ss-sim-kicker {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem 1rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, .55);
    border: 1px solid var(--sim-live);
    color: var(--sim-dim-bright);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .22em;
    text-transform: uppercase;
}

.ss-sim .ss-sim-live-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--sim-live);
    animation: ss-sim-pulse 2.4s ease-in-out infinite;
}

@keyframes ss-sim-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .35; transform: scale(.7); }
}

/* ---- titles ---- */

.ss-sim .ss-sim-title {
    margin: 1rem 0 .5rem;
    font-family: 'Space Grotesk', sans-serif;
    font-size: clamp(1.9rem, 5.6vw, 3.3rem);
    font-weight: 700;
    letter-spacing: .12em;
    line-height: 1.05;
    color: var(--sim-text);
    text-transform: uppercase;
    text-shadow: 0 0 4px rgba(0, 0, 0, .95), 0 2px 24px rgba(0, 0, 0, .85);
}

.ss-sim .ss-sim-sub {
    margin: 0;
    font-size: clamp(.85rem, 2.4vw, 1.05rem);
    color: var(--sim-text-muted);
    text-shadow: var(--sim-shadow-strong);
}

/* ---- live / simulated stamp ----
   The honesty convention, shared: when a module is showing anything
   other than right now, it says so rather than blurring the two. */
.ss-sim .ss-sim-stamp {
    display: block;
    text-shadow: var(--sim-shadow-strong);
    /* Bottom margin matters in fullscreen, where the subtitle is
       hidden and this would otherwise sit right on the buttons. */
    margin: .45rem 0 1.1rem;
    font-size: .64rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--sim-dim);
}

.ss-sim .ss-sim-module.is-simulated .ss-sim-stamp { color: var(--sim-active); }

/* ================================================================
   COUNTDOWN
   Voyager and Eclipse both count toward a single instant, and future
   celestial-event simulations will too. Cells are tokenised so a warm
   page and a cold page can share the structure.
   ================================================================ */

.ss-sim .ss-sim-count-label {
    margin: 1.2rem 0 .6rem;
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--sim-text-muted);
    text-shadow: var(--sim-shadow);
}

.ss-sim .ss-sim-countdown {
    display: grid;
    grid-template-columns: repeat(4, minmax(64px, 118px));
    gap: .55rem;
    font-variant-numeric: tabular-nums;
    justify-content: center;
    margin: 0 auto;
}

.ss-sim .ss-sim-cell {
    background: var(--sim-card-bg);
    border: 1px solid var(--sim-card-border);
    border-radius: 10px;
    padding: .65rem .35rem .55rem;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.ss-sim .ss-sim-num {
    display: block;
    font-family: 'Space Grotesk', sans-serif;
    font-size: clamp(1.65rem, 6.2vw, 3.1rem);
    font-weight: 700;
    line-height: 1;
    color: var(--sim-text);
}

.ss-sim .ss-sim-unit {
    display: block;
    margin-top: .3rem;
    font-size: .6rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sim-dim);
}

.ss-sim .ss-sim-instant {
    margin: .9rem 0 0;
    font-size: .78rem;
    line-height: 1.7;
    color: var(--sim-dim);
    text-shadow: var(--sim-shadow);
}

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

/* ================================================================
   TELEMETRY
   ================================================================ */

.ss-sim .ss-sim-panel {
    margin-top: auto;
    width: 100%;
    max-width: 640px;
    /* Enough clearance for the credit line, which sits absolutely at
       the foot of the frame, plus the hide button now under the
       readout. Was 1.6rem and everything was touching. */
    padding: 0 0 4.75rem;
}

.ss-sim .ss-sim-telemetry {
    /* Was 560px, which left a gulf between label and value on pages
       with only two rows. Values stay right-aligned (space-between on
       the row) because a column of right-aligned numbers is what makes
       a readout scannable; the box simply no longer overreaches. */
    max-width: 460px;
    margin: 0 auto;
    box-shadow: 0 2px 16px rgba(0, 0, 0, .6);
    border-top: 1px solid var(--sim-rule);
    background: rgba(0, 0, 0, .4);
    border-radius: 10px;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.ss-sim .ss-sim-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .55rem .9rem;
    border-bottom: 1px solid var(--sim-rule);
}

.ss-sim .ss-sim-row:last-child { border-bottom: 0; }

.ss-sim .ss-sim-row-label {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--sim-text-muted);
    text-align: left;
}

.ss-sim .ss-sim-value {
    font-size: clamp(.85rem, 2.6vw, 1.02rem);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    /* Readings are text, not controls. Keeping them light rather than
       blue is what takes the blue down without losing it: blue now
       marks only the things you can actually click or follow. */
    color: var(--sim-text);
}

.ss-sim .ss-sim-suffix {
    margin-left: .25rem;
    font-size: .72em;
    color: var(--sim-text-muted);
}

.ss-sim .ss-sim-info {
    width: 17px;
    height: 17px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(226, 232, 240, .4);
    background: transparent;
    color: var(--sim-text-muted);
    font-size: .62rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color .2s, color .2s;
}

.ss-sim .ss-sim-info:hover,
.ss-sim .ss-sim-info:focus-visible {
    border-color: var(--sim-active);
    color: var(--sim-active);
}

.ss-sim .ss-sim-note {
    display: none;
    margin: 0;
    padding: 0 .9rem .7rem;
    font-size: .75rem;
    line-height: 1.6;
    text-align: left;
    color: var(--sim-dim-bright);
}

.ss-sim .ss-sim-note.is-open { display: block; }

/* ================================================================
   CONTROLS
   Labelled, not bare icons. A lone unlabelled circle in a corner does
   not read as anything. Primary actions sit centred under the render,
   view actions stay in the corner.
   ================================================================ */

.ss-sim .ss-sim-actions {
    display: flex;
    justify-content: center;
    gap: .6rem;
    flex-wrap: wrap;
    margin: 0 0 1rem;
}

/* View controls: centred beneath the readout, and deliberately
   lighter than the action row above it. Controls above the data change
   what the simulation is doing; controls below change how you are
   looking at it. Two tiers of equal weight would compete, so this row
   is smaller and quieter. */
.ss-sim .ss-sim-controls {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin: 1.1rem 0 0;
}

.ss-sim .ss-sim-controls .ss-sim-btn {
    padding: .42rem .85rem;
    font-size: .72rem;
    background: rgba(0, 0, 0, .45);
}

.ss-sim .ss-sim-controls .ss-sim-btn svg { width: 13px; height: 13px; }

.ss-sim .ss-sim-btn {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .55rem 1rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, .6);
    border: 1px solid var(--sim-accent);
    color: var(--sim-accent);
    font-size: .78rem;
    font-weight: 500;
    letter-spacing: .06em;
    cursor: pointer;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    /* These sit over the render, which on a full Moon is close to
       white. Without a shadow the outline and label were being lost
       into it entirely. */
    box-shadow: 0 2px 10px rgba(0, 0, 0, .75);
    text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
    transition: background .2s, border-color .2s, color .2s;
}

/* Hover fills solid, whatever the state. A faint tint was too easy to
   miss, and it meant hovering an already-active button did nothing at
   all, since active and hover both painted the same yellow outline. */
.ss-sim .ss-sim-btn:hover,
.ss-sim .ss-sim-btn:focus-visible {
    background: var(--sim-active);
    border-color: var(--sim-active);
    color: #1A0C08;
}



/* Active state: outline and text go yellow, background stays dark.
   Deliberately not a solid fill, which read as heavy against the
   render. Yellow matches the in-lesson interactable convention
   rather than the navigation blue. */
.ss-sim .ss-sim-btn[aria-pressed="true"] {
    border-color: var(--sim-active);
    color: var(--sim-active);
    background: rgba(var(--sim-frame), .1);
}

/* Three states: resting blue outline, active yellow outline, and any
   hover solid yellow. */

.ss-sim .ss-sim-btn svg { width: 15px; height: 15px; flex: none; }

/* Hide readout sits directly under the readout it acts on, rather
   than parked in the corner beside Fullscreen. Proximity does the
   explaining: in the corner the label had to carry the whole meaning,
   and it grouped two controls that do quite unrelated jobs. */
.ss-sim .ss-sim-hide-row {
    display: flex;
    justify-content: center;
    margin: 1.75rem 0 0;
}

/* Controls that only earn their place at full size. Hidden in the
   normal view so it stays the tidy row it was. */
.ss-sim .ss-sim-fs-only { display: none; }
.ss-sim .ss-sim-module:fullscreen .ss-sim-fs-only,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-fs-only { display: inline-flex; }
.ss-sim .ss-sim-btn-label { white-space: nowrap; }

/* A brief yellow flash so a momentary action such as reset gives
   feedback even though it has no lasting on state. */
.ss-sim .ss-sim-btn.is-flash {
    animation: ss-sim-flash .45s ease;
}

@keyframes ss-sim-flash {
    0%   { border-color: var(--sim-active); color: var(--sim-active); background: rgba(var(--sim-frame), .3); }
    100% { border-color: var(--sim-accent); color: var(--sim-accent); background: rgba(0, 0, 0, .6); }
}

/* ---- hint and credit ---- */

.ss-sim .ss-sim-hint,
.ss-sim .ss-sim-credit {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 3;
    margin: 0;
    text-align: center;
    font-size: .62rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sim-dim);
    text-shadow: var(--sim-shadow);
}

.ss-sim .ss-sim-hint   {
    top: 12px;
    /* Was unreadable over a bright Moon: this line sits at the very top
       of the frame where the render can be near-white, and it had no
       shadow of its own. */
    text-shadow: var(--sim-shadow-strong);
}
.ss-sim .ss-sim-credit { bottom: 14px; }

/* ================================================================
   FULLSCREEN
   At full size the framing copy has done its job and only gets in the
   way of the thing people went fullscreen to look at. Title, subtitle
   and kicker step back, the telemetry drops to the foot of the frame,
   and the render gets the middle.
   ================================================================ */

.ss-sim .ss-sim-module:fullscreen,
.ss-sim .ss-sim-module:-webkit-full-screen {
    max-width: none;
    height: 100vh;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
}

/* Nothing is hidden at full size. An earlier version stripped the
   kicker, subtitle and credit and shrank the title, on the theory
   that framing copy gets in the way. It does not: fullscreen means
   the same page seen larger, and removing half the wording made it a
   different page. The only changes here are ones of scale.
   The three zones stay as they are in the normal view: title pinned
   top, render breathing in the middle, readout at the foot. An even
   earlier version set justify-content: flex-end on the overlay, which
   collapsed all three into one clump at the bottom of an otherwise
   empty screen. The panel's own margin-top: auto already does the
   anchoring, so the overlay must be left alone. */
.ss-sim .ss-sim-module:fullscreen .ss-sim-overlay,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-overlay {
    padding-top: 2.75rem;
}

/* Bigger at full size, not smaller. Fullscreen usually means the
   screen is further away, a projector or a classroom display, so the
   readout has to carry across a room. Hiding it is a choice the
   reader makes, not a default. */
.ss-sim .ss-sim-module:fullscreen .ss-sim-telemetry,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-telemetry {
    background: rgba(0, 0, 0, .32);
    max-width: 620px;
}

.ss-sim .ss-sim-module:fullscreen .ss-sim-row,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-row {
    padding: .75rem 1.1rem;
}

.ss-sim .ss-sim-module:fullscreen .ss-sim-row-label,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-row-label {
    font-size: .78rem;
}

.ss-sim .ss-sim-module:fullscreen .ss-sim-value,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-value {
    font-size: clamp(1rem, 1.9vw, 1.3rem);
}

.ss-sim .ss-sim-module:fullscreen .ss-sim-phase-name,
.ss-sim .ss-sim-module:-webkit-full-screen .ss-sim-phase-name {
    font-size: clamp(1.3rem, 2.6vw, 1.8rem);
}

/* ================================================================
   CHROME FADE
   Two ways to clear the frame. The button is explicit and sticky, the
   idle timer is automatic and only runs in fullscreen, which is the
   only place a bare render is the point. Both hide the buttons too,
   including the hide button: leaving one control floating over an
   otherwise empty frame defeats the exercise. Any pointer movement,
   tap or keypress brings it all back, so nothing is ever stranded.
   ================================================================ */

/* Asymmetric on purpose. Going away is slow enough to read as a
   drift rather than a blink; coming back is near-instant, so reaching
   for the mouse feels answered rather than waited on. The fast value
   lives here and the slow one on the hidden state, because a CSS
   transition belongs to the state being entered. */
.ss-sim .ss-sim-overlay,
.ss-sim .ss-sim-controls,
.ss-sim .ss-sim-actions,
.ss-sim .ss-sim-hint,
.ss-sim .ss-sim-credit {
    transition: opacity .15s ease-out;
}

.ss-sim .ss-sim-module.is-chrome-hidden .ss-sim-overlay,
.ss-sim .ss-sim-module.is-chrome-hidden .ss-sim-controls,
.ss-sim .ss-sim-module.is-chrome-hidden .ss-sim-actions,
.ss-sim .ss-sim-module.is-chrome-hidden .ss-sim-hint,
.ss-sim .ss-sim-module.is-chrome-hidden .ss-sim-credit,
.ss-sim .ss-sim-module.is-idle .ss-sim-overlay,
.ss-sim .ss-sim-module.is-idle .ss-sim-controls,
.ss-sim .ss-sim-module.is-idle .ss-sim-actions,
.ss-sim .ss-sim-module.is-idle .ss-sim-hint,
.ss-sim .ss-sim-module.is-idle .ss-sim-credit {
    opacity: 0;
    pointer-events: none;
    transition: opacity 1.2s ease-in-out;
}

/* Hide the cursor too once idle in fullscreen, the way a video player
   does. Nothing on screen but the thing itself. */
.ss-sim .ss-sim-module.is-idle { cursor: none; }

/* ================================================================
   PAGE BODY BELOW THE MODULE
   ================================================================ */

.ss-sim .ss-sim-container {
    max-width: var(--content-w, 1320px);
    margin: 0 auto;
    padding: 0 1.5rem;
}

.ss-sim .ss-sim-section { padding: 3rem 0 0; text-align: center; }

/* The gap above whatever follows the module now lives on the module's
   own margin-bottom, above, rather than here: a rule scoped to one
   class name silently misses any page section that happens to use a
   different one, which is exactly what left Voyager's dossier banner
   with no gap at all. */
.ss-sim .ss-sim-footer-space { padding-bottom: 3.5rem; }

.ss-sim .ss-sim-sec-kicker {
    margin: 0 0 .4rem;
    font-family: 'Space Grotesk', sans-serif;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--sim-accent);
}

.ss-sim .ss-sim-sec-title {
    margin: 0 0 1.25rem;
    font-family: 'Space Grotesk', sans-serif;
    font-size: clamp(1.6rem, 4vw, 2.4rem);
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--sim-text);
}

.ss-sim .ss-sim-prose {
    max-width: 820px;
    margin: 0 auto 1rem;
    font-size: .95rem;
    line-height: 1.75;
    text-align: left;
    color: var(--sim-text-muted);
}

/* ---- link cards ---- */

.ss-sim .ss-sim-links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
    max-width: 900px;
    margin: 1rem auto 0;
}

.ss-sim .ss-sim-link-card {
    display: block;
    padding: 1.1rem 1.2rem;
    border-radius: 12px;
    background: var(--sim-card-bg);
    border: 1px solid var(--sim-card-border);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    text-decoration: none;
    text-align: left;
    transition: border-color .25s ease, transform .25s ease;
}

.ss-sim .ss-sim-link-card:hover,
.ss-sim .ss-sim-link-card:focus-visible {
    border-color: var(--sim-link);
    transform: translateY(-2px);
}

.ss-sim .ss-sim-link-title {
    margin: 0 0 .4rem;
    font-size: .95rem;
    font-weight: 500;
    color: var(--sim-text);
}

.ss-sim .ss-sim-link-card:hover .ss-sim-link-title,
.ss-sim .ss-sim-link-card:focus-visible .ss-sim-link-title {
    color: var(--sim-link);
}

.ss-sim .ss-sim-link-desc {
    margin: 0;
    font-size: .82rem;
    line-height: 1.65;
    color: var(--sim-dim);
}

.ss-sim .ss-sim-ext {
    margin-left: .3rem;
    font-size: .8em;
    color: var(--sim-link);
}

/* ================================================================
   THE TIMELINE BACKBONE
   The alternating spine from the Voyager page, generalised. Any
   simulation can hang an ordered story off it: mission milestones,
   eclipse contact points, the phases of a lunar month.
   New here, and the reason it was worth generalising: each entry can
   carry its own links out.
   ================================================================ */

.ss-sim .ss-sim-timeline {
    list-style: none;
    margin: 2rem auto 0;
    padding: 0;
    position: relative;
    max-width: 1080px;
}

.ss-sim .ss-sim-timeline::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 6px;
    bottom: 6px;
    width: 2px;
    margin-left: -1px;
    background: linear-gradient(180deg, var(--sim-spine-from), var(--sim-spine-to));
    border-radius: 2px;
}

/* Colour has three jobs on the spine and only three: yellow for the
   furniture that marks position in time (node, connector, date), blue
   for anything you can follow, neutral for the card itself. An earlier
   pass put yellow on the border too and the result was a column of
   yellow rectangles where nothing stood out from anything. */
.ss-sim .ss-sim-tl-item {
    position: relative;
    width: calc(50% - 32px);
    padding: .9rem 1.15rem;
    background: var(--sim-card-bg);
    border: 1px solid var(--sim-card-border);
    border-radius: 12px;
    box-sizing: border-box;
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .55s ease, transform .55s ease;
}

/* Shared reveal class. voyager.js currently adds vg-visible and needs
   updating to is-visible alongside this file. */
.ss-sim .ss-sim-tl-item.is-visible {
    opacity: 1;
    transform: none;
}

.ss-sim .ss-sim-tl-item + .ss-sim-tl-item { margin-top: 1.1rem; }

.ss-sim .ss-sim-tl-item:hover {
    border-color: rgba(var(--sim-frame), .45);
}

.ss-sim .ss-sim-tl-item:nth-child(odd) {
    margin-right: auto;
    margin-left: 0;
    text-align: right;
}

.ss-sim .ss-sim-tl-item:nth-child(even) {
    margin-left: auto;
    margin-right: 0;
    text-align: left;
}

/* Pull each card up to sit alongside its predecessor on the opposite
   side, giving the woven look rather than a single stacked column. */
.ss-sim .ss-sim-tl-item:nth-child(n+2) { margin-top: -1.4rem; }
.ss-sim .ss-sim-tl-item:nth-child(2)   { margin-top: 3rem; }

/* Node on the centre spine */
.ss-sim .ss-sim-tl-item::before {
    content: "";
    position: absolute;
    top: 1.1rem;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--sim-module-bg);
    border: 2px solid var(--sim-active);
    z-index: 1;
}

.ss-sim .ss-sim-tl-item:nth-child(odd)::before  { right: -38px; }
.ss-sim .ss-sim-tl-item:nth-child(even)::before { left:  -38px; }

/* Connector from card edge to spine */
.ss-sim .ss-sim-tl-item::after {
    content: "";
    position: absolute;
    top: 1.4rem;
    width: 26px;
    height: 2px;
    background: var(--sim-active);
    opacity: .5;
}

.ss-sim .ss-sim-tl-item:nth-child(odd)::after  { right: -32px; }
.ss-sim .ss-sim-tl-item:nth-child(even)::after { left:  -32px; }

.ss-sim .ss-sim-tl-item.ss-sim-tl-milestone {
    border-color: rgba(var(--sim-frame), .55);
}

.ss-sim .ss-sim-tl-item.ss-sim-tl-milestone::before {
    border-color: var(--sim-active);
    background: var(--sim-active);
}

.ss-sim .ss-sim-tl-year {
    display: block;
    margin: 0 0 .25rem;
    font-size: .64rem;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sim-active);
}

.ss-sim .ss-sim-tl-title {
    margin: 0 0 .35rem;
    font-size: 1rem;
    font-weight: 500;
    color: var(--sim-text);
}

.ss-sim .ss-sim-tl-text {
    margin: 0;
    font-size: .82rem;
    line-height: 1.65;
    color: var(--sim-dim);
}

/* Links out from a timeline entry. Inline chips rather than full
   cards, so an entry can offer two or three sources without the
   spine turning into a wall. */
.ss-sim .ss-sim-tl-links {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin: .6rem 0 0;
    padding: 0;
    list-style: none;
}

.ss-sim .ss-sim-tl-item:nth-child(odd) .ss-sim-tl-links { justify-content: flex-end; }

.ss-sim .ss-sim-tl-link {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .22rem .6rem;
    border-radius: 999px;
    border: 1px solid var(--sim-link);
    background: rgba(0, 0, 0, .3);
    font-size: .7rem;
    line-height: 1.4;
    text-decoration: none;
    color: var(--sim-link);
    transition: border-color .2s, color .2s, background .2s;
}

.ss-sim .ss-sim-tl-link:hover,
.ss-sim .ss-sim-tl-link:focus-visible {
    background: var(--sim-link);
    color: #000;
}

/* ================================================================
   PROGRESS BAR
   Named progress, not rail: rail now means the timeline backbone.
   ================================================================ */

.ss-sim .ss-sim-progress { width: 100%; max-width: 560px; margin: 1rem auto 0; }

/* Thinner than the first pass. Amber is right, it matches the distance
   figure and the bar is a distance measure, but a near-solid slab as
   wide as the countdown was competing with it for attention. Slimmer
   fill, bright pip: the eye goes to the gap, which is the part worth
   reading. */
.ss-sim .ss-sim-progress-track {
    position: relative;
    height: 5px;
    border-radius: 999px;
    /* Lighter than before so the unfilled remainder is actually
       visible. At 98.76% the old faint track made the bar look like a
       plain line, hiding the very thing worth seeing. */
    background: rgba(255, 255, 255, .16);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}

/* The milestone. A target pip at the far end turns the bar from a
   decorative gradient into a measurement: what you read is the gap
   between where the fill has reached and where it is going. */
.ss-sim .ss-sim-progress-track::after {
    content: "";
    position: absolute;
    top: -5px;
    bottom: -5px;
    right: 0;
    width: 3px;
    border-radius: 2px;
    background: var(--sim-active);
    box-shadow: 0 0 8px rgba(var(--sim-frame), .8);
}

.ss-sim .ss-sim-progress-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 0;
    border-radius: 999px;
    /* One colour, not a gradient: a gradient reads as decoration,
       a solid fill reads as a quantity. The leading edge is picked
       out so the current position is unambiguous. */
    background: var(--sim-accent);
    opacity: .85;
    box-shadow: 2px 0 6px rgba(74, 159, 212, .5);
    transition: width .6s ease;
}

.ss-sim .ss-sim-progress-caption {
    margin: .5rem 0 0;
    font-size: .7rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sim-dim);
}

.ss-sim .ss-sim-progress-caption strong {
    color: var(--sim-accent);
    font-variant-numeric: tabular-nums;
}

/* ================================================================
   PUZZLE TIE-IN
   ================================================================ */

.ss-sim .ss-sim-puzzles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1rem;
    max-width: 900px;
    margin: 1rem auto 0;
}

.ss-sim .ss-sim-puzzle-card {
    display: block;
    padding: 1.1rem 1.2rem;
    border-radius: 12px;
    background: var(--sim-card-bg);
    border: 1px solid rgba(var(--sim-frame), .3);
    text-decoration: none;
    text-align: left;
    font-size: .95rem;
    color: var(--sim-text);
    transition: border-color .25s ease, transform .25s ease;
}

.ss-sim .ss-sim-puzzle-card:hover,
.ss-sim .ss-sim-puzzle-card:focus-visible {
    border-color: var(--sim-active);
    transform: translateY(-2px);
}

.ss-sim .ss-sim-puzzle-tag {
    display: block;
    margin-bottom: .4rem;
    font-size: .62rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sim-active);
}

/* ================================================================
   RESPONSIVE
   The timeline collapses to a single left-hand spine on narrow
   screens: two columns of alternating cards is unreadable there.
   ================================================================ */

@media (max-width: 860px) {
    .ss-sim .ss-sim-timeline::before { left: 12px; margin-left: 0; }

    .ss-sim .ss-sim-tl-item,
    .ss-sim .ss-sim-tl-item:nth-child(odd),
    .ss-sim .ss-sim-tl-item:nth-child(even) {
        width: auto;
        margin: 0 0 1rem 44px;
        text-align: left;
    }

    .ss-sim .ss-sim-tl-item:nth-child(n+2) { margin-top: 0; }
    .ss-sim .ss-sim-tl-item:nth-child(2)   { margin-top: 0; }

    .ss-sim .ss-sim-tl-item:nth-child(odd)::before,
    .ss-sim .ss-sim-tl-item:nth-child(even)::before { left: -38px; right: auto; }

    .ss-sim .ss-sim-tl-item:nth-child(odd)::after,
    .ss-sim .ss-sim-tl-item:nth-child(even)::after { left: -32px; right: auto; }

    .ss-sim .ss-sim-tl-item:nth-child(odd) .ss-sim-tl-links { justify-content: flex-start; }
}

@media (max-width: 640px) {
    .ss-sim .ss-sim-module { height: clamp(560px, 92vh, 720px); margin-top: 1rem; }
    .ss-sim .ss-sim-overlay { padding: 2rem 1rem 0; }
    .ss-sim .ss-sim-container { padding: 1.25rem 1rem 0; }
    .ss-sim .ss-sim-row { flex-direction: column; align-items: flex-start; gap: .2rem; }
    .ss-sim .ss-sim-value { align-self: flex-end; }
    .ss-sim .ss-sim-controls { right: 12px; bottom: 12px; }
    .ss-sim .ss-sim-btn { font-size: .72rem; padding: .5rem .8rem; }
    .ss-sim .ss-sim-countdown {
        gap: .4rem;
        grid-template-columns: repeat(4, minmax(58px, 1fr));
        width: 100%;
        max-width: 380px;
    }
}

/* ================================================================
   REDUCED MOTION
   ================================================================ */

@media (prefers-reduced-motion: reduce) {
    .ss-sim .ss-sim-live-dot { animation: none; }
    .ss-sim .ss-sim-btn.is-flash { animation: none; }
    .ss-sim .ss-sim-link-card,
    .ss-sim .ss-sim-puzzle-card,
    .ss-sim .ss-sim-progress-fill { transition: none; }
    .ss-sim .ss-sim-link-card:hover,
    .ss-sim .ss-sim-puzzle-card:hover { transform: none; }
    .ss-sim .ss-sim-tl-item { opacity: 1; transform: none; transition: none; }
}