
  :root {
    --bg:#0f1419; --panel:#171d24; --line:#26303a; --fg:#e6edf3;
    --muted:#8b98a5; --accent:#4a9eff; --blue:#3b82f6; --red:#ef4444;
    --ok:#22c55e; --warn:#f59e0b;
  }
  * { box-sizing:border-box; }
  body { margin:0; background:var(--bg); color:var(--fg);
         font:15px/1.55 system-ui,-apple-system,Segoe UI,Roboto,sans-serif; }
  .wrap { max-width:1080px; margin:0 auto; padding:24px 18px 64px; }
  header { border-bottom:1px solid var(--line); background:var(--panel); }
  header .wrap { padding:16px 18px; display:flex; align-items:center;
                 justify-content:space-between; gap:16px; flex-wrap:wrap; }
  .brand { font-weight:650; letter-spacing:.3px; }
  .clock { font-variant-numeric:tabular-nums; font-size:.88rem;
           color:var(--fg); letter-spacing:.4px; }
  .clock .muted { font-size:.78rem; }
  .brand span { color:var(--accent); }
  h1 { font-size:1.5rem; margin:0 0 6px; }
  h2 { font-size:1.1rem; margin:28px 0 10px; }
  .sub { color:var(--muted); margin:0 0 22px; }
  .panel { background:var(--panel); border:1px solid var(--line);
           border-radius:10px; padding:18px; margin-bottom:18px; }
  .grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:16px; }
  /* Tabs: radio + sibling selectors, no script. The inputs are moved out of
     sight rather than hidden, so they keep focus and stay operable by keyboard
     and screen reader. */
  .tabs > input { position:absolute; width:1px; height:1px; opacity:0; }
  .tabbar { display:flex; gap:8px; margin:0 0 18px; flex-wrap:wrap; }
  .tabbar label { display:inline-block; padding:9px 18px; border-radius:8px;
    border:1px solid var(--line); background:transparent; color:var(--muted);
    font-weight:600; font-size:.92rem; cursor:pointer; user-select:none; }
  .tabbar label:hover { color:var(--fg); }
  .tabpane { display:none; }
  .tabpane .sub { margin:-4px 0 18px; }
  #tab-app:checked ~ .tabbar label[for="tab-app"],
  #tab-cfg:checked ~ .tabbar label[for="tab-cfg"] {
    background:var(--accent); border-color:var(--accent); color:#04101d; }
  #tab-app:focus-visible ~ .tabbar label[for="tab-app"],
  #tab-cfg:focus-visible ~ .tabbar label[for="tab-cfg"] {
    outline:2px solid var(--fg); outline-offset:2px; }
  #tab-app:checked ~ .pane-app,
  #tab-cfg:checked ~ .pane-cfg { display:block; }
  /* Account tabs sit inside a panel; the landing page tabs are standalone. */
  .panel.tabs .tabbar { margin-bottom:14px; }
  .tabbar .count { display:inline-block; margin-left:6px; padding:0 6px;
    border-radius:10px; background:rgba(255,255,255,.10); font-size:.74rem; }
  #tab-blue:checked ~ .tabbar label[for="tab-blue"],
  #tab-red:checked ~ .tabbar label[for="tab-red"],
  #tab-inst:checked ~ .tabbar label[for="tab-inst"],
  #tab-admin:checked ~ .tabbar label[for="tab-admin"] {
    background:var(--accent); border-color:var(--accent); color:#04101d; }
  #tab-blue:checked ~ .pane-blue,
  #tab-red:checked ~ .pane-red,
  #tab-inst:checked ~ .pane-instructor,
  #tab-admin:checked ~ .pane-admin { display:block; }
  #tab-blue:focus-visible ~ .tabbar label[for="tab-blue"],
  #tab-red:focus-visible ~ .tabbar label[for="tab-red"],
  #tab-inst:focus-visible ~ .tabbar label[for="tab-inst"],
  #tab-admin:focus-visible ~ .tabbar label[for="tab-admin"] {
    outline:2px solid var(--fg); outline-offset:2px; }

  /* Native scrollbar, deliberately: 180 rows should scroll in place rather
     than push the controls off the page, and a custom scrollbar would lose
     the platform behaviour people already know. */
  .scrolllist { max-height:60vh; overflow:auto; border:1px solid var(--line);
    border-radius:8px; }
  .scrolllist table { margin:0; }
  .scrolllist thead th { position:sticky; top:0; background:var(--panel);
    z-index:1; box-shadow:0 1px 0 var(--line); }
  form.inline { display:flex; gap:6px; align-items:center; }
  form.inline input[type=password] { width:150px; }
  form.inline select { width:auto; min-width:96px; padding:5px 8px;
    font-size:.84rem; }
  form.inline button { padding:5px 10px; font-size:.8rem; }
  button[disabled] { opacity:.4; cursor:not-allowed; }

  /* The platform control is a compact pair, not a full-width field: the
     global select rule stretches every select to 100%, which is wrong inside a
     dense table row. */
  .platcell { display:flex; align-items:center; gap:6px; flex-wrap:nowrap; }
  .platcell .platsel { width:auto; min-width:132px; max-width:160px;
    padding:4px 8px; font-size:.82rem; }
  .platcell button { padding:4px 10px; font-size:.78rem; white-space:nowrap; }
  .tag.hq { background:rgba(245,158,11,.24); color:#ffe9b0; margin-left:6px; }
  th.sortable { cursor:pointer; user-select:none; white-space:nowrap; }
  th.sortable:hover { color:var(--fg); }
  th.sortable::after { content:"\2195"; opacity:.28; margin-left:5px;
    font-size:.8em; }
  th.sortable[data-dir="asc"]::after { content:"\2191"; opacity:1;
    color:var(--accent); }
  th.sortable[data-dir="desc"]::after { content:"\2193"; opacity:1;
    color:var(--accent); }

  /* Expired rows read as expired at a glance, across the data columns only --
     the checkbox column stays plain so the control is still legible. */
  tr.expired td:not(.nohl) { background:rgba(239,68,68,.15); }
  tr.expired td:not(.nohl):first-of-type { box-shadow:inset 3px 0 0 var(--red); }

  .bulkbar { display:flex; align-items:center; gap:12px; margin-top:12px;
    flex-wrap:wrap; }
  /* Kept in the layout but out of sight: these forms exist only as targets for
     the row controls' form= attribute, since they cannot be nested inside the
     bulk-delete form. */
  .offscreen { position:absolute; width:1px; height:1px; overflow:hidden;
    clip:rect(0 0 0 0); white-space:nowrap; }
  td.nohl input[type=checkbox], th.nohl input[type=checkbox] {
    width:16px; height:16px; accent-color:var(--accent); cursor:pointer; }
  .callsign { font-weight:600; }
  .callsign.online { color:var(--ok); }
  .callsign.offline { color:var(--muted); font-weight:400; }
  .modal { display:none; position:fixed; inset:0; z-index:50;
    align-items:center; justify-content:center; padding:20px; }
  .modal.show { display:flex; }
  .modal-backdrop { position:absolute; inset:0; background:rgba(0,0,0,.66); }
  .modal-card { position:relative; background:var(--panel); border-radius:12px;
    border:1px solid var(--line); padding:22px; max-width:380px; width:100%;
    text-align:center; box-shadow:0 18px 50px rgba(0,0,0,.5); }
  .modal-card h3 { margin:0 0 6px; font-size:1.05rem; word-break:break-all; }
  .modal-card img { width:260px; max-width:100%; background:#fff; padding:10px;
    border-radius:8px; margin:12px 0; }
  .modal-actions { display:flex; gap:10px; justify-content:center; }
  .pkg { display:inline-block; margin-left:6px; padding:1px 7px; border-radius:5px;
    border:1px solid var(--line); color:var(--accent); text-decoration:none;
    font-size:.74rem; font-weight:600; }
  .pkg:hover { border-color:var(--accent); }
  .qr-note { width:200px; height:200px; margin:0 auto; display:flex;
    align-items:center; justify-content:center; border-radius:8px;
    border:1px dashed var(--line); color:var(--muted); font-size:4rem;
    max-width:100%; }
  .qr { text-align:center; }
  .qr img { width:200px; height:200px; background:#fff; padding:10px;
            border-radius:8px; max-width:100%; }
  .qr h3 { margin:12px 0 4px; font-size:1rem; }
  a.btn, button, input[type=submit] {
    display:inline-block; background:var(--accent); color:#04101d; border:0;
    border-radius:7px; padding:9px 15px; font-weight:600; font-size:.92rem;
    text-decoration:none; cursor:pointer; }
  a.btn.ghost, button.ghost { background:transparent; color:var(--fg);
    border:1px solid var(--line); }
  button.danger { background:transparent; color:var(--red);
    border:1px solid var(--red); padding:4px 10px; font-size:.82rem; }
  input[type=text], input[type=password], input[type=file], select {
    background:#0d1218; color:var(--fg); border:1px solid var(--line);
    border-radius:7px; padding:8px 10px; font-size:.92rem; width:100%; }
  label { display:block; font-size:.82rem; color:var(--muted);
          margin:10px 0 4px; text-transform:uppercase; letter-spacing:.4px; }
  table { width:100%; border-collapse:collapse; font-size:.9rem; }
  th, td { text-align:left; padding:9px 10px; border-bottom:1px solid var(--line); }
  th { color:var(--muted); font-weight:600; font-size:.78rem;
       text-transform:uppercase; letter-spacing:.4px; }
  .tag { display:inline-block; padding:2px 9px; border-radius:20px;
         font-size:.76rem; font-weight:600; }
  .tag.blue { background:rgba(59,130,246,.22); color:#cfe4ff; }
  .tag.red  { background:rgba(239,68,68,.22); color:#ffd4d4; }
  .tag.all  { background:rgba(34,197,94,.22); color:#c6f6d5; }
  .flash { padding:11px 14px; border-radius:8px; margin-bottom:12px; font-size:.9rem; }
  .flash.ok { background:rgba(34,197,94,.12); border:1px solid rgba(34,197,94,.35); }
  .flash.error { background:rgba(239,68,68,.12); border:1px solid rgba(239,68,68,.35); }
  .muted { color:var(--muted); font-size:.86rem; }
  pre { background:#0d1218; border:1px solid var(--line); border-radius:8px;
        padding:12px; overflow:auto; font-size:.82rem; max-height:280px; }
  code { background:#0d1218; padding:2px 6px; border-radius:4px; font-size:.88rem; }
  .row { display:flex; gap:10px; flex-wrap:wrap; align-items:flex-end; }
  .row > div { flex:1; min-width:150px; }
  @media (max-width:600px){ .qr img { width:170px; height:170px; } }

  /* Utility classes replacing inline style attributes. CSP style-src 'self'
     forbids them, and a policy with 'unsafe-inline' is barely a policy. */
  .noflex { flex:0 0 auto; }
  .scrollx { overflow-x:auto; }
  .m0 { margin:0; }
  .mt0 { margin-top:0; }
  .mt10 { margin-top:10px; }
  .mt12 { margin-top:12px; }
  .mt16 { margin-top:16px; }
  .mt18-center { margin-top:18px; align-items:center; }
  .mb10 { margin:0 0 10px; }
  .ml8 { margin-left:8px; }
  .narrow { max-width:420px; }
  .tighttop { margin:-4px 0 10px; }
  .cardhead { margin:0 0 4px; font-size:1rem; }
  .dinline { display:inline; }
