/*
 * slashwork shared styles. Linked from base.html, so the arena board, the
 * landing page, the live tape, and the first-visit loader all read from the
 * same tokens.
 *
 * Visual system: "Broadcast terminal" (see DESIGN.md). Utilities come from the
 * committed Tailwind build (tw.css); these variables and a few component classes
 * carry the parts Tailwind cannot express (the self-hosted fonts below, the tape
 * crawl, the loader). Implementation is incremental: the landing and the shared
 * chrome are on the new system; inner pages keep their prior styling until their
 * slice lands.
 */

/*
 * Self-hosted fonts (latin subset, woff2). Vendored from Google Fonts into
 * static/fonts/ so the page pulls no external stylesheet or font host. Refresh
 * by re-running the fetch documented in static/vendor/README.md. The families
 * here match the --disp/--body/--mono/--code roles in :root below.
 */
@font-face {
    font-family: 'Anton';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/anton-400.woff2') format('woff2');
}
@font-face {
    font-family: 'Hanken Grotesk';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/hanken-grotesk-400.woff2') format('woff2');
}
@font-face {
    font-family: 'Hanken Grotesk';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/static/fonts/hanken-grotesk-500.woff2') format('woff2');
}
@font-face {
    font-family: 'Hanken Grotesk';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/static/fonts/hanken-grotesk-600.woff2') format('woff2');
}
@font-face {
    font-family: 'Hanken Grotesk';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/static/fonts/hanken-grotesk-700.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/ibm-plex-mono-400.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/static/fonts/ibm-plex-mono-500.woff2') format('woff2');
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/static/fonts/ibm-plex-mono-600.woff2') format('woff2');
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/jetbrains-mono-400.woff2') format('woff2');
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/static/fonts/jetbrains-mono-500.woff2') format('woff2');
}

:root {
    color-scheme: dark;

    /* surfaces */
    --bg: #0B0B0D;      /* warm near-black, the page background */
    --surface: #141417; /* raised cards */
    --surface2: #1B1B1F;/* deeper insets, tracks */
    --line: #26262B;    /* hairline borders */

    /* text */
    --fg: #F4F1EA;      /* warm off-white */
    --muted: #8A8A93;

    /* state accents (reserved, meaningful) */
    --live: #E8FF3A;    /* floodlight yellow: LIVE + primary action */
    --win: #FF5B2E;     /* klaxon orange-red: crowned + ELO up */
    --down: #6CC0FF;    /* ELO down, used sparingly */
    --tape: #34D399;    /* emerald: the ticker dots and its hairline (2026-07-14 call) */

    /* type roles */
    --disp: 'Anton', 'Archivo', sans-serif;
    --body: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif;
    --mono: 'IBM Plex Mono', ui-monospace, monospace;
    --code: 'JetBrains Mono', ui-monospace, monospace;

    /*
     * Loader background. Pinned to the color the w-spin video is baked on
     * (#09090b), which is within 2 points of --bg, so the crossfade has no
     * visible seam. Rebake the video to --bg if the palette shift makes it one.
     */
    --loader-bg: #09090b;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--fg);
    font-family: var(--body);
    -webkit-font-smoothing: antialiased;
}

/* Code and preformatted text are always the code mono, even inside body prose,
   so command snippets stay monospaced without a class on every element. */
pre, code { font-family: var(--code); }

/* ---- type-role utilities (used alongside Tailwind) ---- */
.font-disp { font-family: var(--disp); }
.font-body { font-family: var(--body); }
.font-data { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.font-code { font-family: var(--code); }
.cap { font-family: var(--disp); text-transform: uppercase; letter-spacing: .01em; }

/* ---- the /work wordmark ---- */
.bt-mark { font-family: var(--disp); font-size: 26px; line-height: .9; letter-spacing: .01em; color: var(--fg); text-decoration: none; }
.bt-mark .slash { color: var(--live); }

/* ---- header nav chips ---- */
/* Every nav destination is a bordered chip, not bare muted text: readable at
   rest, an obvious button on touch screens, and sized so wrapped rows on a
   phone still give a real tap target. The current section is marked by the
   nav script in base.html (is-active), lifted on a raised surface so you can
   see where you are without spending the yellow reserved for live/action. */
.bt-nav {
    display: inline-flex; align-items: center;
    padding: 7px 12px; border: 1px solid var(--line); border-radius: 6px;
    font-size: 14px; line-height: 1.2; font-weight: 500;
    color: #C6C3BC; background: transparent; text-decoration: none;
    cursor: pointer; white-space: nowrap;
    transition: color .12s ease, border-color .12s ease, background .12s ease;
}
.bt-nav:hover { color: var(--fg); border-color: #3A3A41; background: var(--surface); }
.bt-nav.is-active { color: var(--fg); background: var(--surface2); border-color: #45454C; }

/* Primary CTA: the one yellow-outlined action per screen (e.g. dashboard sign-in). */
.bt-cta {
    display: inline-flex; align-items: center;
    padding: 9px 16px; border: 1px solid var(--live); border-radius: 6px;
    font-family: var(--disp); text-transform: uppercase; letter-spacing: .04em;
    font-size: 14px; color: var(--live); background: transparent; text-decoration: none;
    cursor: pointer; transition: background .12s ease, color .12s ease;
}
.bt-cta:hover { background: var(--live); color: #0B0B0D; }

/* Status dots for the dashboard ledger. ok = delivered, live = in flight,
   muted = fell back local. */
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.dot-ok { background: #34D399; }
.dot-live { background: var(--live); box-shadow: 0 0 8px var(--live); }
.dot-muted { background: var(--muted); }

/* ---------- LIVE TAPE ---------- */
/*
 * Full-bleed broadcast wire at the very top of every page. Filled by an htmx
 * fragment from GET /tape. The page is never blocked on it: it starts empty and
 * fills on load. It does NOT scroll on a timer. The wire holds still and ticks
 * forward exactly one notch when a real event lands on the live stream, driven
 * by the tape script in base.html (the slide here, the trigger there). Reduced
 * motion drops the tick and stacks the items.
 */
#tape {
    background: #000;
    border-bottom: 1px solid var(--line);
    box-shadow: 0 1px 0 rgba(52, 211, 153, .08);
    overflow: hidden;
}
.bt-tape { height: 40px; display: flex; align-items: center; overflow: hidden; padding-left: 16px; }
.bt-track {
    display: inline-flex; gap: 2.5rem; white-space: nowrap; will-change: transform;
}
.bt-it { font-family: var(--mono); font-size: 13px; color: var(--muted); display: inline-flex; align-items: center; gap: .5rem; }
.bt-it b { color: var(--fg); font-weight: 500; }
.bt-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tape); display: inline-block; box-shadow: 0 0 8px var(--tape); animation: bt-blink 1.2s ease-in-out infinite; }
/* Desynchronize the dots: a three-phase stagger across the 1.2s blink so the
 * wire shimmers instead of pulsing in lockstep. Negative delays start each dot
 * mid-cycle, so nothing sits unlit waiting for its first loop. The tape's JS
 * rotates items to the end of the track, which re-deals the nth-child phases;
 * that drift is fine, the point is only that neighbors differ. */
.bt-it:nth-child(3n+2) .bt-dot { animation-delay: -0.4s; }
.bt-it:nth-child(3n) .bt-dot { animation-delay: -0.8s; }
/* The viewer's own offload on the wire: "you saved N tokens" in their chosen
 * accent (--mine, set inline on the track from users.accent_color, the same
 * color as their handle), falling back to the accepted-work orange when no
 * accent is present. Only ever rendered for the session that owns it; the
 * wire is anonymous to everyone else. */
.bt-it.bt-mine, .bt-it.bt-mine b { color: var(--mine, var(--win)); }
.bt-mine .bt-dot { background: var(--mine, var(--win)); box-shadow: 0 0 8px var(--mine, var(--win)); }
.bt-empty { font-family: var(--mono); font-size: 13px; color: var(--muted); }

@keyframes bt-blink { 50% { opacity: .25; } }

@media (prefers-reduced-motion: reduce) {
    .bt-track { transform: none !important; transition: none !important; white-space: normal; gap: 1.25rem; flex-wrap: wrap; }
    .bt-dot { animation: none; }
}

/* ---------- FIRST-VISIT LOADER ---------- */
#loader {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--loader-bg);
    transition: opacity 300ms ease;
    cursor: pointer;
}
#loader.is-hidden { opacity: 0; pointer-events: none; }
#loader video { width: min(60vmin, 360px); height: auto; }
@media (prefers-reduced-motion: reduce) { #loader { transition: none; } }

/* ---------- ARENA BOARD ---------- */
/* Countdown clock on each contest row. Ticked client-side from data-deadline
   (see base.html). Under 60s it runs hot, pulsing yellow to orange. */
.bt-clock { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.bt-clock.warn { color: var(--live); animation: bt-hot 1s ease-in-out infinite; }
@keyframes bt-hot { 50% { color: var(--win); } }

/* Entrant fill bar: submissions toward the judge-at cap. Width animates on a
   count swap. */
.bt-fill { position: relative; height: 6px; background: var(--surface2); border-radius: 3px; overflow: hidden; }
.bt-fill > i { position: absolute; inset: 0 auto 0 0; background: var(--fg); border-radius: 3px; transition: width .8s ease; }
.bt-fill.live > i { background: var(--live); }

@media (prefers-reduced-motion: reduce) {
    .bt-clock.warn { animation: none; }
    .bt-fill > i { transition: none; }
}

/* ---------- ACTIVITY CHART ---------- */
/* Segmented controls (metric + range). Active segment is floodlight yellow. */
.seg {
    padding: 5px 12px; font-family: var(--mono); font-variant-numeric: tabular-nums;
    font-size: 12px; line-height: 1.3; color: var(--muted); background: transparent;
    border: 0; border-left: 1px solid var(--line); cursor: pointer;
    transition: color .12s ease, background .12s ease;
}
.seg:first-child { border-left: 0; }
.seg:hover { color: var(--fg); }
.seg.is-active, .seg.is-active:hover { background: var(--live); color: #0B0B0D; }

/* Toggleable legend: a color swatch plus the competitor handle. */
.lg-item {
    display: inline-flex; align-items: center; gap: 6px; padding: 2px 2px;
    font-family: var(--mono); font-size: 12px; line-height: 1.2; color: var(--muted);
    background: transparent; border: 0; cursor: pointer; user-select: none;
    transition: color .12s ease, opacity .12s ease;
}
.lg-item:hover { color: var(--fg); }
.lg-swatch { width: 10px; height: 10px; border-radius: 2px; flex: 0 0 auto; }
.lg-item.is-off { opacity: .42; text-decoration: line-through; }
.lg-item.is-off .lg-swatch { background: #3a3a40 !important; }

/* Floating hover tooltip: the time plus each visible competitor's value. */
.u-tip {
    position: absolute; top: 0; left: 0; pointer-events: none; z-index: 10;
    background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
    padding: 6px 8px; font-family: var(--mono); font-size: 11px; line-height: 1.55;
    color: var(--fg); box-shadow: 0 6px 20px rgba(0, 0, 0, .55); white-space: nowrap;
    will-change: transform;
}
.u-tip-x { color: var(--muted); font-size: 10px; margin-bottom: 3px; letter-spacing: .02em; }
.u-tip-row { display: flex; align-items: center; gap: 6px; }
.u-tip-sw { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.u-tip-val { margin-left: auto; padding-left: 14px; font-variant-numeric: tabular-nums; }
.u-tip-more { color: var(--muted); font-size: 10px; margin-top: 2px; }
