/* APRS Nets: the aprsthursday look (dark, amber accent, and a light one for a reader who asks
   for it), written for a phone first.
   Every rule here holds at 390 pixels wide: the page never scrolls sideways, anything a finger
   presses is at least 44 pixels high, and text typed into a form is 16 pixels so the phone does
   not zoom. The wider layout is added at the bottom. Nothing is fetched from another host.

   Every colour on the site is one of these, so the two looks differ in the two blocks below
   and nowhere else: the layout stamps the one that is on upon <html data-theme>
   (Core/SiteTheme.cs). The "-rgb" ones are the three numbers of a colour, for
   rgba(var(--x-rgb), 0.1): a wash or an outline of it. --tint is the ink laid thinly over a
   ground (a hover, a pressed button, a hairline): white on dark, slate on light. */
:root {
    --bg: #07090f;
    --bg-rgb: 7, 9, 15;
    --panel: rgba(var(--panel-rgb), 0.78);
    --panel-rgb: 12, 16, 26;
    --panel-solid: #0e1320;
    /* The panel's colour as it lies on the page, flat: what a chart parts its slices with. */
    --panel-flat: #0b0e18;
    --tint: 255, 255, 255;
    --line: rgba(var(--tint), 0.08);
    --line-strong: rgba(var(--tint), 0.16);
    --text: #e6ebf5;
    --text-soft: #c6cddb;
    --muted: #8b95ab;
    --faint: #5b6478;
    /* Amber three ways, one colour here and three on white: as ink and thin lines (--amber),
       as a solid mark such as a dot, a tab's underline or the logo (--amber-mark), and as a
       ground with --on-amber written on it (--amber-fill). */
    --amber: #f2b84b;
    --amber-rgb: 242, 184, 75;
    --amber-dim: rgba(var(--amber-rgb), 0.35);
    --amber-mark: #f2b84b;
    --amber-fill: #f2b84b;
    --amber-fill-hi: #f7c665;
    --on-amber: #1f1602;
    /* A pill that is picked, on a map: the panel with amber in it (home.css). */
    --amber-panel: rgba(40, 32, 14, 0.94);
    --blue: #7fb4ff;
    --blue-rgb: 127, 180, 255;
    --ok: #5fd39a;
    --ok-rgb: 95, 211, 154;
    --ok-mark: #5fd39a;
    --warn: #f2b84b;
    --bad: #ff6b6b;
    --bad-rgb: 255, 107, 107;
    --bad-fill: #ff6b6b;
    --on-bad: #1a0606;
    /* The charts' amber (charts.css, charts.js): it passes the dataviz validator on the dark
       card and on the light one, so it is the same in each. */
    --chart-amber: #b8862a;
    /* The sky round a globe, as the layers of a background, the nearest first: in the dark, two
       soft glows over the page's colour, for the kit's stars to lie on (map.css, map.js). */
    --sky: 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%);
    /* No sun at night: these two are the light look's (below). */
    --sun: none;
    --glint: none;
    /* How strong a shadow is (a shadow that suits the dark is a smudge on white), and how far
       MapLibre's own black button pictures are turned to white. */
    --shade: 1;
    --invert: 1;
    --radius: 12px;
    --tap: 44px;
    --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;
    /* The desk's surfaces (admin.css), here so its parts can be used on any page. --adm-well is
       the ground of a field; --adm-surface-3 a button under the pointer. */
    --adm-surface: #101624;
    --adm-surface-2: #151c2d;
    --adm-surface-3: #1c2540;
    --adm-well: #0a0e18;
    --adm-border: rgba(var(--tint), 0.1);
    --adm-border-strong: rgba(var(--tint), 0.2);
    --adm-ring: rgba(var(--amber-rgb), 0.35);
    --adm-avatar-a: #2b3a5c;
    --adm-avatar-b: #1b2540;
    color-scheme: dark;
}
/* The light look. Text colours are checked against the white card and the page behind it
   (WCAG: --text 17, --muted 6.2, --faint 4.6, --amber 5.9, --blue 5.9, --ok 5.4, --bad 5.6 to
   1 on white). */
:root[data-theme="light"] {
    --bg: #f3f5f9;
    --bg-rgb: 243, 245, 249;
    --panel: rgba(var(--panel-rgb), 0.86);
    --panel-rgb: 255, 255, 255;
    --panel-solid: #ffffff;
    --panel-flat: #fdfdfe;
    --tint: 16, 24, 40;
    --line: rgba(var(--tint), 0.1);
    --line-strong: rgba(var(--tint), 0.2);
    --text: #141a26;
    --text-soft: #333d4f;
    --muted: #566175;
    --faint: #6b7588;
    --amber: #8a5a00;
    --amber-rgb: 196, 136, 12;
    --amber-dim: rgba(138, 90, 0, 0.45);
    --amber-mark: #b97c00;
    --amber-panel: rgba(253, 243, 220, 0.96);
    --blue: #0b62c4;
    --blue-rgb: 11, 98, 196;
    --ok: #177a4a;
    --ok-rgb: 23, 122, 74;
    --ok-mark: #1f9d5c;
    --warn: #b97c00;
    --bad: #c62a2f;
    --bad-rgb: 198, 42, 47;
    --bad-fill: #c62a2f;
    --on-bad: #ffffff;
    /* Daylight: a white bloom behind the globe, and blue at the top paling down to the page
       (Alex's choice for aprsthursday.com, 10 October 2026, of three shown side by side;
       contour lines were tried first and he did not want them). No stars by day: map.js lays
       none. The sun is a piece of its own that map.js moves as the globe is turned: --sun is
       the sun and its glow in the sky, --glint its shine on the face of the globe. */
    --sky: radial-gradient(circle at 50% 50%, #ffffffe6, transparent 58%), linear-gradient(180deg, #9cc5f2 0%, #c9e0f8 48%, #eef4fb 100%);
    --sun: radial-gradient(circle closest-side, rgba(255, 254, 246, 1) 0, rgba(255, 249, 226, 0.96) 3.5%, rgba(255, 236, 182, 0.62) 9%, rgba(255, 228, 164, 0.3) 24%, rgba(255, 228, 170, 0.11) 50%, rgba(255, 232, 184, 0) 100%);
    --glint: radial-gradient(circle closest-side, #ffffffb8 0, #ffffff66 11%, #ffffff2b 34%, #ffffff0d 66%, #ffffff00 100%);
    --shade: 0.3;
    --invert: 0;
    --adm-surface: #ffffff;
    --adm-surface-2: #f6f8fb;
    --adm-surface-3: #e9edf4;
    --adm-well: #ffffff;
    --adm-border: rgba(var(--tint), 0.12);
    --adm-border-strong: rgba(var(--tint), 0.24);
    --adm-avatar-a: #e6ecf6;
    --adm-avatar-b: #cfd9ea;
    color-scheme: light;
}

* { box-sizing: border-box; }
/* No blue flash on a tap: Android Chrome tints whatever element owns the click handler. */
* { -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
html, body { height: 100%; }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 15px/1.5 var(--font);
    font-feature-settings: "tnum" 1;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* A long callsign list or a raw packet wraps inside its box and never widens the page. */
    overflow-wrap: anywhere;
}
a { color: var(--blue); 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; }
img, svg { max-width: 100%; }
[hidden] { display: none !important; }

/* ── Header ──────────────────────────────────────────────────────────────── */
.top {
    position: relative;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(to bottom, rgba(var(--bg-rgb), 0.95), rgba(var(--bg-rgb), 0.75));
    backdrop-filter: blur(10px);
}
.brand { display: flex; align-items: center; gap: 10px; min-height: var(--tap); min-width: 0; color: var(--text); font-weight: 650; font-size: 16px; letter-spacing: 0.01em; }
.brand:hover { text-decoration: none; }
.brand span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brand-mark { flex: none; width: 26px; height: 26px; color: var(--amber-mark); }
/* On a phone the nav folds behind a button at the far right, where a thumb expects it. */
.menu-btn { display: grid; place-items: center; flex: none; margin-left: auto; width: var(--tap); height: var(--tap); border: 1px solid var(--line); border-radius: 10px; background: transparent; color: var(--muted); cursor: pointer; padding: 0; }
.menu-btn svg { width: 20px; height: 20px; }
.menu-btn[aria-expanded="true"] { color: var(--text); background: rgba(var(--tint), 0.06); }
.nav { display: none; position: absolute; left: 0; right: 0; top: 100%; flex-direction: column; gap: 2px; padding: 6px 8px 10px; background: rgba(var(--bg-rgb), 0.98); border-bottom: 1px solid var(--line); z-index: 6; }
.nav.open { display: flex; }
.nav a { display: flex; align-items: center; gap: 10px; min-height: var(--tap); padding: 0 12px; border-radius: 9px; color: var(--muted); font-size: 16px; }
.nav a.on, .nav a:hover { color: var(--text); background: rgba(var(--tint), 0.05); text-decoration: none; }
.nav a.start { color: var(--amber); }
.nav .who { color: var(--text); }
/* Light or dark (Core/SiteTheme.cs): a sun while the page is dark, a moon while it is light.
   The last row of a phone's menu, with its words; on a wide screen the picture alone, at the
   end of the nav. */
.nav a.theme-link { margin-top: 4px; border-top: 1px solid var(--line); border-radius: 0 0 9px 9px; }
.nav a.theme-link svg { flex: none; width: 18px; height: 18px; }
.avatar { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 28px; height: 28px; border-radius: 50%; background: linear-gradient(135deg, var(--adm-avatar-a), var(--adm-avatar-b)); border: 1px solid var(--line-strong); color: var(--text); font-size: 11px; font-weight: 600; letter-spacing: 0.02em; }

/* ── A net's own bar: its name, and its tabs ─────────────────────────────── */
.net-bar { border-bottom: 1px solid var(--line); background: var(--panel-solid); }
.net-bar-in { width: min(1080px, 100% - 24px); margin: 0 auto; }
.net-name { display: flex; align-items: center; gap: 0 10px; flex-wrap: wrap; padding: 4px 0 0; }
.net-name a.name { display: inline-flex; align-items: center; min-height: var(--tap); color: var(--text); font-size: 18px; font-weight: 650; letter-spacing: -0.01em; }
.net-name a.name:hover { text-decoration: none; }
.net-name .to-desk { margin-left: auto; }
/* The tabs scroll sideways inside their own box when they do not fit; the page never does. */
.net-tabs { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; margin: 0 -6px; padding: 0 6px; }
.net-tabs::-webkit-scrollbar { display: none; }
.net-tabs a { flex: none; display: flex; align-items: center; min-height: var(--tap); padding: 0 12px; color: var(--muted); border-bottom: 2px solid transparent; white-space: nowrap; }
.net-tabs a:hover { color: var(--text); text-decoration: none; }
.net-tabs a.on { color: var(--text); border-bottom-color: var(--amber-mark); }
/* A row with more to one side fades out to nothing on that side; common.js says which
   (more-left, more-right) as the row is moved. Cut exactly between two tabs the row looked
   finished: at 390 pixels "Check in" was off the edge with nothing to show it. The fade is
   steep enough to take the end off the last word in view, so that word reads as cut. */
.net-tabs.more-right { -webkit-mask-image: linear-gradient(to left, transparent 12px, #000 72px); mask-image: linear-gradient(to left, transparent 12px, #000 72px); }
.net-tabs.more-left { -webkit-mask-image: linear-gradient(to right, transparent 12px, #000 72px); mask-image: linear-gradient(to right, transparent 12px, #000 72px); }
.net-tabs.more-left.more-right { -webkit-mask-image: linear-gradient(to right, transparent 12px, #000 72px, #000 calc(100% - 72px), transparent calc(100% - 12px)); mask-image: linear-gradient(to right, transparent 12px, #000 72px, #000 calc(100% - 72px), transparent calc(100% - 12px)); }
/* One line under the bar when the net is a draft or is paused. */
.notice { margin: 0; padding: 9px 12px; border-bottom: 1px solid var(--amber-dim); background: rgba(var(--amber-rgb), 0.1); color: var(--text); font-size: 14px; text-align: center; }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.foot { display: flex; justify-content: space-between; align-items: center; gap: 4px 16px; flex-wrap: wrap; padding: 6px 12px; border-top: 1px solid var(--line); color: var(--faint); font-size: 13px; background: var(--bg); }
.foot a { display: inline-flex; align-items: center; min-height: var(--tap); color: var(--muted); }
.foot-links { display: flex; gap: 0 16px; flex-wrap: wrap; }
.foot .powered { color: var(--muted); }
.foot .powered a { color: var(--amber); font-weight: 600; }

/* ── Ordinary pages ──────────────────────────────────────────────────────── */
.page { width: min(1080px, 100% - 24px); margin: 0 auto; padding: 18px 0 40px; flex: 1; }
.page.narrow { width: min(620px, 100% - 24px); }
.page-head { margin-bottom: 18px; }
.crumb { color: var(--faint); font-size: 13px; margin: 0 0 6px; }
.crumb a { display: inline-flex; align-items: center; min-height: var(--tap); color: var(--muted); }
.page h1 { font-size: 24px; line-height: 1.25; }
.page h1 small { display: block; color: var(--muted); font-weight: 400; font-size: 15px; margin-top: 2px; }
.lede { color: var(--muted); margin: 6px 0 0; }
.prose { max-width: 720px; }
.prose p { color: var(--text-soft); line-height: 1.6; }
.prose h2 { font-size: 16px; margin: 22px 0 6px; color: var(--text); }
.muted { color: var(--faint); }
/* A link that stands by itself in a list or a table cell, made as tall as a finger needs. A
   link in the middle of a sentence stays as it is. */
.tap { display: inline-flex; align-items: center; min-height: var(--tap); }
/* A link inside a sentence or a line of a list: as tall as a finger needs, without making its
   line taller (the address to write to for an account, APRS Connect in a net's list of programs). */
a.in-line { display: inline-flex; align-items: center; min-height: var(--tap); margin: calc((22px - var(--tap)) / 2) 0; }
.mono { font-family: var(--mono); font-size: 13px; color: var(--muted); word-break: break-all; }
.call { font-family: var(--mono); font-weight: 600; }
.summary { color: var(--muted); font-size: 13px; margin: 0 0 10px; }

.card { position: relative; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: 14px; }
.card h2 { font-size: 13px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; margin: 2px 0 10px; }
.card-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.card-head.row { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.card-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.card-row h2 { margin: 0; flex: 1; }
.grid-2 { display: grid; grid-template-columns: 1fr; gap: 14px; }

/* Numbers in a row: a session's headline. Two across on a phone. */
.counts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 0 0 14px; }
.counts > div { display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 14px; }
.counts b { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; font-family: var(--mono); }
.counts span { color: var(--muted); font-size: 12px; }
.facts { display: grid; grid-template-columns: 1fr; gap: 10px 16px; margin: 0 0 14px; }
.facts div { display: flex; flex-direction: column; }
.facts dt { color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.facts dd { margin: 0; }

/* The net's clock: a light that is green while the net is on, grey between sessions. */
.net-state { display: flex; align-items: center; gap: 9px; margin: 0 0 10px; color: var(--muted); }
.net-state b { color: var(--text); font-weight: 600; }
.net-light { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--faint); }
.net-light.on { background: var(--ok-mark); box-shadow: 0 0 10px rgba(var(--ok-rgb), 0.7); animation: netpulse 2s ease-in-out infinite; }
@keyframes netpulse { 0%, 100% { box-shadow: 0 0 6px rgba(var(--ok-rgb), 0.5); } 50% { box-shadow: 0 0 14px rgba(var(--ok-rgb), 0.95); } }
@keyframes flash { from { background: rgba(var(--amber-rgb), 0.25); } to { background: transparent; } }
.new { animation: flash 1.6s ease-out; }

/* ── What to send: the exact line, with a button that copies it ──────────── */
.send-line { display: flex; align-items: stretch; gap: 8px; margin: 6px 0; }
.send-line code { flex: 1; min-width: 0; display: flex; align-items: center; min-height: var(--tap); padding: 6px 12px; border-radius: 9px; border: 1px solid var(--line-strong); background: var(--adm-well); font-size: 15px; word-break: break-word; }

/* ── Buttons, chips, tags ────────────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: var(--tap); padding: 0 14px; border-radius: 9px; border: 1px solid var(--line-strong); background: var(--adm-surface-2); color: var(--text); font: inherit; font-size: 15px; font-weight: 500; line-height: 1.2; cursor: pointer; text-decoration: none; white-space: nowrap; }
.btn:hover { background: var(--adm-surface-3); border-color: rgba(var(--tint), 0.3); text-decoration: none; }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--adm-ring); }
.btn.primary { background: var(--amber-fill); border-color: var(--amber-fill); color: var(--on-amber); font-weight: 600; }
.btn.primary:hover { background: var(--amber-fill-hi); border-color: var(--amber-fill-hi); }
.btn.ghost { background: none; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { background: rgba(var(--tint), 0.06); color: var(--text); }
.btn.danger { background: none; border-color: rgba(var(--bad-rgb), 0.45); color: var(--bad); }
.btn.danger:hover { background: var(--bad-fill); border-color: var(--bad-fill); color: var(--on-bad); }
.btn:disabled { opacity: 0.45; cursor: default; }
.btn.wide { width: 100%; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.chip { display: inline-flex; align-items: center; min-height: 32px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--panel-solid); color: var(--text); font-size: 13px; }
a.chip, button.chip { min-height: var(--tap); padding: 0 14px; cursor: pointer; }
a.chip:hover { border-color: var(--amber); text-decoration: none; }
.chip.on { border-color: var(--amber); background: rgba(var(--amber-rgb), 0.1); }
/* A tag says one thing about a line. What each tag means is printed once under its table. */
.tag { display: inline-block; padding: 1px 7px; border-radius: 5px; border: 1px solid var(--line-strong); color: var(--muted); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; vertical-align: 1px; }
.tag.ok { color: var(--ok); border-color: rgba(var(--ok-rgb), 0.4); }
.tag.warn { color: var(--amber); border-color: var(--amber-dim); }
.tag.bad { color: var(--bad); border-color: rgba(var(--bad-rgb), 0.45); }
.tag.info { color: var(--blue); border-color: rgba(var(--blue-rgb), 0.4); }
.tag.dashed { color: var(--faint); border-style: dashed; }
.tag.live { color: var(--ok); border-color: rgba(var(--ok-rgb), 0.4); background: rgba(var(--ok-rgb), 0.12); }
.tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.legend { display: grid; grid-template-columns: max-content 1fr; gap: 6px 10px; margin: 12px 0 0; color: var(--muted); font-size: 13px; }
.legend dt { margin: 0; }
.legend dd { margin: 0; }

/* ── Nothing here yet ────────────────────────────────────────────────────── */
.empty { padding: 28px 12px; text-align: center; color: var(--muted); }
.empty b { display: block; color: var(--text); font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.empty p { margin: 0 auto; max-width: 46ch; }
.empty .btn { margin-top: 14px; }

/* ── Tables ──────────────────────────────────────────────────────────────── */
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: 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
td { padding: 9px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
td.num, th.num { text-align: right; }
/* A heading that puts its table in order by its column (Pages/Shared/_SortHead.cshtml,
   Core/SortHead.cs). A link in the heading's own look, as tall as what is pressed without
   making its row taller. The column the table is in order by is brighter and has an arrow
   that says which way round: up for A to Z and the least first, down for the other way. */
th a.sort-by { display: inline-flex; align-items: center; gap: 5px; min-height: var(--tap); margin: calc((16px - var(--tap)) / 2) 0; color: inherit; text-decoration: none; }
th a.sort-by:hover, th a.sort-by:focus-visible { color: var(--text); }
th[aria-sort] a.sort-by { color: var(--text); }
th[aria-sort] a.sort-by::after { content: ""; flex: none; width: 0; height: 0; border: 4px solid transparent; }
th[aria-sort="ascending"] a.sort-by::after { border-bottom-color: currentColor; margin-top: -4px; }
th[aria-sort="descending"] a.sort-by::after { border-top-color: currentColor; margin-top: 4px; }
/* A column of numbers has its heading at the right, so its arrow goes before the words and
   the words stay over the numbers. */
th.num a.sort-by { flex-direction: row-reverse; }
/* The headings are how a table is put in order. Where a table is folded into cards it has
   none, so its form has a list to pick an order from, and that list is out of sight where
   the table is a table. It still goes with the form, so a search keeps the order. */
@media (min-width: 761px) {
    select.order-pick { display: none; }
}
td .also { margin-left: 6px; color: var(--muted); font-family: var(--font); font-weight: 400; font-size: 13px; }
td .utc { color: var(--faint); font-size: 12.5px; white-space: nowrap; }
td .note { display: block; margin-top: 2px; color: var(--amber); font-size: 13px; }
td.act { white-space: nowrap; text-align: right; }
td.act form { display: inline; }
/* A table wider than the screen scrolls inside its own box. */
.table-scroll { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
.table-scroll table { min-width: 560px; }
/* Or it folds into cards: each row a small card, each cell on its own line, the callsign and
   the time side by side on the first. The roster does this. */
.cards thead { display: none; }
.cards, .cards tbody { display: block; width: 100%; }
.cards tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; padding: 10px 2px; border-bottom: 1px solid var(--line); }
.cards td { display: block; padding: 0; border: 0; min-width: 0; }
.cards td:empty { display: none; }
.cards td.when { text-align: right; color: var(--muted); font-size: 13px; }
.cards td.said, .cards td.wide, .cards td.act { grid-column: 1 / -1; }
.cards td.said { color: var(--text); }
/* Folded into a card the buttons go on to a second line when they do not fit one: three of
   them ("Open its desk", "Public page", "Take off pause") ran off the edge of a phone. */
.cards td.act { text-align: left; padding-top: 6px; white-space: normal; }
.cards td.act .btn { margin: 0 6px 6px 0; }
/* A cell whose heading is hidden with the others says what it is itself. */
.cards td[data-label].labelled::before { content: attr(data-label) ": "; color: var(--faint); font-size: 12px; }
/* On a net whose clock is UTC the roster's time has no clock beside it in the table, where the
   heading names it. Folded into a card the heading is gone, so the card says it. */
.cards td.when .utc-only { color: var(--faint); font-size: 12.5px; }
.pager { display: flex; align-items: center; gap: 10px; justify-content: flex-end; flex-wrap: wrap; padding-top: 12px; }
.pager .muted { margin-right: auto; font-size: 13px; }

/* ── Forms on ordinary pages (the desk's fields are in admin.css) ────────── */
input, select, textarea { font: inherit; font-size: 16px; color: var(--text); }
.filter { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 0 0 16px; }
.filter input, .filter select { flex: 1 1 160px; min-width: 0; min-height: var(--tap); padding: 0 12px; background: var(--panel-solid); border: 1px solid var(--line-strong); border-radius: 9px; }
.check-form { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.check-form input[type=text] { flex: 1 1 180px; min-width: 0; min-height: var(--tap); padding: 0 12px; background: var(--adm-well); border: 1px solid var(--line-strong); border-radius: 9px; font-family: var(--mono); text-transform: uppercase; }
.check-form input[type=text]::placeholder { font-family: var(--font); text-transform: none; color: var(--faint); }
.check-result { padding: 12px 14px; border-radius: 10px; border: 1px solid var(--line); margin: 10px 0; }
.check-result.yes { border-color: rgba(var(--ok-rgb), 0.5); background: rgba(var(--ok-rgb), 0.06); }
.check-result.no { border-color: var(--amber-dim); background: rgba(var(--amber-rgb), 0.06); }
.check-result p { margin: 0 0 6px; }
.check-result p:last-child { margin-bottom: 0; }

/* ── The list of nets ────────────────────────────────────────────────────── */
.net-list { display: grid; grid-template-columns: 1fr; gap: 12px; margin: 0; padding: 0; list-style: none; }
.net-list > li { margin: 0; }
.net-card { display: block; min-height: var(--tap); padding: 14px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--panel); color: var(--text); }
.net-card:hover { border-color: var(--amber-dim); text-decoration: none; }
.net-card b { display: block; font-size: 17px; font-weight: 650; }
.net-card p { margin: 4px 0 0; color: var(--muted); font-size: 14px; }

/* ── Wider screens ───────────────────────────────────────────────────────── */
@media (min-width: 761px) {
    :root { --tap: 38px; }
    .top { gap: 24px; padding: 8px 18px; }
    .menu-btn { display: none; }
    .nav { display: flex; position: static; flex-direction: row; align-items: center; gap: 4px; flex: 1; padding: 0; background: none; border: 0; }
    .nav a { min-height: 34px; padding: 0 10px; font-size: 14.5px; }
    .nav .push { margin-left: auto; }
    .nav a.theme-link { margin-top: 0; padding: 0 9px; border-top: 0; border-radius: 9px; }
    .nav a.theme-link span { display: none; }
    .net-bar-in, .page { width: min(1080px, 100% - 36px); }
    .page { padding-top: 26px; }
    .page.narrow { width: min(620px, 100% - 36px); }
    .page h1 { font-size: 26px; }
    .foot { padding: 4px 18px; }
    .card { padding: 16px 18px; }
    .grid-2 { grid-template-columns: 1fr 1fr; }
    .counts { grid-template-columns: repeat(4, 1fr); }
    .facts { grid-template-columns: 1fr 1fr; }
    .net-list { grid-template-columns: 1fr 1fr; }
    .btn.wide { width: auto; }
    /* The roster is a table again. */
    .cards thead { display: table-header-group; }
    .cards { display: table; }
    .cards tbody { display: table-row-group; }
    .cards tr { display: table-row; padding: 0; border: 0; }
    .cards td { display: table-cell; padding: 9px 8px; border-bottom: 1px solid var(--line); }
    .cards td:empty { display: table-cell; }
    .cards td.when { text-align: left; white-space: nowrap; font-size: inherit; }
    .cards td.act { text-align: right; padding-top: 9px; white-space: nowrap; }
    .cards td.act .btn { margin: 0 0 0 6px; }
    .cards td[data-label].labelled::before { content: none; }
    .cards td.when .utc-only { display: none; }
}
/* A wide screen that is pressed with a finger (a phone held sideways, a tablet) keeps what is
   pressed a finger tall: a width says nothing about what presses. */
@media (min-width: 761px) and (pointer: coarse) {
    :root { --tap: 44px; }
    .nav a { min-height: var(--tap); }
}

/* ---- The public pages (Pages/Public): the list of nets, a net's pages, how to check in. ---- */
/* One number by itself fills the row. */
.counts.one { grid-template-columns: 1fr; }
.counts.one > div { flex-direction: row; align-items: baseline; gap: 10px; }
.counts.one span { font-size: 14px; }
/* The list of nets: a card with links in it, not one big link. */
.net-card { padding-top: 6px; }
.net-card b a { display: inline-flex; align-items: center; min-height: var(--tap); color: var(--text); }
.after-list { margin-top: 18px; }
.cards td.who a.tap { font-weight: 600; }
/* A callsign that leads to its station's page (Pages/Shared/_RosterTable.cshtml): as tall as a
   finger needs, without making its line any taller. */
.cards td.who a.station { display: inline-flex; align-items: center; min-height: var(--tap); margin: calc((22px - var(--tap)) / 2) 0; }
.net-card b .tag { margin-left: 6px; }
.net-card .card-row { margin: 12px 0 0; }
.net-card .now { color: var(--text); }
/* What to send: the name of each box above it, as on a radio's message screen. */
.send-label { margin: 12px 0 0; color: var(--faint); font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }
.send-line .btn { flex: none; }
.plain-list { margin: 0; padding: 0; list-style: none; }
.plain-list li { padding: 9px 0; border-bottom: 1px solid var(--line); }
.plain-list li:last-child { border-bottom: 0; }
.plain-list b { display: block; font-weight: 600; }
.plain-list span { color: var(--muted); font-size: 14px; }
.pager .btn { min-width: var(--tap); }
.cards td.door { grid-column: 1 / -1; color: var(--muted); font-size: 13px; }
.card > p:last-child { margin-bottom: 0; }
/* A notice inside a page, above the card it is about. */
.notice.in-page { margin: 0 0 14px; border: 1px solid var(--amber-dim); border-radius: var(--radius); text-align: left; }
/* "Did my check-in get through?" on the live page: one question, one box, one button. */
.check-ask label { display: block; font-size: 13px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; margin: 2px 0 0; }
.check-ask .check-form { margin-bottom: 0; }
.check-form select { flex: 1 1 100%; min-width: 0; min-height: var(--tap); padding: 0 12px; background: var(--adm-well); border: 1px solid var(--line-strong); border-radius: 9px; }
/* What a controller wrote keeps its own line breaks. */
.about-text { white-space: pre-line; }

/* More about something, behind an "i" (Alex, 5 October 2026: a long explanation is never laid
   out on the page; it opens from an i button). It is the browser's own popover, so it needs no
   script. The markup is in CLAUDE.md, "How the site's words are written". Never give .info-pop
   a display of its own: the browser hides it until its button is pressed. */
.info-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap);
    height: var(--tap);
    margin: -11px -8px -11px -4px;
    padding: 0;
    background: none;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    vertical-align: middle;
    flex: none;
}
.info-btn::before {
    content: "i";
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: 1.5px solid currentColor;
    border-radius: 50%;
    font: italic 600 14px/1 Georgia, "Times New Roman", serif;
}
.info-btn:hover, .info-btn:focus-visible { color: var(--amber); }
.info-btn:focus-visible { outline: 2px solid var(--adm-ring); outline-offset: -8px; border-radius: 50%; }
.info-pop {
    width: min(92vw, 460px);
    max-height: 80vh;
    margin: auto;
    padding: 18px 18px 14px;
    overflow: auto;
    background: var(--panel-solid);
    color: var(--text);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: 0 18px 60px rgba(0, 0, 0, calc(0.6 * var(--shade)));
    font-size: 16px;
    line-height: 1.5;
    text-align: left;
}
.info-pop::backdrop { background: rgba(3, 5, 10, 0.6); }
.info-pop h3 { margin: 0 0 8px; font-size: 17px; }
.info-pop p { margin: 0 0 10px; }
.info-pop ul { margin: 0 0 10px; padding-left: 20px; }
.info-pop li { margin: 0 0 4px; }
/* A key to tags inside the box (the live page, a session's roster, the desk's): read at the
   box's own size, with room under it. */
.info-pop .legend { margin: 0 0 12px; font-size: 14px; }
/* Close stays at the foot of a box that scrolls inside itself: the full account of what counts
   is taller than a phone's screen lets the box be. The shadows, in the box's own colour and
   side by side to its left edge, are a plain band behind the button, so the words pass under
   a band and not under half a button. The box cuts off what of them lies outside it. */
.info-close {
    display: block;
    position: sticky;
    bottom: 0;
    min-height: var(--tap);
    margin: 6px 0 0 auto;
    padding: 0 16px;
    background: var(--panel-solid);
    box-shadow: 0 0 0 8px var(--panel-solid), -60px 0 0 8px var(--panel-solid), -120px 0 0 8px var(--panel-solid),
        -180px 0 0 8px var(--panel-solid), -240px 0 0 8px var(--panel-solid), -300px 0 0 8px var(--panel-solid),
        -360px 0 0 8px var(--panel-solid), -420px 0 0 8px var(--panel-solid);
    color: var(--text);
    border: 1px solid var(--line-strong);
    border-radius: 10px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
/* One short line with the i button that holds the rest ("Each operator is counted once a
   session, for ..."), or a label that only names what is behind its button ("The tags"). */
.more-line { margin: 10px 0; color: var(--muted); font-size: 14px; }
/* A browser with no popover (before 2024). common.js marks such a page (no-popover), and a
   press on the i then opens its text in place, under the line it explains, and a second
   press or Close shuts it. With no script the i and its text are not shown at all. */
@supports not selector(:popover-open) {
    html:not(.no-popover) .info-btn, html:not(.no-popover) .info-pop { display: none; }
}
.no-popover .info-pop { display: none; position: static; width: auto; max-height: none; margin: 8px 0 12px; box-shadow: none; }
.no-popover .info-pop.open { display: block; }
.no-popover .info-close { position: static; box-shadow: none; }

/* The packet behind a line, as it was heard (Alex, 6 October 2026: "can we add a raw packet
   button to all the tables with messages?"). It is the second thing that opens over a page,
   after the i button, in the same box (.info-pop) and by the same means, the browser's own
   popover. Its one shape is Pages/Shared/_RawButton.cshtml, and which line has one is
   Core/RawPacket.cs. The button is as tall and as wide as a finger needs; what is drawn of
   it is the small outline in its middle, and what is over is taken from the space round its
   line, so no row is taller for it. */
.raw-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap);
    height: var(--tap);
    margin: calc((22px - var(--tap)) / 2) 0;
    padding: 0 8px;
    background: none;
    border: 0;
    color: var(--muted);
    font: 600 11px/1 var(--mono);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    vertical-align: middle;
    flex: none;
}
.raw-btn::before { content: ""; position: absolute; top: 50%; left: 0; right: 0; height: 24px; margin-top: -12px; border: 1px solid var(--line-strong); border-radius: 6px; }
.raw-btn:hover, .raw-btn:focus-visible { color: var(--text); outline: none; }
.raw-btn:hover::before { border-color: var(--amber-dim); }
.raw-btn:focus-visible::before { box-shadow: 0 0 0 3px var(--adm-ring); }
/* The box: the i button's, a little wider, for a line of a hundred characters and more. It
   is written inside the row it belongs to, so it takes back what a cell or a row that can be
   pressed would hand down to it. */
.raw-pop { width: min(92vw, 560px); white-space: normal; font-weight: 400; cursor: auto; }
.raw-pop .raw-who { color: var(--muted); font-size: 14px; }
/* The line wraps inside its box wherever it must and never widens the page. A press on it
   marks the whole of it. */
.raw-line { margin: 0 0 12px; padding: 10px 12px; background: rgba(var(--tint), 0.04); border: 1px solid var(--line); border-radius: 8px; color: var(--text); font: 13px/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; user-select: all; }
/* Copy at the left and Close at the right, in one row that stays at the foot of a box that
   scrolls inside itself, as the i box's Close does. */
.raw-acts { position: sticky; bottom: 0; display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--panel-solid); box-shadow: 0 0 0 8px var(--panel-solid); }
.raw-acts .info-close { position: static; margin: 0; box-shadow: none; }
/* The cell that holds the button: the last of its row, as narrow as the button, under a
   heading with no words to read (it has a name for a screen reader). */
th.raw, td.raw { width: 1%; padding-left: 0; padding-right: 0; text-align: right; white-space: nowrap; }
/* Folded into a card (.cards), a table that has such a cell says so (has-raw), and the button
   stands at the right end of the line of words: the card is no taller for it. */
@media (max-width: 760px) {
    .cards.has-raw tr { grid-template-columns: minmax(0, 1fr) auto var(--tap); }
    .cards.has-raw td.when { grid-column: 2 / -1; }
    .cards.has-raw td.said { grid-column: 1 / 3; }
    .cards.has-raw td.raw { grid-column: 3; grid-row: 2; width: auto; justify-self: end; }
}
/* A browser with no popover (before 2024): with no script the button is not shown, like the
   i. With one, common.js opens the box, and it is laid over the page as the popover would
   be, because in place it would open inside a cell as narrow as the button. */
@supports not selector(:popover-open) {
    html:not(.no-popover) .raw-btn { display: none; }
}
.no-popover .raw-pop.open { position: fixed; z-index: 60; top: 8vh; left: 50%; width: min(92vw, 560px); max-height: 84vh; margin: 0; transform: translateX(-50%); box-shadow: 0 18px 60px rgba(0, 0, 0, calc(0.6 * var(--shade))); }
.no-popover .raw-acts { position: static; box-shadow: none; }
