html, body {
    margin: 0; padding: 0; min-height: 100%;
    background: var(--bg, #030510);
    color: var(--fg, #141c3c);
    /* body { position: relative } turns the body into the
       containing block for body::before's absolute glow
       layer below — without this the ::before would size to
       <html> (capped at viewport height) and the moon's glow
       would have nowhere to render once its DOC position
       crossed below the first viewport. */
    position: relative;
    /* No long color transition: in cycle mode JS sets --bg/--fg
       every rAF frame (60Hz), so the bg already smooth-fades
       via the rapid-fire updates. A long CSS transition on top
       (the prior 12s) would lerp the body bg toward EACH frame's
       target, lagging the orb by seconds. */
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    /* Glassmorphism tokens. Landing page doesn't have a fixed
       light/dark mode (it cycles), so the glass bg is derived
       from --bg via color-mix at low opacity — it picks up
       the warm sunrise / cool midnight automatically while
       staying see-through enough to read the spinning cube
       through the panel. blur + saturate restore legibility. */
    --glass-bg: color-mix(in srgb, var(--bg, #0c1226) 32%, transparent);
    --glass-border: rgba(255, 255, 255, 0.45);
    --glass-highlight: rgba(255, 255, 255, 0.55);
    --glass-shadow: 0 10px 32px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.10);
    --glass-blur: blur(20px) saturate(1.65);
}
/* Slide between hero (cube) and games sections with a smooth
   snap. Snap is mandatory but proximity-style on touch devices
   keeps casual scrolling responsive instead of force-snapping
   every gesture. Reduced-motion users opt out below. */
html { scroll-behavior: smooth; scroll-snap-type: y proximity; }
main { position: relative; z-index: 1; }
main {
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
}
/* Hero: one viewport, cube centred, scroll arrow at the bottom.
   Sun + light cascade live inside (not on body) so they scroll
   with the hero — when the user pulls down to the games
   section, the celestial chrome is offscreen. */
.hero {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 1.5rem 1rem;
    box-sizing: border-box;
    position: relative;
    scroll-snap-align: start;
    /* No overflow:hidden — the orb's elliptical orbit extends
       past the bottom of the hero at midnight, and we want
       the user to see the moon down there when they scroll
       into the games section. */
}
/* Light cascade — radial gradient anchored to the orb's DOC
   position (not viewport). position:absolute on the body
   pseudo means the glow scrolls WITH the page; the gradient
   sits at the orb's true place in the document, and as the
   user scrolls between the hero and the games section the
   visible slice of the glow changes naturally.
   A fixed-pixel radius (520px) instead of a percentage stop
   keeps the falloff consistent no matter how tall the body
   grows — percentage stops on a multi-viewport-tall ::before
   would make the gradient huge and washed out. */
body::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 0;
    background: radial-gradient(
        circle 520px at var(--sun-x, 50%) var(--sun-y, 0%),
        var(--sun-glow, rgba(255, 220, 110, 0)) 0%,
        transparent 100%
    );
    transition: background 0.6s ease;
}
.hero-scroll {
    position: absolute;
    bottom: 4vh;
    left: 50%;
    transform: translateX(-50%);
    color: var(--fg, #141c3c);
    text-decoration: none;
    user-select: none;
    opacity: 0.55;
    transition: opacity 0.2s ease, transform 0.2s ease, color 0.4s ease;
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
    cursor: pointer;
    z-index: 4;
}
.hero-scroll:hover { opacity: 1; transform: translate(-50%, 4px); }
.hero-scroll-arrow {
    font-family: inherit;
    font-size: clamp(1.6rem, 4vw, 2.6rem);
    font-weight: 700;
    line-height: 1;
    transform: scaleX(2.2);              /* widen into a flat V */
    transform-origin: center;
    animation: hero-arrow-bob 2.2s ease-in-out infinite;
}
@keyframes hero-arrow-bob {
    0%, 100% { transform: scaleX(2.2) translateY(0); opacity: 0.8; }
    50%      { transform: scaleX(2.2) translateY(4px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .hero-scroll-arrow { animation: none; }
}
/* Games section: filling the second viewport, clickable /crib. */
.games {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    box-sizing: border-box;
    scroll-snap-align: start;
    gap: 0.6rem;
}
pre {
    font-family: inherit;
    line-height: 1.15;
    letter-spacing: 0.02em;
    margin: 0;
    color: var(--fg, #141c3c);
    transition: color 0.4s ease;
    user-select: none;
    white-space: pre;
}
#cube {
    /* +40% from the prior clamp — cube is now the focal element on
       the page (welcome banner removed), so we want it to dominate
       but stay shorter than the /crib block below it. */
    font-size: clamp(0.45rem, 0.78vw, 1.0rem);
    position: relative;
    z-index: 1;
}
.cube-wrap {
    position: relative;
    display: inline-block;
    line-height: 1;
}
/* Cast shadow anchored to the cube's footprint. updateCubeShadow()
   sets transform skew + scaleX so the shape stretches away from
   the sun: long & faint at dawn/dusk, short & dense at noon. */
#cube-shadow {
    position: absolute;
    bottom: -4%;
    left: 50%;
    width: 62%;
    height: 9%;
    background: radial-gradient(ellipse at center,
        rgba(0, 0, 0, 0.55) 0%,
        rgba(0, 0, 0, 0.35) 40%,
        transparent 70%);
    border-radius: 50%;
    transform: translateX(-50%);
    transform-origin: center top;
    pointer-events: none;
    opacity: 0;
    filter: blur(3px);
    /* Only opacity smooths via CSS — transform is driven from
       the cube's rAF loop, where any added CSS transition
       would just add lag against the per-frame target. */
    transition: opacity 0.8s ease;
    z-index: 0;
    will-change: transform, opacity;
}
@media (prefers-reduced-motion: reduce) {
    #cube-shadow { transition: opacity 0.3s linear; }
}
#links {
    display: flex;
    gap: 1.5rem;
    justify-content: center;
    font-size: clamp(0.85rem, 1.2vw, 1.05rem);
}
#links a {
    color: var(--fg, #141c3c);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding: 0.1rem 0.15rem;
    transition: color 0.4s ease, opacity 0.2s;
    font-weight: 600;
}
#links a:hover {
    opacity: 0.65;
}
#sim {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    font-size: clamp(0.55rem, 0.95vw, 0.85rem);
    line-height: 1.25;
    opacity: 0.92;
    max-width: 100%;
}
#sim pre { margin: 0; font-family: inherit; }
#sim-stack {
    display: flex;
    gap: 0.35rem;
    justify-content: center;
    align-items: flex-start;
    flex-wrap: wrap;
    min-height: 5.5em;
    padding-top: 0.6rem;
}
#sim-stack .sim-card {
    display: inline-block;
    transform-origin: center top;
}
#sim-stack .sim-card pre {
    margin: 0;
    line-height: 1.15;
    color: var(--fg, #141c3c);
    transition: color 0.4s ease;
}
#sim-stack .sim-card.red pre { color: var(--accent, #ff9a3c); }
/* Compact hand rows below the pegging stack — first-initial of the
   player name + their remaining cards as tiny rank+suit chips. The
   rows sit side-by-side so the eye reads each hand as a compact
   block rather than a vertical list. */
.sim-hands {
    margin-top: 0.4rem;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.25rem 0.8rem;
    justify-content: flex-end;
    font-size: clamp(0.5rem, 0.85vw, 0.7rem);
    opacity: 0.65;
    transition: color 0.4s ease;
}
.sim-hand-row {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    font-family: inherit;
    color: var(--fg, #141c3c);
    white-space: nowrap;
}
.sim-hand-row.active { opacity: 1; font-weight: 600; }
.sim-hand-label {
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.6;
}
.sim-hand-cards { display: inline-flex; gap: 0.25rem; }
.sim-hand-chip {
    display: inline-block;
    padding: 0 0.2rem;
    border: 1px solid currentColor;
    border-radius: 2px;
    line-height: 1.1;
    opacity: 0.75;
}
.sim-hand-chip.red { color: var(--accent, #ff9a3c); }
.sim-hand-chip.played {
    opacity: 0.2;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}
/* Big suit glyph in the center of each ASCII card — matches the
   in-game /crib renderer so the home preview shows the same
   shape as the live app. The .bigsuit span is inserted by
   cards.js's renderCardHtml. */
#sim-stack .sim-card .bigsuit {
    display: inline-block;
    transform: scale(1.9);
    transform-origin: center;
    line-height: 0.9;
}
#sim-stack .sim-card.just-played {
    animation: sim-throw 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes sim-throw {
    0% {
        transform: translateY(-72px) translateX(34px) rotate(-22deg) scale(1.08);
        opacity: 0;
    }
    55% {
        transform: translateY(6px) translateX(-3px) rotate(2deg) scale(1);
        opacity: 1;
    }
    100% {
        transform: translateY(0) translateX(0) rotate(0deg) scale(1);
        opacity: 1;
    }
}

/* Top-right control buttons */
.top-controls {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 10;
    display: flex;
    gap: 0.4rem;
}
.theme-btn {
    background: transparent;
    color: var(--fg, #141c3c);
    border: 1px solid currentColor;
    font-family: inherit;
    font-size: 0.85rem;
    padding: 0.3rem 0.7rem;
    cursor: pointer;
    opacity: 0.65;
    transition: opacity 0.15s, color 0.4s ease;
}
.theme-btn:hover { opacity: 1; }
.theme-btn.off { opacity: 0.45; }
.theme-btn.off::after { content: ' (off)'; opacity: 0.7; }

/* Click-anywhere /crib block */
.crib-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    text-decoration: none;
    color: inherit;
    padding: 1rem 1.5rem;
    /* Real glass — the cube + sim + card-rain behind read
       through as soft blurred texture. Low-opacity bg
       (~32% of --bg) + strong saturated blur + a 1px
       translucent border + inset top-edge highlight + outer
       shadow are the four ingredients that read as "a pane
       of frosted glass sitting on the page" instead of "a
       flat tinted div". */
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight);
    border-radius: 14px;
    transition: transform 0.15s, background 0.2s, box-shadow 0.2s;
    cursor: pointer;
    margin-top: 0.5rem;
    opacity: 0.95;
}
.crib-block:hover {
    transform: translateY(-3px);
    box-shadow:
        var(--glass-shadow),
        inset 0 1px 0 var(--glass-highlight),
        0 12px 36px rgba(0, 0, 0, 0.18);
    opacity: 1;
}
.crib-block-label {
    font-size: clamp(0.95rem, 1.4vw, 1.2rem);
    font-weight: 700;
    letter-spacing: 0.06em;
}
.crib-block-label::after {
    content: ' →';
    transition: transform 0.15s;
    display: inline-block;
}
.crib-block:hover .crib-block-label::after { transform: translateX(4px); }

/* ---- Mobile ---- */
@media (max-width: 700px) {
    main { padding: 1rem 0.5rem 2rem; gap: 0.35rem; }
    #cube { font-size: clamp(0.36rem, 1.35vw, 0.78rem); }
    .crib-block { padding: 0.75rem 1rem; gap: 0.5rem; }
    .crib-block-label { font-size: 0.95rem; }
    #sim { font-size: clamp(0.5rem, 1.4vw, 0.7rem); gap: 0.3rem; }
    #sim-stack { gap: 0.2rem; }
    #sim-stack .sim-card pre { line-height: 1.05; }
    .top-controls { top: 0.5rem; right: 0.5rem; gap: 0.3rem; }
    .theme-btn { font-size: 0.72rem; padding: 0.25rem 0.5rem; }
    /* Hide one of the starfields on phones to reduce clutter */
    #starfield-left { display: none !important; }
}
@media (max-width: 380px) {
    #cube { font-size: clamp(0.31rem, 1.13vw, 0.63rem); }
    #sim { font-size: 0.5rem; }
    #starfield-right { display: none !important; }
}


/* Site footer — single source for monorepo build version + a
   rough unique-visitor counter. Muted + small so it sits as
   metadata, not a focal element. Fixed to the bottom of the
   viewport so it appears regardless of page scroll state. */
.site-footer {
    position: fixed;
    bottom: 0.5rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 0.5rem;
    align-items: center;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.68rem;
    color: var(--fg, #141c3c);
    opacity: 0.55;
    transition: opacity 0.2s, color 0.4s ease;
    user-select: text;
    z-index: 5;
    pointer-events: auto;
}
.site-footer:hover { opacity: 0.95; }
.footer-version:empty { display: none; }
.footer-sep { opacity: 0.4; }
