/* APRS Thursday — the SpaceAPRS look: one dark theme, because the globe sits in space and the page is its frame. */
:root {
    --bg: #07090f;
    --panel: rgba(12, 16, 26, 0.78);
    --panel-solid: #0e1320;
    --line: rgba(255, 255, 255, 0.08);
    --line-strong: rgba(255, 255, 255, 0.16);
    --text: #e6ebf5;
    --muted: #8b95ab;
    --faint: #5b6478;
    --amber: #f2b84b;
    --amber-dim: rgba(242, 184, 75, 0.35);
    --iss: #7fb4ff; --blue: #7fb4ff;
    --ok: #5fd39a;
    --warn: #f2b84b;
    --bad: #ff6b6b;
    --radius: 12px;
    --font: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
    color-scheme: dark;
}

* { box-sizing: border-box; }
/* No blue flash on a tap: Android Chrome tints whatever element owns the click handler, and
   here that is a whole table, list or chart, not the row that was tapped. */
* { -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
html { overflow-x: hidden; }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.45 var(--font);
    font-feature-settings: "tnum" 1;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}
a { color: var(--iss); text-decoration: none; }
a:hover { text-decoration: underline; }
code { font-family: var(--mono); font-size: 0.92em; color: var(--amber); }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
button { font: inherit; color: inherit; }

/* Header */
.top {
    position: relative;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 10px 18px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(to bottom, rgba(7, 9, 15, 0.95), rgba(7, 9, 15, 0.75));
    backdrop-filter: blur(10px);
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); font-weight: 650; font-size: 15px; letter-spacing: 0.01em; }
.brand:hover { text-decoration: none; }
.brand-mark { width: 24px; height: 24px; color: var(--amber); }
.nav { display: flex; gap: 4px; }
.menu-btn { display: none; width: 34px; height: 34px; border: 1px solid var(--line); border-radius: 9px; background: transparent; color: var(--muted); cursor: pointer; padding: 0; place-items: center; }
.menu-btn svg { width: 18px; height: 18px; }
.menu-btn[aria-expanded="true"] { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.nav a { color: var(--muted); padding: 6px 10px; border-radius: 8px; }
.nav a.on, .nav a:hover { color: var(--text); background: rgba(255, 255, 255, 0.05); text-decoration: none; }
/* The link to the sibling site: the same as the page links, marked only as leaving. */
.nav a.ext::after { content: " ↗"; font-size: 11px; }
/* Which satellite: a small segmented control ahead of the page links. */
.nav .platform-seg { margin-right: 8px; align-self: center; }
.nav .platform-seg a { padding: 4px 10px; border-radius: 7px; font-size: 12.5px; white-space: nowrap; }
.nav .platform-seg a.on { background: rgba(255, 255, 255, 0.1); }
.powered-top { margin-left: auto; display: inline-flex; align-items: center; gap: 9px; padding: 5px 12px 5px 6px; border-radius: 999px; border: 1px solid rgba(242, 184, 75, 0.35); background: rgba(242, 184, 75, 0.08); color: var(--text); font-size: 13.5px; }
.powered-top:hover { text-decoration: none; border-color: var(--amber); background: rgba(242, 184, 75, 0.14); }
.powered-top img { width: 26px; height: 26px; border-radius: 7px; }
.powered-top span { color: var(--muted); }
.powered-top b { color: var(--amber); font-weight: 650; }
.status { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12.5px; }
.status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); box-shadow: 0 0 0 0 transparent; }
.status.ok .dot { background: var(--ok); box-shadow: 0 0 10px rgba(95, 211, 154, 0.6); }
.status.warn .dot { background: var(--warn); }
.status.bad .dot { background: var(--bad); }

/* Footer */
.foot {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 10px 18px;
    border-top: 1px solid var(--line);
    color: var(--faint);
    font-size: 12px;
    background: var(--bg);
    position: relative;
    z-index: 5;
}
.foot a { color: var(--muted); }
.legal { color: var(--faint); }
.legal a { color: var(--muted); }
.made-in { color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.flag { width: 19px; height: 10px; border-radius: 1.5px; box-shadow: 0 0 0 1px rgba(255,255,255,0.12); }
.powered { color: var(--muted); }
.powered a { color: var(--amber); font-weight: 600; }

/* An emergency packet heard through the station: a red bar across the top, above the map,
   one line per packet, until dismissed or a day old. */
.alert-bar { background: rgba(255, 107, 107, 0.14); border-bottom: 1px solid rgba(255, 107, 107, 0.5); color: var(--text); font-size: 13.5px; }
.alert-bar[hidden] { display: none; }
.demo-bar { background: rgba(242, 184, 75, 0.12); border-bottom: 1px solid rgba(242, 184, 75, 0.45); color: var(--text); font-size: 13.5px; }
.demo-bar .alert-inner { align-items: center; }
.alert-tag.demo { background: var(--amber); color: #1f1602; margin-top: 0; }
.demo-x { font-size: 18px; line-height: 1; padding: 0 8px 2px; margin-left: auto; }
.alert-inner { display: flex; align-items: flex-start; gap: 14px; padding: 8px 16px; }
.alert-tag { flex-shrink: 0; display: inline-flex; align-items: center; gap: 7px; padding: 2px 9px; border-radius: 999px; background: var(--bad); color: #1a0606; font-weight: 800; font-size: 11.5px; letter-spacing: 0.08em; margin-top: 2px; }
.alert-tag .dot { width: 7px; height: 7px; border-radius: 50%; background: #1a0606; animation: alertPulse 1.2s ease-in-out infinite; }
@keyframes alertPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.alert-items { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.alert-items .row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.alert-items .call { font-family: var(--mono); font-weight: 700; color: var(--bad); text-decoration: none; }
.alert-items .call:hover { text-decoration: underline; }
.alert-items .when { color: var(--muted); font-size: 12.5px; }
.alert-items .info { font-family: var(--mono); font-size: 12.5px; color: var(--text); overflow-wrap: anywhere; }
.alert-items .show { background: none; border: 1px solid var(--line-strong); color: var(--muted); border-radius: 6px; padding: 1px 8px; font-size: 11.5px; cursor: pointer; }
.alert-items .show:hover { color: var(--text); border-color: var(--bad); }
.alert-x { flex-shrink: 0; background: none; border: 1px solid var(--line-strong); color: var(--muted); border-radius: 6px; padding: 3px 10px; font-size: 12px; cursor: pointer; }
.alert-x:hover { color: var(--text); }
.ticker li.emergency b, .ticker li.emergency .info { color: var(--bad); }
.ticker li.emergency { background: rgba(255, 107, 107, 0.08); }

/* Live page: the globe fills the main area and cards float on it. */
body.live { height: 100vh; overflow: hidden; }
.live-main { position: relative; flex: 1; min-height: 0; }
.globe {
    position: absolute; inset: 0;
    background:
        radial-gradient(ellipse at 30% 20%, rgba(40, 60, 110, 0.25), transparent 60%),
        radial-gradient(ellipse at 70% 80%, rgba(90, 50, 30, 0.14), transparent 55%),
        var(--bg);
}
.globe .maplibregl-canvas { outline: none; }
/* The leg from the sub-satellite point up to the lifted station icon, and the icon itself as a
   marker (see updateLift); the label rides above it as the symbol layer's did. */
.globe .iss-leg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.iss-float { cursor: pointer; line-height: 0; } /* MapLibre positions the marker itself */
.iss-float img { display: block; width: 58px; height: auto; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6)); }
.iss-float .lbl { position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%); margin-bottom: 4px; font: 500 12px/1 var(--font); color: #cfe2ff; white-space: nowrap; text-shadow: 0 0 2px #07090f, 0 0 2px #07090f, 0 0 3px #07090f; }
/* The OpenStreetMap credit lives on the map, as the licence asks: MapLibre's compact control,
   a small (i) that opens on tap, styled to the page. */
.maplibregl-ctrl-attrib { background: rgba(12, 16, 26, 0.9) !important; border-radius: 8px; font-size: 11px; }
.maplibregl-ctrl-attrib, .maplibregl-ctrl-attrib-inner, .maplibregl-ctrl-attrib a { color: var(--muted) !important; }
.maplibregl-ctrl-attrib a:hover { color: var(--text) !important; }
.maplibregl-ctrl-attrib-button { filter: invert(0.8); }
/* Sits above the net bar; the script keeps the offset equal to the bar's height. */
/* The map credit in the bottom corner, level with the net bar, which is a small card in the middle. */
.live .maplibregl-ctrl-bottom-right { right: 372px; bottom: 4px; z-index: 4; } /* + MapLibre's own 10px margin */
/* The zoom buttons sit just left of the right-hand panel, not under it. */
.live .maplibregl-ctrl-top-right { right: 352px; top: 16px; }
.live .maplibregl-ctrl-group { background: var(--panel-solid); border: 1px solid var(--line-strong); box-shadow: 0 6px 20px rgba(0,0,0,.4); }
.live .maplibregl-ctrl-group button { background-color: transparent; }
.live .maplibregl-ctrl-group button + button { border-top-color: var(--line); }
.live .maplibregl-ctrl button .maplibregl-ctrl-icon { filter: invert(0.85); }
.hud { position: absolute; z-index: 3; display: flex; flex-direction: column; gap: 12px; pointer-events: none; }
.hud > * { pointer-events: auto; }
.hud-left { top: 16px; left: 16px; width: 300px; }
.hud-right { top: 16px; right: 16px; width: 340px; bottom: 14px; }
.hud-bottom { left: 16px; right: 372px; bottom: 14px; flex-direction: row; align-items: center; gap: 12px; }
.card {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 14px 16px;
    backdrop-filter: blur(14px) saturate(1.1);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}
.card { position: relative; }
.card-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
/* Fold: a chevron in the card's corner. Collapsed, the card is its header and nothing else. */
.fold { position: absolute; top: 10px; right: 10px; width: 22px; height: 22px; border: 0; border-radius: 6px; background: transparent; color: var(--faint); cursor: pointer; display: grid; place-items: center; padding: 0; }
.fold:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.fold svg { width: 12px; height: 12px; transition: transform 0.2s ease; }
.card.collapsed .fold svg { transform: rotate(-90deg); }
.card[data-collapsible] .card-head { padding-right: 26px; }
.card.collapsed { flex: 0 0 auto !important; min-height: 0; }
.card.collapsed > :not(.card-head):not(.fold) { display: none !important; }
.card.collapsed .card-head { margin-bottom: 0; }
.card.collapsed .card-head .seg, .card.collapsed .card-head .freq, .card.collapsed .card-head .live-dot { display: none; }
/* On a wide screen a folded card is a square the size and style of a map button, showing what
   it holds; the header would otherwise sit there as an empty bar. The right-hand ones line up
   under the zoom buttons (the script places them from the control column's measurements), so
   the card left open has the whole column. Phones keep the header, where the words help. */
@media (min-width: 901px) {
    .card.collapsed {
        width: 31px; height: 31px; padding: 0; flex: 0 0 31px !important; min-height: 31px;
        border-radius: 4px; background: var(--panel-solid); border: 1px solid var(--line-strong);
        box-shadow: 0 6px 20px rgba(0,0,0,.4); backdrop-filter: none;
    }
    .hud-right .card.collapsed { align-self: flex-end; }
    .hud-left .card.collapsed { align-self: flex-start; }
    .card.collapsed .card-head { display: none; }
    .card.collapsed .fold { position: static; width: 100%; height: 100%; border-radius: 3px; color: #e6ebf5; }
    .card.collapsed .fold:hover { color: var(--amber); }
    .card.collapsed .fold svg { width: 16px; height: 16px; transform: none; }
    .card.collapsed .fold .chev { display: none; }
    .card:not(.collapsed) .fold .glyph { display: none; }
    /* With both right-hand cards folded the column is two small squares, so the map takes the
       width back: the squares tuck under the map buttons (the script sets their top), and the
       time bar and the credit run to the edge. */
    .side-folded .hud-bottom { right: 16px; }
    .live.side-folded .maplibregl-ctrl-top-right { right: 6px; }
    .live.side-folded .maplibregl-ctrl-bottom-right { right: 16px; }
}
@media (max-width: 900px) {
    .fold .glyph { display: none; }
}
.card-head.row { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; }
.card-head.row h2 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-head.row .seg { flex-shrink: 0; }
.card h2 { font-size: 13px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.platform-name { font-size: 17px; }
.freq { color: var(--muted); font-size: 12.5px; }
.iss-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; margin: 0; }
.iss-facts div { display: flex; flex-direction: column; }
.iss-facts dt, .facts dt { color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.iss-facts dd, .facts dd { margin: 0; font-size: 14px; }
.quiet { margin: 10px 0 0; padding: 8px 10px; border-radius: 8px; background: rgba(242, 184, 75, 0.1); color: var(--amber); font-size: 12.5px; border: 1px solid var(--amber-dim); }
.counts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 12px 14px; }
.counts div { display: flex; flex-direction: column; }
.counts b { font-size: 20px; font-weight: 600; letter-spacing: -0.02em; }
.counts span { color: var(--faint); font-size: 11px; }

.feed-card { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 8px var(--amber-dim); opacity: 0.55; }
.live-dot.blink { animation: blink 0.9s ease-out; }
@keyframes blink { from { opacity: 1; box-shadow: 0 0 14px var(--amber); } to { opacity: 0.55; box-shadow: 0 0 8px var(--amber-dim); } }
.stations { list-style: none; margin: 0; padding: 0; overflow: auto; flex: 1; min-height: 0; margin: 0 -8px; }
.stations li { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto; gap: 0 10px; padding: 7px 8px; border-radius: 8px; cursor: pointer; border-bottom: 1px solid var(--line); }
.stations li:hover { background: rgba(255, 255, 255, 0.04); }
.stations li.pass { border-left: 2px solid var(--amber); padding-left: 6px; }
.stations li.new { animation: flash 1.6s ease-out; }
.stations .call { font-family: var(--mono); font-weight: 600; font-size: 13.5px; color: var(--text); }
.stations .when { color: var(--muted); font-size: 12px; text-align: right; }
.stations .meta { grid-column: 1 / -1; color: var(--faint); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stations .n { color: var(--amber); }
.empty { color: var(--faint); text-align: center; padding: 20px 0; }
@keyframes flash { from { background: rgba(242, 184, 75, 0.25); } to { background: transparent; } }

.controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pan-btn { padding: 4px 8px; font-size: 16px; line-height: 1; color: var(--muted); }
.pan-btn:disabled { opacity: 0.3; cursor: default; }
.seg { display: inline-flex; background: var(--panel); border: 1px solid var(--line); border-radius: 9px; padding: 2px; backdrop-filter: blur(10px); }
.seg button { background: transparent; border: 0; padding: 5px 11px; border-radius: 7px; color: var(--muted); cursor: pointer; font-size: 12.5px; white-space: nowrap; }
.seg button.on { background: rgba(255, 255, 255, 0.1); color: var(--text); }
.btn { background: var(--panel); border: 1px solid var(--line); border-radius: 9px; padding: 7px 12px; color: var(--muted); cursor: pointer; font-size: 12.5px; backdrop-filter: blur(10px); }
.btn:hover { color: var(--text); border-color: var(--line-strong); }
.btn[aria-pressed="true"] { color: var(--iss); border-color: rgba(127, 180, 255, 0.4); }
/* The map's own buttons, stacked under the zoom buttons: full screen, globe/flat, follow,
   and an options menu for the overlays. */
.map-btns button { display: grid; place-items: center; }
.map-btns svg, .fs-ctrl svg { width: 16px; height: 16px; color: #e6ebf5; }
.map-btns button[aria-pressed="true"] svg { color: var(--amber); }
.map-btns .ic-flat, .map-btns[data-view="flat"] .ic-globe { display: none; }
.map-btns[data-view="flat"] .ic-flat { display: block; }
/* Demo mode: a circling arrow to start the globe turning, pause bars while it turns. */
.demo-ctrl .ic-pause, .demo-ctrl button[aria-pressed="true"] .ic-spin { display: none; }
.demo-ctrl button[aria-pressed="true"] .ic-pause { display: block; }
.map-options { position: absolute; right: calc(100% + 8px); top: 0; background: var(--panel-solid); border: 1px solid var(--line-strong); border-radius: 10px; padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; white-space: nowrap; box-shadow: 0 10px 30px rgba(0,0,0,.45); }
.map-options .chk { background: transparent; border: 0; padding: 4px 2px; backdrop-filter: none; color: var(--text); }
.map-options[hidden] { display: none; }
.north-ctrl[hidden] { display: none; }
.north-ctrl .needle { transition: transform 0.2s ease; }
.map-toast { position: absolute; left: 50%; top: 18px; transform: translateX(-50%); z-index: 4; background: var(--panel-solid); border: 1px solid var(--line-strong); border-radius: 9px; padding: 8px 12px; font-size: 13px; color: var(--text); box-shadow: 0 10px 30px rgba(0,0,0,.45); }
.map-toast[hidden] { display: none; }
.map-toast .btn { margin-left: 10px; padding: 3px 10px; font-size: 12.5px; }
.maplibregl-ctrl-group.map-btns { position: relative; overflow: visible; }
/* Full screen lives with the zoom buttons in the map's top-right corner, as a map control. */
.fs-ctrl button { display: grid; place-items: center; }
.fs-ctrl svg { width: 15px; height: 15px; color: #e6ebf5; }
.fs-ctrl .fs-close { display: none; }
.fs-ctrl[aria-pressed="true"] .fs-open { display: none; }
.fs-ctrl[aria-pressed="true"] .fs-close { display: block; }
.live-main:fullscreen { background: var(--bg); }
.powered-fs { display: none; }
@media (min-width: 1200px) {
    .live-main:fullscreen .powered-fs { display: inline-flex; position: absolute; left: 16px; bottom: 14px; z-index: 3; margin: 0; background: rgba(12, 16, 26, 0.85); backdrop-filter: blur(10px); }
}
.chk { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12.5px; background: var(--panel); border: 1px solid var(--line); border-radius: 9px; padding: 6px 10px; backdrop-filter: blur(10px); cursor: pointer; }
.chk input { accent-color: var(--amber); margin: 0; }

.ticker { list-style: none; margin: 0 -8px; padding: 0; overflow: auto; flex: 1; min-height: 0; font-family: var(--mono); font-size: 11.5px; color: var(--muted); }
.ticker li { display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; padding: 5px 8px; border-bottom: 1px solid var(--line); animation: slide 0.35s ease-out; }
.ticker li .t { color: var(--faint); }
.ticker li b { color: var(--amber); font-weight: 600; }
.ticker li.beacon b { color: var(--iss); }
.ticker li .hdr { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ticker li .info { grid-column: 1 / -1; color: var(--text); opacity: 0.85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes slide { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.maplibregl-popup-content { background: var(--panel-solid); color: var(--text); border: 1px solid var(--line-strong); border-radius: 10px; padding: 10px 12px; font: 12.5px/1.4 var(--font); box-shadow: 0 10px 30px rgba(0,0,0,.5); }
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip { border-top-color: var(--panel-solid); }
.maplibregl-popup-anchor-top .maplibregl-popup-tip { border-bottom-color: var(--panel-solid); }
.maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: var(--panel-solid); }
.maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: var(--panel-solid); }
.maplibregl-popup-close-button { color: var(--muted); font-size: 16px; padding: 2px 6px; }
.popup .call { font-family: var(--mono); font-weight: 600; font-size: 14px; }
.popup .muted { color: var(--muted); }

/* Ordinary pages */
.page { width: min(1080px, 100% - 36px); margin: 0 auto; padding: 28px 0 40px; flex: 1; }
.page-head { margin-bottom: 20px; }
.crumb { color: var(--faint); font-size: 12.5px; margin: 0 0 6px; }
.crumb a { color: var(--muted); }
.page h1 { font-size: 26px; }
.page h1 small { color: var(--muted); font-weight: 400; font-size: 15px; }
.page h1 .call { font-family: var(--mono); }
.lede { color: var(--muted); margin: 6px 0 0; }
.links { display: flex; gap: 14px; margin: 8px 0 0; font-size: 13px; }
/* On a made-up station's page the outside links open this note instead of leaving the site. */
.demo-dialog { background: var(--panel-solid); color: var(--text); border: 1px solid rgba(242, 184, 75, 0.5); border-radius: var(--radius); padding: 18px 20px; max-width: min(440px, calc(100% - 32px)); font-size: 14px; line-height: 1.5; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); }
.demo-dialog::backdrop { background: rgba(7, 9, 15, 0.7); }
.demo-dialog p { margin: 0 0 14px; }
.demo-dialog b { color: var(--amber); }
.page .card { margin-bottom: 16px; }
.page .card h2 { margin: 6px 0 10px; }
.station-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.station-grid.one { grid-template-columns: 1fr; }
/* A net's countries, a long list: flowed into columns so the card is as tall as it needs, no more. */
ul.plain.columns { columns: 4 220px; column-gap: 24px; }
ul.plain.columns li { break-inside: avoid; }
/* The hour chart across the whole card, tall enough to read the day's shape. */
.spark.hours.wide { width: 100%; height: 140px; }
.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 16px; margin: 0 0 14px; }
.facts div { display: flex; flex-direction: column; }
.facts dd { font-size: 14px; }
.facts dd a { font-family: var(--mono); }
.map-card { padding: 0; overflow: hidden; }
.mini-map { height: 100%; min-height: 320px; background: var(--bg); }
.spark { width: 100%; height: 60px; display: block; }
.mono { font-family: var(--mono); font-size: 12.5px; color: var(--muted); word-break: break-all; }
.plain { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px; }
.plain li { display: flex; justify-content: space-between; gap: 8px; border-bottom: 1px solid var(--line); padding: 4px 0; font-size: 13px; }
.plain time { color: var(--muted); font-size: 12px; white-space: nowrap; }
.spark rect { fill: var(--amber); }
.spark line { stroke: var(--line-strong); }
table { width: 100%; border-collapse: collapse; }
th { text-align: left; color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; padding: 6px 8px; border-bottom: 1px solid var(--line); }
td { padding: 7px 8px; border-bottom: 1px solid var(--line); vertical-align: top; font-size: 13px; }
td.num, th.num { text-align: right; }
td .call, .stations-table .call { font-family: var(--mono); font-weight: 600; }
.packets td:nth-child(1) { white-space: nowrap; color: var(--muted); font-family: var(--mono); font-size: 12px; }
.packets td:nth-child(2) { font-family: var(--mono); font-size: 12px; color: var(--muted); white-space: nowrap; }
.packets td:nth-child(2) b { color: var(--amber); font-weight: 600; }
.packets td:nth-child(3) { font-family: var(--mono); font-size: 12px; overflow-wrap: anywhere; }
.filter { display: flex; gap: 8px; margin: 0 0 16px; }
.filter input { background: var(--panel-solid); border: 1px solid var(--line-strong); color: var(--text); border-radius: 9px; padding: 8px 10px; font: inherit; font-family: var(--mono); text-transform: uppercase; width: 220px; }
/* The packets page: a row of filters that wraps, and a wide table that scrolls sideways on a phone. */
.filter.wide { flex-wrap: wrap; align-items: center; }
.filter select { background: var(--panel-solid); border: 1px solid var(--line-strong); color: var(--text); border-radius: 9px; padding: 8px 10px; font: inherit; max-width: 240px; }
.filter .lbl { color: var(--muted); font-size: 12.5px; }
.filter a.clear { color: var(--muted); font-size: 12.5px; margin-left: auto; }
.table-scroll { overflow-x: auto; margin: 0 -8px; padding: 0 8px; }
.packets-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.packets-table th { text-align: left; color: var(--muted); font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; padding: 8px 8px; border-bottom: 1px solid var(--line-strong); white-space: nowrap; }
.packets-table th a { color: inherit; text-decoration: none; }
.packets-table th a:hover, .packets-table th.on a { color: var(--text); }
.packets-table td { padding: 7px 8px; border-bottom: 1px solid var(--line); vertical-align: top; white-space: nowrap; }
.packets-table td.info { white-space: normal; font-family: var(--mono); font-size: 12px; color: var(--text); opacity: 0.9; min-width: 260px; word-break: break-all; }
.packets-table td.when { color: var(--muted); font-family: var(--mono); font-size: 12px; }
.packets-table tr.beacon .call { color: var(--iss); }
.packets-table tr.emergency td { background: rgba(255, 107, 107, 0.08); }
.packets-table tr.emergency .call { color: var(--bad); }
.packets-table .flag { font-size: 15px; margin-right: 5px; vertical-align: -1px; }
/* Windows has no flag glyphs and shows two letters instead; there the flag is a small code badge. */
html.no-flags .flag { font-size: 0; }
html.no-flags .flag::after { content: attr(data-code); font: 600 10px/1 var(--mono); color: var(--muted); border: 1px solid var(--line-strong); border-radius: 4px; padding: 2px 4px; vertical-align: 1px; }
.packets-table .muted { color: var(--faint); }
.summary { color: var(--muted); font-size: 12.5px; margin: 0 0 10px; }
.pager { display: flex; gap: 14px; justify-content: flex-end; padding-top: 10px; }
.prose { max-width: 720px; }

/* Passes */
.passes-form { flex-wrap: wrap; }
.muted-line { color: var(--muted); font-size: 12.5px; margin: 0 0 12px; }
.choices { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 6px; max-width: 640px; }
.choices button { width: 100%; text-align: left; background: var(--panel-solid); border: 1px solid var(--line-strong); color: var(--text); border-radius: 9px; padding: 8px 10px; cursor: pointer; }
.choices button:hover { border-color: var(--amber); }
.now-banner { margin: 0 0 12px; padding: 8px 10px; border-radius: 8px; background: rgba(127, 180, 255, 0.1); border: 1px solid rgba(127, 180, 255, 0.35); color: var(--iss); font-size: 13px; }
.passes td { font-size: 13.5px; }
.passes td b { font-weight: 600; font-family: var(--mono); }
.passes .dim { color: var(--muted); font-size: 12px; }
.q { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; border: 1px solid var(--line-strong); color: var(--muted); }
.q-hi { color: var(--ok); border-color: rgba(95, 211, 154, 0.4); }
.q-mid { color: var(--amber); border-color: var(--amber-dim); }
.prose p { color: #c6cddb; line-height: 1.6; }
.prose h2 { font-size: 15px; margin: 22px 0 6px; color: var(--text); }

@media (max-width: 900px) {
    body.live { height: auto; overflow: auto; }
    .live-main { height: auto; }
    /* Short enough that the top of the stations card shows under it, so the page reads as
       having more below and a finger on the card scrolls; a finger on the map pans the map. */
    .globe { position: relative; height: 52vh; }
    .scroll-cue { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); z-index: 3; display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px 5px 13px; border-radius: 999px; border: 1px solid var(--line-strong); background: rgba(12, 16, 26, 0.85); color: var(--muted); font: 500 12px/1 var(--font); cursor: pointer; backdrop-filter: blur(6px); }
    .scroll-cue svg { width: 11px; height: 11px; }
    .scroll-cue[hidden] { display: none; }
    .hud { position: static; width: auto; padding: 12px 12px 0; }
    .hud-right { bottom: auto; }
    .hud-bottom { flex-direction: column; align-items: stretch; padding-bottom: 12px; overflow: hidden; }
    /* Stacked under the map: the picker takes the row, arrows at the edges, date in the middle. */
    .netbar { flex: none; min-width: 0; }
    .net-pick { min-width: 0; }
    /* Stacked under the map the cards have no height to inherit, so the lists scroll inside a
       cap instead of running the page on for hundreds of rows. */
    .feed-card { flex: none; }
    .stations { max-height: 300px; }
    .live-main, body.live { overflow-x: hidden; }
    .live .maplibregl-ctrl-top-right { right: 0; top: 0; }
    .live .maplibregl-ctrl-bottom-right { right: 0; bottom: 0; }
    /* The bar wraps: the tag and Dismiss share the first line, each packet takes the full width. */
    .alert-inner { flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 8px 12px; }
    .alert-inner .alert-x { order: 2; margin-left: auto; }
    .alert-items { order: 3; flex: 1 1 100%; gap: 8px; }
    .alert-items .row { gap: 2px 8px; }
    /* The demo notice stays one row: tag, text, the × — the text wraps, the rest does not. */
    .demo-bar { font-size: 12.5px; }
    .demo-bar .alert-inner { flex-wrap: nowrap; align-items: flex-start; gap: 8px; padding: 7px 10px 7px 12px; }
    .demo-bar .alert-items { order: 0; flex: 1 1 auto; }
    .demo-bar .alert-tag { margin-top: 1px; }
    .demo-bar .alert-x { order: 0; margin-left: 0; margin-top: -2px; }
    .powered-top { padding: 4px 8px 4px 4px; font-size: 12.5px; }
    .powered-top span { display: none; }
    .station-grid { grid-template-columns: 1fr; }
    /* The station page's packet table: three columns do not fit a phone, and a path that
       may not wrap left the info column three characters wide. Each packet becomes two lines,
       the time and path on the first, the info on its own underneath. */
    .packets thead { display: none; }
    .packets tr { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; border-bottom: 1px solid var(--line); padding: 7px 0; }
    .packets td { border: 0; padding: 0; }
    .packets td:nth-child(2) { white-space: normal; overflow-wrap: anywhere; }
    .packets td:nth-child(3) { grid-column: 1 / -1; padding-top: 3px; }
    /* Two rows: brand, the APRS Connect pill and the status light; then the nav. Nothing
       may push the header past the viewport, so everything can shrink and the row wraps. */
    /* One row: brand on the left, then the APRS Connect pill, the status light and the menu
       button at the far right, where a thumb expects it. The nav drops down from the header. */
    .top { gap: 8px; padding: 8px 12px; }
    .menu-btn { display: grid; flex-shrink: 0; order: 10; }
    .brand { font-size: 14px; min-width: 0; }
    .brand span { white-space: nowrap; }
    .nav { display: none; position: absolute; left: 0; right: 0; top: 100%; flex-direction: column; gap: 0; padding: 6px 8px 10px; background: rgba(7, 9, 15, 0.97); border-bottom: 1px solid var(--line); backdrop-filter: blur(10px); z-index: 6; }
    .nav.open { display: flex; }
    .nav a { padding: 10px 12px; font-size: 15px; border-radius: 8px; }
    .nav .platform-seg { align-self: flex-start; margin: 6px 8px 8px; }
    .nav .platform-seg a { padding: 6px 14px; font-size: 14px; }
    .powered-top { margin-left: auto; flex-shrink: 0; }
    .status { flex-shrink: 0; }
    .status .label { display: none; }
    .page { width: calc(100% - 24px); padding-top: 18px; }
    .card { padding: 12px; }
    td, th { padding: 6px 5px; }
    .passes th:last-child, .passes td:last-child { display: none; }
    .passes td { font-size: 13px; }
}

/* ---- APRS Thursday: what the net adds to the SpaceAPRS look ---- */
/* The net's clock: a light that is green while the net is on, grey between nets, and a line
   saying which and how long. */
.net-state { display: flex; align-items: center; gap: 9px; margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.net-state b { color: var(--text); font-weight: 600; }
.net-state .muted { color: var(--faint); }
.net-light { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background: var(--faint); }
.net-light.on { background: var(--ok); box-shadow: 0 0 10px rgba(95, 211, 154, 0.7); animation: netpulse 2s ease-in-out infinite; }
@keyframes netpulse { 0%, 100% { box-shadow: 0 0 6px rgba(95, 211, 154, 0.5); } 50% { box-shadow: 0 0 14px rgba(95, 211, 154, 0.95); } }
.card.collapsed .net-state { display: none; }
/* The list of stations checked in: the callsign, when, what they said, and the small print. */
.stations li { grid-template-rows: auto auto auto; }
.stations .said { grid-column: 1 / -1; color: var(--text); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: 0.9; }
.stations .said i { color: var(--faint); font-style: italic; }
.stations li.unplaced .call { color: var(--muted); }
.stations .call .flag { margin-left: 4px; }
.stations .call .sym { display: inline-block; width: 20px; height: 20px; margin: -3px 6px -3px 0; vertical-align: middle; background-repeat: no-repeat; }
.flag.small { font-size: 12px; vertical-align: -1px; }
html.no-flags .flag.small::after { font-size: 9px; padding: 1px 3px; }
/* The ticker: a small tag says what kind of message each row is. */
.ticker .kind { display: inline-block; padding: 0 5px; border-radius: 4px; border: 1px solid var(--line-strong); color: var(--faint); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; vertical-align: 1px; }
.ticker li.role-checkin .kind { color: var(--amber); border-color: var(--amber-dim); }
.ticker li.role-reply b, .ticker li.role-logged b { color: var(--iss); }
.ticker li.role-reply .info, .ticker li.role-logged .info, .ticker li.role-keepalive .info, .ticker li.role-join .info, .ticker li.role-leave .info { color: var(--muted); }
.ticker li .hdr .flag { margin-left: 2px; }
.popup .said { color: var(--text); margin: 2px 0; }
/* Tables: the kind of a message, and how far a post reached. */
.kind { display: inline-block; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--line-strong); color: var(--muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; }
tr.role-checkin .kind { color: var(--amber); border-color: var(--amber-dim); }
/* A post outside the net: tagged early or late, dashed, and counted for nothing. */
tr.role-early .kind, tr.role-late .kind, .ticker li.role-early .kind, .ticker li.role-late .kind { color: var(--faint); border-style: dashed; cursor: help; }
tr.role-early .call, tr.role-late .call, .ticker li.role-early b, .ticker li.role-late b { color: var(--muted); }
/* The same tag on a station that is on a list only because the box counts early and late posts in. */
.kind.timing, .stations .meta .timing { display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 4px; border: 1px dashed var(--line-strong); color: var(--faint); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; vertical-align: 1px; cursor: help; }
.stations .meta .timing { margin: 0 4px 0 0; }
.offnet-opt { margin: 0 0 14px; }
.page-head .offnet-opt { margin-top: 6px; }
.range-row .offnet-opt { margin: 0; } /* on the trends row it sits in line with the slider and the SSID box */
tr.role-reply .kind, tr.role-logged .kind { color: var(--iss); border-color: rgba(127, 180, 255, 0.4); }
tr.role-reply .call, tr.role-logged .call { color: var(--muted); }
.reach { display: inline-block; margin-left: 8px; color: var(--faint); font-size: 11px; font-family: var(--font); white-space: nowrap; }
.packets-table td.info { min-width: 220px; }
td.said { max-width: 420px; white-space: normal; overflow-wrap: anywhere; color: var(--muted); font-size: 12.5px; }
.stations-table .flag { margin-left: 6px; }
.tag { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; vertical-align: 2px; }
.tag.live { background: rgba(95, 211, 154, 0.15); color: var(--ok); border: 1px solid rgba(95, 211, 154, 0.4); }
.nets-table tr.live td { background: rgba(95, 211, 154, 0.05); }
.nets-table td:first-child { padding-right: 16px; }
/* On a phone the nets table keeps four columns that fit without wrapping or scrolling. */
@media (max-width: 600px) {
    .nets-table .wide { display: none; }
    .nets-table th { font-size: 10px; letter-spacing: 0; padding: 6px 4px; }
    .nets-table td { padding: 7px 4px; font-size: 13px; }
    .nets-table td:first-child { padding-right: 4px; }
    .nets-table .call { font-size: 12.5px; }
}
/* On a phone the messages and stations tables give up columns for rows: each message or
   station is a small card — the callsign and the time on one line, what was said on the next,
   the small print under — instead of seven columns wrapping inside a sideways scroll. */
@media (max-width: 600px) {
    .msgs-table thead, .stations-table thead { display: none; }
    .msgs-table, .msgs-table tbody, .stations-table, .stations-table tbody { display: block; width: 100%; }
    .msgs-table tr, .stations-table tr { display: grid; column-gap: 8px; row-gap: 3px; padding: 9px 2px; border-bottom: 1px solid var(--line); }
    .msgs-table td, .stations-table td { display: block; padding: 0; border: 0; white-space: normal; min-width: 0; text-align: left; }
    .msgs-table tr { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "call country when" "info info info" "kind device gateway"; }
    .msgs-table td:nth-child(1) { grid-area: when; }
    .msgs-table td:nth-child(2) { grid-area: call; }
    .msgs-table td:nth-child(3) { grid-area: country; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; align-self: center; }
    .msgs-table td:nth-child(3) a { color: var(--muted); }
    .msgs-table td:nth-child(4) { grid-area: kind; }
    .msgs-table td.info { grid-area: info; min-width: 0; font-size: 12.5px; word-break: normal; overflow-wrap: anywhere; }
    .msgs-table td:nth-child(6) { grid-area: device; font-size: 11.5px; color: var(--faint); align-self: center; }
    .msgs-table td:nth-child(7) { grid-area: gateway; font-size: 11.5px; align-self: center; }
    .msgs-table tr.role-reply td:nth-child(3), .msgs-table tr.role-logged td:nth-child(3) { visibility: hidden; }
    .stations-table tr { grid-template-columns: minmax(0, 1fr) auto auto auto; grid-template-areas: "call call call last" "said said said said" "first nets checkins ."; }
    .stations-table td:nth-child(1) { grid-area: call; }
    .stations-table td:nth-child(2) { grid-area: last; color: var(--muted); font-size: 12px; align-self: center; }
    .stations-table td:nth-child(3) { grid-area: first; }
    .stations-table td:nth-child(4) { grid-area: nets; }
    .stations-table td:nth-child(5) { grid-area: checkins; }
    .stations-table td:nth-child(3), .stations-table td:nth-child(4), .stations-table td:nth-child(5) { font-size: 11.5px; color: var(--faint); white-space: nowrap; }
    .stations-table td:nth-child(3)::before { content: "since "; }
    .stations-table td:nth-child(4)::after { content: " nets"; }
    .stations-table td:nth-child(5)::after { content: " check-ins"; }
    .stations-table td.said { grid-area: said; max-width: none; }
    .stations-table td.said:empty { display: none; }
}
/* A station's nets, as chips; a net page's four numbers and its tall map. */
.net-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.chip { display: inline-block; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--panel-solid); color: var(--text); font-size: 12px; }
.chip:hover { border-color: var(--amber); text-decoration: none; }
.facts div.wide { grid-column: 1 / -1; }
.facts dd { overflow-wrap: anywhere; }
.counts.wide { grid-template-columns: repeat(4, 1fr); margin-bottom: 16px; }
.map-card.tall .mini-map { height: 440px; }
.spark .band { fill: rgba(95, 211, 154, 0.12); }
.spark.hours { height: 70px; }
.spark.hours text { fill: var(--faint); font: 9px var(--mono); }
.roster { list-style: none; margin: 0; padding: 0; max-height: 520px; overflow: auto; }
.roster li { display: grid; grid-template-columns: 1fr auto; gap: 0 10px; padding: 6px 4px; border-bottom: 1px solid var(--line); cursor: pointer; border-radius: 6px; }
.roster li:hover { background: rgba(255, 255, 255, 0.04); }
.roster .call { font-family: var(--mono); font-weight: 600; font-size: 13px; }
.roster .call a { color: var(--text); }
.roster .when { color: var(--muted); font-size: 12px; font-family: var(--mono); }
.roster .meta { grid-column: 1 / -1; color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }
.plain li .num { color: var(--muted); font-family: var(--mono); }
.muted { color: var(--faint); }
@media (max-width: 900px) {
    .counts.wide { grid-template-columns: repeat(2, 1fr); }
    .map-card.tall .mini-map { height: 320px; }
}

/* The net picker: which net is on show, sized to be seen. A compact control centred under the
   map, not a bar across it: big arrows either side of the date. The date turns amber on a past
   net; the later arrow (or the jump list, or End) is the way back to the present. */
.hud-bottom { justify-content: center; }
.netbar { display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 10px; flex: 0 0 auto; min-width: 0; max-width: 100%; }
.netbar .pan-btn { flex: 0 0 44px; width: 44px; height: 44px; padding: 0; font-size: 30px; line-height: 1; color: var(--text); border-color: var(--line-strong); background: rgba(255, 255, 255, 0.04); display: grid; place-items: center; }
.netbar .pan-btn:hover:not(:disabled) { border-color: var(--amber); color: var(--amber); }
.netbar .pan-btn:disabled { opacity: 0.25; cursor: default; }
.net-pick { flex: 1; display: flex; flex-direction: column; align-items: center; min-width: 230px; padding: 0 8px; line-height: 1.25; }
.net-day { font-weight: 650; font-size: 19px; letter-spacing: -0.01em; color: var(--text); white-space: nowrap; background: none; border: 0; padding: 2px 8px; border-radius: 8px; cursor: pointer; }
.net-day:hover, .net-day[aria-expanded="true"] { background: rgba(255, 255, 255, 0.07); }
.net-day::after { content: "▾"; margin-left: 7px; color: var(--muted); font-size: 14px; }
/* The jump list: every net by year and month, opening upward from the picker. The element lives
   on the body (the script moves it there): inside the bar's card a backdrop filter would make the
   card its containing block and the bar's overflow would clip it. The script sets left and bottom
   from the date button's position. */
.net-menu { position: fixed; transform: translateX(-50%); width: min(560px, calc(100vw - 32px)); max-height: min(60vh, 520px); overflow: auto; background: var(--panel-solid); border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 0 14px 14px; box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55); z-index: 30; text-align: left; }
/* The year is a bar that sticks to the top of the list while its months scroll under it, so a
   fast scroll never leaves you guessing which year you are in. */
.nm-year h4 { position: sticky; top: 0; z-index: 1; margin: 0 -14px 4px; padding: 9px 14px 7px; font-size: 15px; font-weight: 700; letter-spacing: 0.06em; color: var(--text); background: var(--panel-solid); border-bottom: 1px solid var(--line-strong); box-shadow: 0 8px 14px -8px rgba(0, 0, 0, 0.7); }
.nm-year h4::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--amber); margin-right: 9px; vertical-align: 1px; }
.net-menu[hidden] { display: none; }
.nm-month { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; padding: 3px 0; border-bottom: 1px solid var(--line); }
.nm-name { width: 82px; color: var(--muted); font-size: 12.5px; }
.nm-day { width: 34px; height: 30px; border-radius: 7px; border: 1px solid var(--line); background: transparent; color: var(--text); font: 600 12.5px var(--mono); cursor: pointer; }
.nm-day:hover { border-color: var(--amber); color: var(--amber); }
.nm-day.on { background: var(--amber); color: #1f1602; border-color: var(--amber); }
.nm-day.cur:not(.on) { border-color: rgba(95, 211, 154, 0.6); color: var(--ok); }
.nm-close { display: none; }
/* On a phone the bar sits in a box that clips its overflow, so the menu is a sheet fixed over
   the page instead, with a close button; the chips are thumb-sized and the month name sits on
   its own line above them. */
@media (max-width: 900px) {
    .net-menu { left: 12px !important; right: 12px; bottom: 12px !important; top: auto; width: auto; transform: none; max-height: 72vh; padding: 0 12px 12px; }
    .nm-year h4 { margin: 0 -12px 6px; padding: 10px 12px 8px; font-size: 17px; }
    .netbar { gap: 8px; padding: 8px; }
    .netbar .pan-btn { flex-basis: 48px; width: 48px; height: 48px; font-size: 34px; }
    .net-day { font-size: 17px; padding: 2px 4px; }
    .nm-close { display: block; position: sticky; top: 5px; float: right; margin: 5px 0 0 8px; width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--line-strong); background: var(--panel-solid); color: var(--text); font-size: 20px; line-height: 1; cursor: pointer; z-index: 2; }
    .nm-month { flex-wrap: wrap; gap: 8px; padding: 8px 0; }
    .nm-name { width: 100%; font-size: 13px; }
    .nm-day { width: 46px; height: 44px; font-size: 15px; border-radius: 9px; }
}
.net-sub { color: var(--muted); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
body.past .net-day { color: var(--amber); }
.live.past .globe { filter: saturate(0.85); }
.roster-table tr.placed { cursor: pointer; }
.roster-table tr.placed:hover td { background: rgba(255, 255, 255, 0.04); }
.roster-table td.info { min-width: 200px; }
.pager .muted { margin-right: auto; font-size: 12.5px; }
.kind.origin { margin-left: 4px; color: var(--faint); border-style: dashed; }

/* Trends: Chart.js canvases (the chart sets its own height), recessive grid and axes drawn by
   the script from the site's tokens. */
.chart-card h2 { margin-bottom: 4px; }
.chart { position: relative; width: 100%; min-height: 120px; margin-top: 8px; }
.chart canvas { display: block; width: 100% !important; }
.chart .empty { margin: 0; }
/* The card a tapped bar opens: the net's numbers and the way to its page. */
.chart-pop { position: fixed; z-index: 60; min-width: 200px; max-width: min(300px, calc(100vw - 16px)); padding: 10px 30px 10px 12px; background: var(--panel-solid); border: 1px solid var(--line-strong); border-radius: 10px; box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55); font-size: 12.5px; line-height: 1.45; color: var(--text); }
.chart-pop[hidden] { display: none; }
.chart-pop b { display: block; font-size: 13px; margin-bottom: 2px; }
.chart-pop .muted { color: var(--muted); }
.chart-pop a { display: inline-block; margin-top: 7px; font-weight: 600; }
.chart-pop .x { position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; }
.chart-pop .x:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.counts .up { color: var(--ok); }
.counts .down { color: var(--bad); }
.rank-table td { font-size: 13px; }
.rank-bar { display: inline-block; height: 6px; margin-left: 10px; border-radius: 3px; background: #b8862a; vertical-align: 1px; }

/* Trends: the two-handle month slider and the SSID box on one row. The slider is two native
   range inputs laid over one track, their thumbs the only visible part, with a fill between
   the handles. */
.range-row { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin: 0 0 16px; }
.year-range { display: flex; align-items: center; gap: 12px; flex: 1 1 260px; max-width: 560px; }
.fold-opt { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 12.5px; white-space: nowrap; cursor: pointer; }
.fold-opt input { accent-color: var(--amber); width: 15px; height: 15px; margin: 0; }
.fold-opt:hover { color: var(--text); }
.year-range[hidden] { display: none; }
.year-label { font-family: var(--mono); font-size: 13px; color: var(--muted); white-space: nowrap; min-width: 150px; }
.year-range.on .year-label { color: var(--text); }
.year-track { position: relative; flex: 1; height: 28px; }
.year-track::before { content: ""; position: absolute; left: 0; right: 0; top: 12px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.12); }
.year-fill { position: absolute; top: 12px; height: 4px; border-radius: 2px; background: var(--faint); }
.year-range.on .year-fill { background: var(--amber); }
.year-track input[type="range"] { position: absolute; left: 0; right: 0; top: 0; width: 100%; height: 28px; margin: 0; background: transparent; -webkit-appearance: none; appearance: none; pointer-events: none; }
.year-track input[type="range"]::-webkit-slider-runnable-track { background: transparent; height: 28px; }
.year-track input[type="range"]::-moz-range-track { background: transparent; height: 28px; }
.year-track input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; pointer-events: auto; width: 16px; height: 16px; margin-top: 6px; border-radius: 50%; background: var(--text); border: 2px solid var(--panel-solid); box-shadow: 0 0 0 1px var(--line-strong); cursor: pointer; }
.year-track input[type="range"]::-moz-range-thumb { pointer-events: auto; width: 12px; height: 12px; border-radius: 50%; background: var(--text); border: 2px solid var(--panel-solid); box-shadow: 0 0 0 1px var(--line-strong); cursor: pointer; }
.year-range.on .year-track input[type="range"]::-webkit-slider-thumb { background: var(--amber); }
.year-range.on .year-track input[type="range"]::-moz-range-thumb { background: var(--amber); }
