/**
 * RUST Server Page — live data sections
 *
 * Events, vitals, population graph, wipe totals and leaderboards. Everything
 * here is driven by js/rust.js from the stats the plugin pushes.
 *
 * Kept separate from rust.css so the original page styling stays untouched
 * and this can be dropped without side effects.
 *
 * Uses the palette defined in rust.css: --rust-orange, --rust-glow,
 * --rust-metal, --rust-dark.
 */

/* --- PVE / PVP switcher --------------------------------------------------- */

.server-switcher {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    margin: 1.75rem 0 0.5rem;
}

/* Vault toggle (Uiverse.io by Gidarx), recoloured to the site palette.
   --color-amber is the unchecked side (PVE, green) and --color-emerald the
   checked side (PVP, red) — the variable names are the original author's and
   no longer describe the hues, but renaming them would mean touching every
   rule below. Unchecked is the first server in SERVERS, checked the second. */
.ux-vault-toggle {
    --color-slate-base: #241a15;
    --color-slate-dark: #150f0c;
    --color-slate-light: #35271f;
    --color-amber: #22c55e;      /* PVE */
    --color-emerald: #ef4444;    /* PVP */
    --color-text-dim: #6b7280;
    --track-w: 200px;
    --track-h: 74px;
    --thumb-size: 62px;
    display: inline-block;
    position: relative;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.ux-vault-toggle__input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.ux-vault-toggle__wrapper {
    width: var(--track-w);
    height: var(--track-h);
    position: relative;
    border-radius: 40px;
    background: var(--color-slate-base);
    box-shadow:
        0 0 0 2px var(--color-slate-dark),
        0 8px 24px rgba(0, 0, 0, 0.6);
    isolation: isolate;
}

.ux-vault-toggle__filter {
    position: absolute;
    pointer-events: none;
}

.ux-vault-toggle__track {
    position: absolute;
    inset: 2px;
    border-radius: 38px;
    background: var(--color-slate-dark);
    box-shadow:
        inset 0 8px 16px rgba(0, 0, 0, 0.9),
        inset 0 3px 6px rgba(0, 0, 0, 0.7),
        inset 0 -2px 4px rgba(255, 255, 255, 0.03);
    overflow: hidden;
    display: flex;
    align-items: center;
}

.ux-vault-toggle__texture {
    position: absolute;
    inset: 0;
    background: var(--color-slate-dark);
    filter: url(#ux-metal-noise);
    opacity: 0.6;
    mix-blend-mode: overlay;
    pointer-events: none;
}

.ux-vault-toggle__circuit {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;
}

.ux-circuit-path {
    fill: none;
    stroke-width: 2;
    stroke-dasharray: 100;
    stroke-linecap: round;
    transition:
        stroke-dashoffset 0.6s cubic-bezier(0.65, 0, 0.35, 1),
        stroke 0.6s ease;
}

.ux-circuit--off {
    stroke: var(--color-amber);
    stroke-dashoffset: 0;
    opacity: 0.4;
}

.ux-circuit--on {
    stroke: var(--color-emerald);
    stroke-dashoffset: 100;
    opacity: 0.4;
}

.ux-vault-toggle__status {
    position: absolute;
    font-family: system-ui, -apple-system, sans-serif;
    font-weight: 800;
    font-size: 17px;
    letter-spacing: 2px;
    display: flex;
    z-index: 2;
}

.ux-vault-toggle__status span {
    display: inline-block;
    transition:
        transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
        opacity 0.4s ease,
        color 0.4s ease;
    transition-delay: calc(var(--i) * 0.05s);
}

.ux-vault-toggle__status--off {
    right: 24px;
    color: var(--color-amber);
    text-shadow: 0 0 8px color-mix(in srgb, var(--color-amber) 50%, transparent);
}

.ux-vault-toggle__status--on {
    left: 24px;
    color: var(--color-emerald);
    text-shadow: 0 0 8px color-mix(in srgb, var(--color-emerald) 50%, transparent);
}

.ux-vault-toggle__status--on span {
    opacity: 0;
    transform: translateY(15px) scale(0.8);
    color: var(--color-text-dim);
}

.ux-vault-toggle__thumb {
    position: absolute;
    top: 6px;
    left: 6px;
    width: var(--thumb-size);
    height: var(--thumb-size);
    border-radius: 50%;
    background: linear-gradient(145deg, var(--color-slate-light), var(--color-slate-base));
    box-shadow:
        0 8px 16px rgba(0, 0, 0, 0.6),
        0 4px 8px rgba(0, 0, 0, 0.5),
        inset 0 2px 4px rgba(255, 255, 255, 0.15),
        inset 0 -3px 6px rgba(0, 0, 0, 0.5);
    z-index: 3;
    transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.ux-vault-toggle__thumb-ring {
    position: absolute;
    inset: 2px;
    border-radius: 50%;
    background: linear-gradient(to bottom, #443128, #1f1713);
    box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.8);
    z-index: 1;
}

.ux-vault-toggle__thumb-core {
    position: absolute;
    inset: 8px;
    border-radius: 50%;
    background: var(--color-slate-dark);
    border: 2px solid var(--color-amber);
    box-shadow:
        inset 0 0 10px color-mix(in srgb, var(--color-amber) 35%, transparent),
        0 0 15px color-mix(in srgb, var(--color-amber) 45%, transparent);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.6s ease, box-shadow 0.6s ease;
}

.ux-thumb-icon {
    width: 23px;
    height: 23px;
    color: var(--color-amber);
    transition:
        color 0.6s ease,
        transform 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.ux-vault-toggle__thumb-glare {
    position: absolute;
    top: 2px;
    left: 10%;
    width: 80%;
    height: 40%;
    border-radius: 50%;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.15), transparent);
    z-index: 4;
    pointer-events: none;
}

/* Travel distance = track width - thumb size - (2 x 6px inset). */
.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-vault-toggle__thumb {
    transform: translateX(126px);
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-vault-toggle__thumb-core {
    border-color: var(--color-emerald);
    box-shadow:
        inset 0 0 12px color-mix(in srgb, var(--color-emerald) 40%, transparent),
        0 0 20px color-mix(in srgb, var(--color-emerald) 50%, transparent);
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-thumb-icon {
    color: var(--color-emerald);
    transform: rotate(180deg) scale(1.1);
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-circuit--off {
    stroke-dashoffset: -100;
    opacity: 0;
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-circuit--on {
    stroke-dashoffset: 0;
    opacity: 0.8;
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-vault-toggle__status--off span {
    opacity: 0;
    transform: translateY(-15px) scale(0.8);
    color: var(--color-text-dim);
}

.ux-vault-toggle__input:checked ~ .ux-vault-toggle__wrapper .ux-vault-toggle__status--on span {
    opacity: 1;
    transform: translateY(0) scale(1);
    color: var(--color-emerald);
}

.ux-vault-toggle:hover .ux-vault-toggle__thumb-core {
    box-shadow:
        inset 0 0 15px color-mix(in srgb, var(--color-amber) 55%, transparent),
        0 0 25px color-mix(in srgb, var(--color-amber) 65%, transparent);
}

.ux-vault-toggle__input:checked:hover ~ .ux-vault-toggle__wrapper .ux-vault-toggle__thumb-core {
    box-shadow:
        inset 0 0 15px color-mix(in srgb, var(--color-emerald) 60%, transparent),
        0 0 25px color-mix(in srgb, var(--color-emerald) 70%, transparent);
}

.ux-vault-toggle:active .ux-vault-toggle__thumb {
    transform: scale(0.95);
}

.ux-vault-toggle__input:checked:active ~ .ux-vault-toggle__wrapper .ux-vault-toggle__thumb {
    transform: translateX(126px) scale(0.95);
}

/* Keyboard focus needs a visible ring — the real checkbox is hidden. */
.ux-vault-toggle__input:focus-visible ~ .ux-vault-toggle__wrapper {
    box-shadow:
        0 0 0 2px var(--color-slate-dark),
        0 0 0 5px rgba(255, 107, 53, 0.7),
        0 8px 24px rgba(0, 0, 0, 0.6);
}

/* Live player count per server, so the other one's state is visible without
   switching to it. */
.server-toggle-counts {
    display: flex;
    gap: 1.25rem;
}

.server-toggle-count {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: system-ui, sans-serif;
    font-size: 0.72rem;
    letter-spacing: 0.02em;
    color: rgba(255, 255, 255, 0.4);
}

.server-toggle-count::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
}

.server-toggle-count.online {
    color: #4ade80;
}

.server-toggle-count.online::before {
    background: #4ade80;
    box-shadow: 0 0 6px rgba(74, 222, 128, 0.9);
}

@media (prefers-reduced-motion: reduce) {
    .ux-vault-toggle__thumb,
    .ux-vault-toggle__status span,
    .ux-circuit-path,
    .ux-thumb-icon {
        transition-duration: 0.01ms;
    }
}

.subsection-title {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.5rem;
    color: #fff;
    text-transform: uppercase;
    letter-spacing: 3px;
    margin: 0 0 1.5rem;
}

.subsection-title::after {
    content: '';
    display: block;
    width: 60px;
    height: 2px;
    margin-top: 0.5rem;
    background: linear-gradient(90deg, var(--rust-orange), transparent);
}

/* --- Live events ---------------------------------------------------------- */

/* No background of its own. Each section used to paint its own gradient, which
   made the page read as a stack of slabs with a seam at every boundary — the
   gradients alternated dark→light and light→dark, so the joins were visible
   even at low opacity. One continuous veil over the video now covers the whole
   page instead (see .rust-page-veil in rust.css). */
.live-events-section {
    background: transparent;
}

.live-events-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
    margin-bottom: 3rem;
}

.event-card {
    position: relative;
    display: flex;
    gap: 1.25rem;
    padding: 1.75rem 1.5rem 1.5rem;
    background: rgba(44, 36, 32, 0.6);
    border: 1px solid rgba(206, 66, 43, 0.3);
    border-radius: 4px;
    overflow: hidden;
}

.event-card.active {
    border-color: rgba(255, 107, 53, 0.6);
    box-shadow: 0 0 30px rgba(255, 107, 53, 0.15);
    animation: eventPulse 3s ease-in-out infinite;
}

@keyframes eventPulse {
    0%, 100% { box-shadow: 0 0 30px rgba(255, 107, 53, 0.15); }
    50%      { box-shadow: 0 0 45px rgba(255, 107, 53, 0.3); }
}

.event-live-badge {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.75rem;
    background: var(--rust-orange);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 1.5px;
    border-bottom-left-radius: 4px;
}

.event-live-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #fff;
    animation: liveDot 1.4s ease-in-out infinite;
}

@keyframes liveDot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.3; }
}

.event-icon {
    font-size: 2.5rem;
    line-height: 1;
    flex-shrink: 0;
}

.event-name {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.35rem;
    color: #fff;
    letter-spacing: 2px;
    margin: 0 0 0.25rem;
}

.event-blurb {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.6);
    margin: 0 0 0.75rem;
}

.event-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    font-size: 0.8rem;
    color: var(--rust-glow);
}

.events-quiet,
.graph-empty,
.vitals-offline {
    grid-column: 1 / -1;
    text-align: center;
    padding: 3rem 1rem;
    color: rgba(255, 255, 255, 0.5);
}

.events-quiet-icon,
.vitals-offline-icon {
    font-size: 2.5rem;
    display: block;
    margin-bottom: 0.75rem;
    opacity: 0.6;
}

.events-quiet p,
.graph-empty p,
.vitals-offline p {
    margin: 0 0 0.35rem;
    color: rgba(255, 255, 255, 0.8);
    font-size: 1.05rem;
}

.events-quiet-sub,
.graph-empty span,
.vitals-offline-sub {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.4);
}

.recent-events-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.event-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1rem;
    background: rgba(44, 36, 32, 0.4);
    border-left: 2px solid rgba(206, 66, 43, 0.4);
    font-size: 0.875rem;
    color: rgba(255, 255, 255, 0.7);
}

.event-row.killed {
    border-left-color: var(--rust-glow);
}

/* Shop purchases rather than scheduled server events — present, but not
   competing for attention with the real thing. */
.event-row.minor {
    opacity: 0.6;
    border-left-color: rgba(255, 255, 255, 0.15);
}

.event-row.minor .event-row-name {
    font-weight: 500;
    color: rgba(255, 255, 255, 0.75);
}

.event-row-name {
    color: #fff;
    font-weight: 600;
}

.event-row-killer {
    color: var(--rust-glow);
}

.event-row-grid {
    color: rgba(255, 255, 255, 0.45);
    font-family: 'Courier New', monospace;
}

.event-row-time {
    margin-left: auto;
    color: rgba(255, 255, 255, 0.4);
    white-space: nowrap;
}

.events-empty,
.online-empty,
.totals-empty {
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.9rem;
    text-align: center;
    padding: 1.5rem 0;
}

/* --- Vitals --------------------------------------------------------------- */

.vitals-section {
    background: transparent;
}

.vitals-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.vital-cell {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.25rem;
    background: rgba(44, 36, 32, 0.55);
    border: 1px solid rgba(206, 66, 43, 0.2);
    border-radius: 4px;
    text-align: center;
}

.vital-label {
    font-size: 0.7rem;
    letter-spacing: 2px;
    color: rgba(255, 255, 255, 0.45);
}

.vital-value {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 2rem;
    color: #fff;
    letter-spacing: 1px;
}

.vital-value.good { color: #4ade80; }
.vital-value.warn { color: #fbbf24; }
.vital-value.bad  { color: #ef4444; }

.queue-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.75rem;
    margin-bottom: 2rem;
    background: rgba(206, 66, 43, 0.12);
    border: 1px solid rgba(206, 66, 43, 0.3);
    border-radius: 4px;
    color: var(--rust-glow);
    font-size: 0.875rem;
    letter-spacing: 1px;
}

.queue-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--rust-glow);
    animation: liveDot 1.4s ease-in-out infinite;
}

/* --- Population graph ----------------------------------------------------- */

.population-block {
    margin-top: 3rem;
}

.population-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
}

.graph-range {
    display: flex;
    gap: 0.5rem;
}

.graph-range-btn {
    padding: 0.4rem 1rem;
    background: transparent;
    border: 1px solid rgba(206, 66, 43, 0.35);
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.75rem;
    letter-spacing: 1.5px;
    cursor: pointer;
    border-radius: 3px;
    transition: all 0.2s ease;
}

.graph-range-btn:hover {
    border-color: var(--rust-orange);
    color: #fff;
}

.graph-range-btn.active {
    background: var(--rust-orange);
    border-color: var(--rust-orange);
    color: #fff;
}

.population-graph {
    margin-top: 1.5rem;
    padding: 1rem;
    background: rgba(44, 36, 32, 0.4);
    border: 1px solid rgba(206, 66, 43, 0.2);
    border-radius: 4px;
}

.graph-svg {
    width: 100%;
    height: 260px;
    display: block;
}

.graph-grid {
    stroke: rgba(255, 255, 255, 0.07);
    stroke-width: 1;
}

.graph-axis-label {
    fill: rgba(255, 255, 255, 0.35);
    font-size: 11px;
}

.graph-line {
    stroke: var(--rust-glow);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

/* Positioning context for the tooltip, which is placed in pixels. */
.graph-plot {
    position: relative;
}

.graph-cursor {
    stroke: rgba(255, 255, 255, 0.35);
    stroke-width: 1;
    stroke-dasharray: 3 3;
    pointer-events: none;
    vector-effect: non-scaling-stroke;
}

.graph-dot {
    fill: var(--rust-glow);
    stroke: #0a0806;
    stroke-width: 2;
    pointer-events: none;
    vector-effect: non-scaling-stroke;
}

.graph-tooltip {
    position: absolute;
    z-index: 5;
    min-width: 140px;
    padding: 0.6rem 0.75rem;
    background: rgba(10, 8, 6, 0.96);
    border: 1px solid rgba(206, 66, 43, 0.5);
    border-radius: 4px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
    font-size: 0.8rem;
    /* The tooltip tracks the pointer, so it must never intercept it. */
    pointer-events: none;
}

.graph-tooltip[hidden] {
    display: none;
}

.tip-when {
    margin-bottom: 0.4rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.72rem;
    white-space: nowrap;
}

.tip-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    line-height: 1.7;
}

.tip-row.muted .tip-label,
.tip-row.muted .tip-value {
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.75rem;
}

.tip-swatch {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--rust-glow);
    flex-shrink: 0;
}

.tip-label {
    color: rgba(255, 255, 255, 0.7);
}

.tip-value {
    margin-left: auto;
    color: #fff;
    font-weight: 700;
}

.graph-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.75rem;
    padding: 0 0.5rem;
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.4);
}

.graph-peak {
    color: var(--rust-glow);
    font-weight: 600;
}

/* --- Wipe totals ---------------------------------------------------------- */

.totals-section {
    background: transparent;
}

.totals-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 1.25rem;
}

.total-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 1.75rem 1rem;
    background: rgba(44, 36, 32, 0.55);
    border: 1px solid rgba(206, 66, 43, 0.25);
    border-radius: 4px;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.total-cell:hover {
    transform: translateY(-3px);
    border-color: rgba(255, 107, 53, 0.5);
}

.total-icon {
    font-size: 1.75rem;
    opacity: 0.85;
}

.total-value {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 2.25rem;
    color: var(--rust-glow);
    letter-spacing: 1px;
    line-height: 1.1;
}

.total-label {
    font-size: 0.68rem;
    letter-spacing: 1.5px;
    color: rgba(255, 255, 255, 0.45);
    text-align: center;
}

/* --- Leaderboards --------------------------------------------------------- */

.leaderboard-section {
    background: transparent;
}

.leaderboard-layout {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 2rem;
    align-items: start;
}

.lb-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
}

.lb-tab {
    padding: 0.55rem 1.25rem;
    background: transparent;
    border: 1px solid rgba(206, 66, 43, 0.3);
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.8rem;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 3px;
    transition: all 0.2s ease;
}

.lb-tab:hover {
    border-color: var(--rust-orange);
    color: #fff;
}

.lb-tab.active {
    background: var(--rust-orange);
    border-color: var(--rust-orange);
    color: #fff;
}

.lb-body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 200px;
}

.lb-row {
    display: grid;
    grid-template-columns: 40px 1fr auto auto;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    background: rgba(44, 36, 32, 0.5);
    border-left: 2px solid transparent;
    border-radius: 3px;
    transition: background 0.2s ease;
}

.lb-row:hover {
    background: rgba(44, 36, 32, 0.8);
}

.lb-row.top-1 { border-left-color: #ffd700; }
.lb-row.top-2 { border-left-color: #c0c0c0; }
.lb-row.top-3 { border-left-color: #cd7f32; }

.lb-rank {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.5rem;
    color: rgba(255, 255, 255, 0.35);
    text-align: center;
}

.lb-row.top-1 .lb-rank { color: #ffd700; }
.lb-row.top-2 .lb-rank { color: #c0c0c0; }
.lb-row.top-3 .lb-rank { color: #cd7f32; }

.lb-name {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: #fff;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lb-online {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #4ade80;
    box-shadow: 0 0 8px rgba(74, 222, 128, 0.8);
    flex-shrink: 0;
}

.lb-sub {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.35);
    white-space: nowrap;
}

.lb-value {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.35rem;
    color: var(--rust-glow);
    letter-spacing: 1px;
    white-space: nowrap;
}

.lb-loading,
.lb-empty {
    text-align: center;
    padding: 2.5rem 1rem;
    color: rgba(255, 255, 255, 0.45);
}

.lb-empty p {
    margin: 0 0 0.35rem;
    color: rgba(255, 255, 255, 0.7);
}

.lb-empty span {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.35);
}

/* --- Leaderboard sidebar -------------------------------------------------- */

.leaderboard-side {
    display: flex;
    flex-direction: column;
    gap: 2rem;
}

.side-block {
    padding: 1.5rem;
    background: rgba(44, 36, 32, 0.4);
    border: 1px solid rgba(206, 66, 43, 0.2);
    border-radius: 4px;
}

.online-count {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.75rem;
    color: var(--rust-glow);
    letter-spacing: 2px;
    margin-bottom: 1rem;
}

.online-list {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

/* A row per player rather than wrapping pills. Rust names can be very long
   and full of decorative characters, which made a wrapped chip layout ragged
   and unreadable — a fixed row truncates instead. */
.online-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    font-size: 0.85rem;
}

.online-row:last-child { border-bottom: none; }

.online-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #4ade80;
    box-shadow: 0 0 6px rgba(74, 222, 128, 0.8);
    flex-shrink: 0;
}

.online-name {
    color: rgba(255, 255, 255, 0.9);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Without this a long name stretches the grid instead of truncating. */
    min-width: 0;
}

.online-time {
    color: var(--rust-glow);
    font-size: 0.78rem;
    white-space: nowrap;
}

/* --- Server summary (replaced the top-teams board) ------------------------ */

.summary-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0.6rem;
    padding: 0.55rem 0.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    font-size: 0.85rem;
}

.summary-row:last-child { border-bottom: none; }

.summary-icon {
    font-size: 0.95rem;
    opacity: 0.8;
}

.summary-label {
    color: rgba(255, 255, 255, 0.6);
}

.summary-value {
    color: #fff;
    font-weight: 700;
    white-space: nowrap;
}

.summary-empty {
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.9rem;
    text-align: center;
    padding: 1.5rem 0;
}

/* --- Next wipe line in the countdown panel -------------------------------- */

.wipe-next-line {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 0.75rem;
    margin: 1.5rem 0;
    padding: 0.85rem;
    background: rgba(206, 66, 43, 0.1);
    border: 1px solid rgba(206, 66, 43, 0.25);
    border-radius: 4px;
}

.wipe-next-label {
    font-size: 0.7rem;
    letter-spacing: 2px;
    color: rgba(255, 255, 255, 0.45);
}

.wipe-next-value {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.25rem;
    letter-spacing: 1px;
    color: var(--rust-glow);
}

/* --- Offline state on the hero status dot --------------------------------- */

.stat-icon-circle.is-offline .pulse-ring {
    animation: none;
    opacity: 0.2;
}

.status-dot.offline {
    background: #ef4444;
    box-shadow: 0 0 10px rgba(239, 68, 68, 0.8);
}

/* --- Map fallback --------------------------------------------------------- */

.map-fallback { cursor: pointer; }

.map-fallback p {
    color: rgba(255, 255, 255, 0.7);
    margin-top: 1rem;
}

.map-fallback-sub {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.5);
}

/* --- Monument hover markers ----------------------------------------------- */

/* Invisible hit areas sitting over the icons drawn into the map render. The
   layer ignores pointer events so the panel's own click-through still works;
   only the markers themselves take the mouse.

   Covers the panel exactly, matching .map-preview img. Marker positions are a
   percentage of the render, and out-of-bounds monuments are clamped in JS to
   the same inset RustMaps uses when drawing their icons. */
.map-monuments {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* Sized as a share of the map, not a fixed pixel count: the icons are baked
   into the render and scale with it, so a fixed 34px target covered the whole
   icon on the old half-width map but only its centre once the map went full
   width. 5.5% of the render is a close match to the drawn icon at any size. */
.map-monument {
    position: absolute;
    width: 5.5%;
    aspect-ratio: 1 / 1;
    transform: translate(-50%, -50%);   /* centre the hit area on the icon */
    border-radius: 50%;
    pointer-events: auto;
    cursor: help;
}

/* A faint ring on hover confirms which icon the label belongs to. */
.map-monument:hover {
    background: rgba(255, 255, 255, 0.12);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

/* Highlighted from the pill list: a ring drawn over the RustMaps icon that
   already sits in the render. Deliberately translucent and slightly larger
   than the hit area so the icon underneath stays readable — the ring marks
   the icon rather than replacing it. */
/* Uses the same colour as the pill that triggered it, so the ring on the map
   and the lit pill are obviously the same thing. */
.map-monument.is-highlighted {
    background: var(--pill-fill, #ff6b35);
    box-shadow:
        0 0 0 3px var(--pill-edge, #ff8c42),
        0 0 22px 6px var(--pill-edge, #ff8c42);
    z-index: 4;
    animation: monument-pulse 0.9s ease-in-out infinite;
}

/* The circle itself grows and shrinks. Every keyframe repeats the centring
   translate: an animated transform replaces the one on .map-monument outright,
   so omitting it would snap the marker down-right by half its own size.
   A wide swing on a short cycle — the job is to catch the eye immediately,
   not to breathe politely. */
@keyframes monument-pulse {
    0%, 100% { transform: translate(-50%, -50%) scale(1.15); }
    50%      { transform: translate(-50%, -50%) scale(2.3); }
}

/* A ring that expands outward and fades, like a radar ping. Drawn as a
   pseudo-element so it can travel well beyond the marker without affecting
   the hit area or the circle's own pulse. */
.map-monument.is-highlighted::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    border: 2px solid var(--pill-edge, #ff8c42);
    animation: monument-ping 0.9s ease-out infinite;
    pointer-events: none;
}

@keyframes monument-ping {
    0%   { transform: scale(1);   opacity: 0.9; }
    100% { transform: scale(3.2); opacity: 0; }
}

.map-monument {
    transition: background 0.18s ease, box-shadow 0.18s ease;
}

/* While a pill is hovered, darken the map so the pulsing marker is the only
   bright thing on it. Far more effective than the pulse alone — the eye goes
   straight there instead of scanning 77 icons. */
.map-preview.has-highlight img {
    filter: contrast(1.1) brightness(0.45) saturate(0.6);
}

.map-preview img {
    transition: filter 0.25s ease;
}

/* A looping pulse is the kind of motion this setting exists to stop. The
   highlight still reads clearly — it holds at a steady enlarged size, and the
   dimmed map still points the eye at it. */
@media (prefers-reduced-motion: reduce) {
    .map-monument.is-highlighted {
        animation: none;
        transform: translate(-50%, -50%) scale(1.7);
    }

    .map-monument.is-highlighted::after {
        animation: none;
        opacity: 0.5;
        transform: scale(1.6);
    }
}

.map-monument-label {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 5;

    display: none;
    white-space: nowrap;
    padding: 0.35rem 0.6rem;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: rgba(10, 8, 6, 0.95);
    color: var(--text);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.6);
}

.map-monument:hover .map-monument-label { display: block; }

/* Near the right edge the label would be clipped, so anchor its right side to
   the marker and let it run leftward instead of centring. */
.map-monument-label.flip-x {
    left: auto;
    right: 50%;
    transform: none;
}

/* Near the top there is no room above the icon, so drop the label below it. */
.map-monument-label.flip-y {
    bottom: auto;
    top: calc(100% + 8px);
}

/* Category accents, matching the grouping used by the desktop app. */
.map-monument-safezone:hover { box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.9); }
.map-monument-hostile:hover  { box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.9); }
.map-monument-resource:hover { box-shadow: 0 0 0 2px rgba(255, 165, 82, 0.9); }
.map-monument-water:hover    { box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.9); }

.map-monument-safezone .map-monument-label { border-color: rgba(74, 222, 128, 0.6); }
.map-monument-hostile .map-monument-label  { border-color: rgba(239, 68, 68, 0.6); }
.map-monument-resource .map-monument-label { border-color: rgba(255, 165, 82, 0.6); }
.map-monument-water .map-monument-label    { border-color: rgba(96, 165, 250, 0.6); }

/* Coarse pointers (phones, tablets) cannot hover, and the targets are packed
   too tightly to tap reliably — hide them rather than misbehave. The pill list
   still works, since tapping a pill highlights the marker. */
@media (hover: none) {
    .map-monument:hover { background: none; box-shadow: none; }
    .map-monument:hover .map-monument-label { display: none; }
}

/* --- Monument pill list --------------------------------------------------- */

/* Scoped to this block so the other stat labels keep their display: block. */
.monuments-block .stat-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.monument-count {
    margin-left: auto;
    font-size: 0.75rem;
    color: var(--text-muted);
    letter-spacing: 0.05em;
}

.monument-pills {
    /* A grid rather than a wrapping flex row. Sizing pills to their text made
       "Ranch" a circle and "Tunnel Entrance Transition" a long oval, so no two
       lines agreed on height or edge. Equal columns give one repeating shape;
       auto-fill keeps as many per row as the card is wide. */
    display: grid;
    /* 9rem is wide enough for the longest two-line names — "Arctic Research
       Base A", "Tunnel Entrance Transition" — to fit without being clipped.
       Fewer columns means more rows, which is fine now that rows stretch to
       fill the card rather than leaving a gap below the last one. */
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    /* Rows divide the card's height between them instead of each taking its
       natural height and leaving a gap at the bottom. 1fr keeps every row the
       same size as the others, so filling the space does not make the pills
       uneven — which is what the earlier stretch-without-1fr did. */
    grid-auto-rows: 1fr;
    gap: 0.5rem;
    margin-top: 0.9rem;
    /* Fills whatever height the card has rather than a fixed cap, so the list
       ends level with the map beside it and scrolls only if it overflows. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0.35rem;
}


.monument-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    /* Fills its grid cell, so every pill matches whether its label wraps or
       not and the rows stay level as they stretch. */
    height: 100%;
    min-height: 2.4rem;
    padding: 0.4rem 0.7rem;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.82rem;
    line-height: 1.2;
    text-align: center;
    cursor: pointer;
    /* Long names shrink to fit rather than widening the cell. */
    overflow: hidden;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/* Two lines maximum, then ellipsis. The full name is on the title attribute,
   and hovering highlights the marker anyway, so a clipped label still works. */
.monument-pill-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

/* Each pill carries its own --pill-fill / --pill-edge, set in JS from a hash
   of the monument name. Only the hue varies — saturation and lightness are
   pinned at values that stay legible on the dark card. */
/* --pill-fill and --pill-edge are complete colour values set from JS, not a
   bare hue fed into hsl(). A custom property substituted inside hsl() only
   resolves at computed-value time, and anything the function cannot parse
   makes the whole declaration invalid — the property then falls back to its
   inherited value rather than to the base rule, so the hover silently did
   nothing. Passing finished colours removes that failure mode. */
.monument-pill:hover,
.monument-pill.is-active,
.monument-pill:focus-visible {
    background: var(--pill-fill, #c2410c);
    border-color: var(--pill-edge, #ea580c);
    color: #fff;
    outline: none;
}

.monument-pill-count {
    font-size: 0.78rem;
    opacity: 0.65;
}

/* Category tints, matching the marker rings and the desktop app's chips. */
/* Resting-state category tints. Scoped with :not(:hover) so they cannot
   override the hover rule above — being later in the file and equally
   specific, they were repainting the border back to the category colour while
   the fill took the monument's hue, which read as a broken edge. */
.monument-pill-safezone:not(:hover):not(.is-active) { border-color: rgba(74, 222, 128, 0.35); }
.monument-pill-hostile:not(:hover):not(.is-active)  { border-color: rgba(239, 68, 68, 0.35); }
.monument-pill-resource:not(:hover):not(.is-active) { border-color: rgba(255, 165, 82, 0.35); }
.monument-pill-water:not(:hover):not(.is-active)    { border-color: rgba(96, 165, 250, 0.35); }

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 968px) {
    .leaderboard-layout {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 640px) {
    .lb-row {
        grid-template-columns: 32px 1fr auto;
    }

    .lb-sub { display: none; }

    /* Seven boards wrap to four stacked rows at this width, which pushes the
       leaderboard itself off screen. Scroll them sideways in one row instead.
       min-width:0 is what makes that work: without it the nowrap row sizes to
       its content and stretches the grid column, overflowing the whole page. */
    .leaderboard-main,
    .lb-tabs {
        min-width: 0;
    }

    .lb-tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 0.25rem;
    }

    .lb-tabs::-webkit-scrollbar { display: none; }

    .lb-tab {
        flex: 0 0 auto;
    }

    .event-row {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    .event-row-time {
        margin-left: 0;
        width: 100%;
    }

    .graph-svg { height: 200px; }

    .vital-value { font-size: 1.6rem; }

    .total-value { font-size: 1.75rem; }
}

/* Respect users who have asked for less motion. The pulsing badges are
   decorative; the data they sit on is unaffected. */
@media (prefers-reduced-motion: reduce) {
    .event-card.active,
    .event-live-dot,
    .queue-dot {
        animation: none;
    }
}
