:root {
  --bg: #0e1116;
  --panel: #161b22;
  --line: #2a313b;
  --text: #d7dde5;
  --muted: #8b949e;
  --accent: #58a6ff;
  --bad: #f0883e;
  --good: #3fb950;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  height: 100vh;
  height: 100dvh;   /* the page fits the screen: the spectrum and waterfall take what the other rows leave */
  min-height: 480px; /* on a smaller screen the page scrolls instead (the bottom bar stays in view) */
  display: flex;
  flex-direction: column;
}

header, #freqbar, #receiver, footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  padding: 10px 16px;
}

header { border-bottom: 1px solid var(--line); }
h1 { font-size: 21px; margin: 0; font-weight: 600; letter-spacing: 0.02em; }
.muted { color: var(--muted); }
.mono { font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; font-size: 13px; }

.chip {
  font-size: 12px;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
}
.chip-on { color: var(--good); border-color: var(--good); }
.chip-off { color: var(--bad); border-color: var(--bad); }

#freqbar, #receiver { background: var(--panel); border-bottom: 1px solid var(--line); }
.slider { display: flex; flex-direction: column; font-size: 13px; min-width: 150px; }
.slider output { font-family: ui-monospace, Consolas, monospace; }

input[type="text"], input[type="password"] {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 8px;
  font: inherit;
  font-family: ui-monospace, Consolas, monospace;
}
button {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 14px;
  font: inherit;
  cursor: pointer;
}
button:hover { border-color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.message {
  margin: 0;
  padding: 8px 16px;
  background: #3a2414;
  color: #ffd2a8;
  border-bottom: 1px solid var(--bad);
}
.message[hidden] { display: none; }

main { flex: 1; display: flex; flex-direction: column; min-height: 0; }
canvas { display: block; width: 100%; background: #000; cursor: crosshair; }
/* The spectrum and waterfall share the height that is left (2 : 3); the canvases fill their panes. */
.pane { position: relative; min-height: 60px; }
.pane:first-child { flex: 40 1 0; border-bottom: 1px solid var(--line); } /* the page sets the shares from the remembered ratio */
.pane:last-child { flex: 60 1 0; }
.pane canvas { position: absolute; left: 0; top: 0; height: 100%; touch-action: none; }
.dbstrip { position: absolute; left: 0; top: 0; bottom: 0; width: 54px; z-index: 1; cursor: ns-resize; touch-action: none; } /* over the dB labels of the spectrum: wheel = Ceiling, drag = Floor */
.dbstrip:hover { background: rgba(92, 200, 255, 0.06); }
.dbstrip.drag { background: rgba(92, 200, 255, 0.12); }
body.joined .dbstrip, body.joined .sqspec { pointer-events: none; }
.sqspec { position: absolute; left: 0; right: 0; height: 13px; margin-top: -6px; z-index: 1; cursor: ns-resize; touch-action: none; } /* over the orange squelch line: hover shows it can be grabbed */
.sqspec[hidden] { display: none; }
.sqspec::before { content: ""; position: absolute; left: 0; right: 0; top: 6px; height: 1px; background: #ff8c00; opacity: 0; }
.sqspec::after { content: "\2195"; position: absolute; left: 62px; top: -2px; font: 14px/16px sans-serif; color: #ff8c00; opacity: 0; } /* the up-and-down arrow */
.sqspec:hover::before, .sqspec.drag::before { opacity: 1; }
.sqspec:hover::after, .sqspec.drag::after { opacity: 1; }

#footRates:not(:empty) { padding-right: 10px; border-right: 1px solid #3a4654; margin-right: -4px; }
footer .footright { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; justify-content: flex-end; }
footer { border-top: 1px solid var(--line); justify-content: space-between; flex: none; position: sticky; bottom: 0; background: var(--bg); z-index: 5; }
.axisbar.vdragging { cursor: ns-resize; background: #323a46; }

/* receiver controls */
#receiver { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 8px 24px; }
#receiverRows { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
#receiver .row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; }
#receiver .label { color: var(--muted); font-size: 13px; min-width: 38px; }
#tuneForm { display: flex; align-items: center; gap: 8px; }
.btns { display: flex; flex-wrap: wrap; gap: 6px; }
.btns button { padding: 4px 11px; min-width: 44px; }
.radio-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; }
.role { font-family: inherit; cursor: default; font-size: 12px; color: #04121f; background: var(--accent); border: 1px solid var(--accent); font-weight: 600; border-radius: 10px; padding: 2px 9px; white-space: nowrap; } /* blue while monitoring, green while controlling */
.role.control { background: var(--good); border-color: var(--good); }
.rolerow { display: flex; align-items: center; gap: 8px; }
/* Follow Control: greyed out in control; white on black when it can be used; filled blue with black text while following */
.role.followbtn { cursor: pointer; color: #fff; background: #000; border: 1px solid var(--line); font-weight: 400; }
.role.followbtn:disabled { opacity: 0.4; cursor: not-allowed; }
.role.followbtn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #000; font-weight: 600; }
#lockButton { margin-left: 8px; align-self: center; }
#lockButton, .tabbtn { width: 56px; padding-left: 0; padding-right: 0; text-align: center; } /* Lock, Step and Cal are one size */
.fgroup + .stepgroup { margin-left: -16px; } /* Lock to Step as close as Step to Cal (the bar's gap is 28px, this makes it 12) */
#lockButton[aria-pressed="true"] { background: #d73a3a; border-color: #d73a3a; color: #fff; font-weight: 600; } /* locked: red, like Mute */
.btns button:disabled, #bands button:disabled, .radio-control select:disabled, #centreButton:disabled { opacity: 0.45; cursor: not-allowed; }
#axisBar.locked { cursor: default; }
.radio-control { display: flex; align-items: center; gap: 8px; }
#receiverRows .radio-slider { width: 150px; } /* the radio's own sliders (LNA state with its dB, IF gain): room for "LNA 12 = 42 dB" */
.radio-slider input:disabled { opacity: 0.45; cursor: not-allowed; }
.overload-badge { font-size: 12px; font-weight: 700; color: #fff; background: #d73a3a; border-radius: 10px; padding: 2px 9px; }
.radio-control .label { min-width: 0; }
[hidden] { display: none !important; }
.btns button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
#listen, #listenC { min-width: 4.6em; padding-left: 8px; padding-right: 8px; } /* wide enough for "Muted", so the label never resizes it */
#listen[aria-pressed="true"], #listenC[aria-pressed="true"] { background: #000; border-color: var(--line); color: #fff; } /* audio on: white on black */
#listen[aria-pressed="false"], #listenC[aria-pressed="false"] { background: #d73a3a; border-color: #d73a3a; color: #fff; font-weight: 600; } /* muted: red */
select {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 4px 6px;
  font: inherit;
}
#smeterBox { display: flex; flex-direction: column-reverse; align-items: flex-start; gap: 3px; min-width: 0; padding-top: 14px; } /* the label above the bar */
#smeter { position: relative; width: 100%; height: 16px; background: #000; border: 1px solid var(--line); border-radius: 3px; overflow: hidden; }
#smeterTicks span { position: absolute; bottom: 0; width: 1px; height: 6px; background: #8b949e; pointer-events: none; }
#smeterTicks span.s9 { height: 10px; background: #d7dde5; }
#smeterGap { position: absolute; top: 0; bottom: 0; left: 0; width: 0; background: rgba(88, 166, 255, 0.5); pointer-events: none; } /* from the level now to the peak marker: pale blue, the same as the AFC button */
#smeterFill { position: relative; z-index: 0; }
.slider.off { opacity: 0.45; }
#nb { display: inline-flex; }
.smwrap { position: relative; width: 270px; top: 2px; } /* the meter takes the width the squelch slider used to have; level with the sliders' tracks */
#smeterText { position: absolute; left: 100%; top: 0; margin-left: 8px; line-height: 18px; white-space: nowrap; } /* the reading sits at the right end of the bar, in line with it */
#smeterBox .smscale { position: absolute; left: 0; right: 0; top: -11px; height: 10px; pointer-events: none; font: 9px/10px var(--mono, monospace); color: #8b949e; }
#smeterBox .smscale span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
#smeterBox .smscale span.s9 { color: #d7dde5; }
.s9confirm { position: fixed; z-index: 60; width: 250px; padding: 10px 12px; background: var(--panel, #161b22); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,.5); font-size: 13px; }
.s9confirm .s9row { display: flex; gap: 8px; margin-top: 8px; }
#smeterPeak { z-index: 3; position: absolute; top: 2px; bottom: 2px; width: 2px; margin-left: -1px; background: #fff; pointer-events: none; } /* the peak, falling back slowly */
.sqline { position: absolute; top: 0; height: 16px; width: 15px; margin-left: -7px; cursor: ew-resize; touch-action: none; z-index: 2; } /* the squelch level: a line that sticks out above the bar and is easy to grab */
.sqline::after { content: ""; position: absolute; left: 6px; width: 2px; top: 3px; bottom: 3px; background: #f85149; } /* inside the bar, as high as the peak marker */
.sqline[hidden] { display: none; }
.sqline:hover::after, .sqline.drag::after, .sqline:focus-visible::after { background: var(--accent); } /* blue while the pointer is on it or it is being moved */
body.joined .sqline { pointer-events: none; opacity: 0.55; }
#smeterFill { height: 100%; width: 0; background: var(--accent); }
#listenNote { margin: 0; font-size: 13px; color: var(--bad); }
#listenNote[hidden] { display: none; }

/* the tuned-signal marker drawn over the spectrum and waterfall */
.mband, .mline { position: absolute; top: 0; bottom: 0; pointer-events: none; }
.mband { background: rgba(255, 140, 0, 0.16); }
.mgrip { position: absolute; top: 0; bottom: 0; width: 14px; margin-left: -7px; z-index: 1; cursor: ew-resize; touch-action: none; }
.mgrip[hidden] { display: none; }
.mgrip::after { content: ""; position: absolute; left: 6px; width: 2px; top: 0; bottom: 0; background: transparent; }
.mgrip:hover::after, .mgrip.drag::after { background: #ff8c00; }
@media (pointer: coarse) { .mgrip { width: 28px; margin-left: -14px; } .mgrip::after { left: 13px; } }
body.joined .mgrip { display: none; } /* following the controller: the channel cannot be changed here */
.mline { width: 1px; background: #ff8c00; }

/* the two frequency displays: big digits, each of which can be changed with the mouse wheel */
#freqbar { gap: 8px 28px; padding-top: 14px; padding-bottom: 14px; }
.fgroup { display: flex; align-items: center; gap: 12px; }
.flabel { color: var(--muted); font-size: 14px; min-width: 52px; }
.funit { color: var(--muted); font-size: 15px; }
.fdisplay {
  font: 600 44px/1.1 Bahnschrift, "Segoe UI", "SF Pro Display", Roboto, "Helvetica Neue", Arial, sans-serif; /* a cleaner face than the monospace one; the digits sit in fixed cells either way */
  font-variant-numeric: tabular-nums;
  background: #000;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 14px;
  color: #7ee787;
  user-select: none;
  white-space: nowrap;
}
.fdisplay .digit { display: inline-block; width: 0.62em; text-align: center; border-radius: 4px; cursor: ns-resize; }
.fdisplay .digit.lead { opacity: 0.28; }
.fdisplay .digit:hover { background: rgba(255, 255, 255, 0.22); }
.fdisplay .sep { display: inline-block; position: relative; width: 0.3em; height: 0.8em; color: transparent; overflow: hidden; opacity: 0.6; pointer-events: none; vertical-align: baseline; }
/* the dot is a small circle, centred in its gap and on the baseline, so it sits in the same place whatever font the PC has */
.fdisplay .sep::after { content: ""; position: absolute; left: 50%; bottom: 0.02em; width: 0.12em; height: 0.12em; margin-left: -0.06em; border-radius: 50%; background: #7ee787; }
.compactbar { display: none; align-items: flex-end; gap: 16px; margin-left: 12px; }
.compactvol { width: 150px; }
.compactbar select { min-width: 5.5em; }
body.controls-hidden .stepgroup, body.controls-hidden #lockButton { display: none; }
body.controls-hidden .compactbar { display: flex; } /* the dot overhangs its box: it must not catch the pointer meant for the digit beside it */
.fedit {
  font: 600 38px/1.1 ui-monospace, Consolas, monospace;
  width: 8.2em;
  background: #000;
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 6px 14px;
}
.fedit[hidden], .fdisplay[hidden] { display: none; }
@media (max-width: 640px) { .fdisplay { font-size: 32px; } }

/* Floor and Ceiling sit over the top left of the spectrum, stacked */
.panetl { position: absolute; left: 58px; top: 8px; z-index: 2; display: flex; align-items: flex-start; gap: 8px; pointer-events: none; }
.panetl > * { pointer-events: auto; }
.overlay {
  position: absolute;
  left: 58px;
  top: 8px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 10px;
  background: rgba(14, 17, 22, 0.72);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 12px;
}
.overlay .slider { min-width: 0; width: 140px; font-size: 12px; }
.overlay .slider label, .overlay .slider output { color: var(--muted); } /* the same grey as Band, Mode and AGC */
input[type="range"] { height: 16px; background: transparent; -webkit-appearance: none; appearance: none; }
.overlay input[type="range"] { width: 100%; margin: 2px 0; }
/* every slider: a blue thumb on a grey track (not the browser's blue-filled or white one) */
input[type="range"]::-webkit-slider-runnable-track { height: 4px; background: #4a525c; border-radius: 2px; }
input[type="range"]::-moz-range-track { height: 4px; background: #4a525c; border-radius: 2px; }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; margin-top: -5px; border: 0; border-radius: 50%; background: var(--accent); }
input[type="range"]::-moz-range-thumb { width: 14px; height: 14px; border: 0; border-radius: 50%; background: var(--accent); }

/* the button that makes the tuned frequency the centre */
.label-agc { margin-left: 8px; }

/* "Step" beside its drop-down, in line with the other controls, with the drop-down only as wide as its text */
.inline { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.inline .label { min-width: 0; font-size: 12px; line-height: 1; }
#step { width: 5.8em; padding: 4px 4px; }

/* the title */
h1 sup { font-size: 0.55em; font-weight: 500; vertical-align: super; line-height: 0; margin-left: 1px; color: var(--muted); }
h1 .simply { color: #fff; }
h1 .sdrx, h1 .sdrx sup { color: var(--accent); }
header { font-size: 16px; }
header .chip { font-size: 14px; }
header .role { font-size: 14px; }
h1 .by { font-weight: 400; color: var(--muted); margin: 0 2px; }

/* Snap and Pause: top right of the spectrum, wherever the window is sized; blue while on / paused */
.overlay-right {
  position: absolute;
  right: 10px;
  top: 8px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}
.ovbuttons { display: flex; gap: 8px; }
.ovbuttons.none { display: none; } /* nothing ticked: the cogwheel takes the top place */
.ovbuttons button.ovhide { display: none !important; }
.ovrow2 { display: flex; align-items: center; gap: 8px; }
.overlay-right .gear { position: static; padding: 0; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; } /* the button rule below gives 14px side padding, which squeezed the 32px box and pushed the cog off-centre (and, on an iPad, partly out of view) */
.chooser { position: absolute; right: 0; top: 100%; margin-top: 4px; min-width: 150px; padding: 8px 12px 8px 12px; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); }
.chooser .panel-x { position: static; display: block; margin: -4px -6px 2px auto; } /* the x has a line to itself at the top */
.ovlist { display: flex; flex-direction: column; gap: 4px; }
.ovsep { height: 0; border-top: 1px solid #3a4654; margin: 4px 0; }
.ovlist label { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.overlay-right button { background: rgba(14, 17, 22, 0.72); padding: 4px 14px; }
.overlay-right button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
.afcout { font-size: 11px; color: #a9b8c8; white-space: nowrap; pointer-events: none; text-shadow: 0 0 3px #000; }
.overlay-right button.inop { opacity: 0.5; } /* on, but not acting: the step is above 1 kHz */

/* the frequency scale under the spectrum: a strip you can drag to change the frequency */
.axisbar {
  flex: none;
  height: 32px;
  background: #12171d;
  border-bottom: 1px solid var(--line);
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.axisbar:hover { background: #262d37; }       /* lighter while the pointer is over it */
.axisbar.dragging { background: #323a46; cursor: grabbing; }
.axisbar.zooming { background: #323a46; cursor: ew-resize; }
#axis { width: 100%; height: 100%; display: block; background: transparent; cursor: inherit; }

/* the relay's landing page */
.lmain { padding: 14px 16px; gap: 22px; max-width: 1100px; width: 100%; margin: 0 auto; }
.lmain h2 { font-size: 15px; margin: 0 0 8px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.lchoices { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px 16px; }
.ldiag { display: flex; align-items: center; gap: 8px; margin: 6px 0 14px; flex-wrap: nowrap; }
.ldiag .lbox { border: 1px solid var(--line); border-radius: 8px; background: var(--bg); padding: 8px 12px; text-align: center; font-weight: 600; white-space: nowrap; }
.ldiag .lbox small { display: block; font-weight: 400; font-size: 11px; color: var(--muted); white-space: normal; max-width: 130px; }
.ldiag .larrow { flex: 1 1 90px; min-width: 70px; display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: 12px; }
.ldiag .larrow i { display: block; width: 100%; height: 0; border-top: 2px solid var(--accent); position: relative; }
.ldiag .larrow i::after { content: ""; position: absolute; right: -1px; top: -6px; border-left: 8px solid var(--accent); border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.ldiag .larrow small { color: var(--muted); font-size: 11px; }
@media (max-width: 640px) {
  .ldiag { flex-direction: column; align-items: stretch; }
  .ldiag .larrow { flex-direction: row; justify-content: center; min-width: 0; }
  .ldiag .larrow i { width: 0; height: 28px; border-top: 0; border-left: 2px solid var(--accent); }
  .ldiag .larrow i::after { right: auto; top: auto; bottom: -1px; left: -6px; border-top: 8px solid var(--accent); border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 0; }
}
.lchoice { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; margin-bottom: 8px; }
.lchoice .label { color: var(--muted); font-size: 13px; min-width: 150px; }
.lchoice label { display: inline-flex; align-items: center; gap: 6px; }
.lchoice select { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px; font: inherit; }
.lnote { flex-basis: 100%; margin: 2px 0 0; font-size: 13px; }
.lcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 12px; }
.lcard { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
.lcard.offline { opacity: 0.75; }
.lrate select { align-self: flex-start; max-width: 100%; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 3px 8px; font: inherit; font-size: 13px; }
.lratenote { font-size: 13px; }
.lhead { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.lhead h3 { margin: 0; font-size: 17px; }
.lfact { display: flex; flex-direction: column; font-size: 14px; }
.lfact .muted { font-size: 12px; }
.lcard a.lopen { margin-top: 6px; align-self: flex-start; background: var(--accent); color: #04121f; font-weight: 600; text-decoration: none; padding: 6px 16px; border-radius: 6px; }
.lcard a.lopen:hover { filter: brightness(1.1); }

/* the relay console */
.cchips { display: flex; gap: 6px; flex-wrap: wrap; }
.cbar { height: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: 4px; overflow: hidden; margin-top: 4px; }
.cbarfill { height: 100%; background: var(--accent); }
.cbarfill.high { background: var(--bad); }
.cbarfill.full { background: #f85149; }
.cactions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.cactions input { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px; font: inherit; font-family: ui-monospace, Consolas, monospace; }
.cactions button.on { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
.lchoice .mono { word-break: break-all; }

/* login and "access" pages */
.loginmain { max-width: 520px; }
.loginform { display: flex; flex-direction: column; gap: 8px; }
.loginform label { color: var(--muted); font-size: 13px; }
.loginform input { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; font: inherit; }
.loginform button { margin-top: 8px; padding: 8px 14px; background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
.loginform button:disabled { opacity: 0.6; cursor: wait; }
.loginerror { margin: 4px 0 0; padding: 8px 10px; background: #3a2414; color: #ffd2a8; border: 1px solid var(--bad); border-radius: 6px; }
.expiredmessage { font-size: 16px; }
.lwho { display: flex; align-items: center; gap: 12px; margin-left: auto; font-size: 13px; }
.lwho button { padding: 2px 10px; font-size: 13px; }
.perm { display: block; font-size: 14px; margin: 2px 0; }
.perm .muted { margin-left: 8px; }
#passwordShown code { font-size: 18px; padding: 2px 8px; user-select: all; }
.slog { min-height: 8em; max-height: 40em; height: 16em; resize: vertical; overflow: auto; font-size: 12px; white-space: pre-wrap; word-break: break-all; margin: 4px 0 0; padding: 6px; border: 1px solid #8884; border-radius: 4px; }
.lcard a { color: var(--accent); }
.unsaved { color: #e3b341; margin-left: 8px; }

/* Jog bar: spring-loaded tuning bar for touch screens */
.jog { display: flex; align-items: center; gap: 10px; width: max(260px, 33vw); max-width: calc(100% - 32px); margin: 6px auto 8px; } /* bottom of the screen, centred under the waterfall */
.jog[hidden] { display: none; }
.jog-arrow { color: var(--accent); font-size: 18px; user-select: none; }
.jog-track { position: relative; flex: 1; height: 31px; border: 1px solid var(--accent); border-radius: 8px; background: var(--panel); touch-action: none; user-select: none; -webkit-user-select: none; }
.jog-centre { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line); pointer-events: none; }
.jog-handle { position: absolute; top: 3px; bottom: 3px; left: calc(50% - 26px); width: 52px; border-radius: 6px; background: var(--accent); cursor: grab; touch-action: none; }
.jog-handle.dragging { background: var(--good); cursor: grabbing; }

/* Memories: a grid of stored stations beside the receiver controls */
#memories { position: relative; width: 252px; }
.memhead { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; margin-bottom: 4px; }
.memband { color: var(--accent); font-size: 13px; }
.memstate { color: var(--bad); font-size: 12px; }
.memmore { margin-left: auto; padding: 0 8px; line-height: 1.2; }
.memgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px; }
.memslot { padding: 3px 6px; font-size: 12px; height: 26px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; touch-action: manipulation; user-select: none; -webkit-user-select: none; }
.memslot.empty { color: var(--muted); opacity: 0.55; text-align: center; }
.memslot.here { border-color: var(--good); }
.mempop { position: absolute; right: 0; top: 24px; z-index: 20; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; padding: 8px; display: flex; flex-direction: column; gap: 6px; width: 200px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); }
.mempop[hidden] { display: none; }
.mempop-row { display: flex; gap: 6px; }
.mempop input[type="text"] { width: 100%; }
@media (max-width: 1140px) { #receiver { grid-template-columns: minmax(0, 1fr); } #memories { width: 100%; } .memgrid { grid-template-columns: repeat(5, 1fr); } }

/* Step and Fine sit beside Centre; the Control/Monitor label (and, later, Shadow) at the right of the frequency bar */
.stepgroup { display: flex; align-items: center; gap: 12px; }
.tabpanel { display: flex; align-items: center; gap: 12px; }
.tabpanel[hidden] { display: none; }
.eyewrap { position: relative; display: inline-flex; align-items: center; }
.eyewrap input { padding-right: 32px; }
.eye { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; padding: 3px; background: none; border: none; color: var(--muted, #8a94a3); cursor: pointer; }
.eye:hover { color: var(--text); border: none; }
.eye[aria-pressed="true"] { color: var(--accent); }
.tabpanel .inline { position: relative; } /* the label sits above the drop-down without making the group taller, so the boxes and the Cal readout line up with the Step and Cal buttons */
.tabpanel .inline .label { position: absolute; left: 2px; bottom: 100%; margin-bottom: 1px; white-space: nowrap; }
.tabbtn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; } /* blue while its controls are open */
.tabbtn { min-width: 3.4em; } /* Step and Cal: each opens its own controls beside it (the other one closes); pressing it again closes it */
.statusbox { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }

/* The Memories grid sits right beside the receiver rows, not at the far edge */
@media (min-width: 1141px) { #receiver { grid-template-columns: minmax(0, max-content) max-content; justify-content: start; } }

/* The jog bar lies along the lower edge of the waterfall, the waterfall's own controls at its lower left */
.jog { position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); z-index: 3; margin: 0; width: max(260px, 33vw); max-width: calc(100% - 16px); pointer-events: none; }
.jog > * { pointer-events: auto; }
.jog-track { background: rgba(22, 27, 34, 0.78); }
#waterfallControls { top: auto; bottom: 8px; left: 8px; }
.panel-x { position: absolute; top: 3px; right: 4px; padding: 0 6px; line-height: 1.2; font-size: 12px; background: transparent; border: none; color: var(--muted); }
.panel-x:hover { color: var(--text); border: none; }
.overlay { padding-right: 26px; }
.gear { position: absolute; z-index: 2; width: 32px; height: 32px; padding: 0; font-size: 18px; line-height: 1; background: rgba(14, 17, 22, 0.72); }
.gear[hidden] { display: none; }
.panetl .gear { position: relative; }
#paneTopLeft #displayControls { position: relative; left: auto; top: auto; }
#controlsToggle { color: #fff; background: #000; }
#controlsToggle[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #000; }
body.controls-hidden #receiver { display: none; }
#waterfallGear { left: 8px; bottom: 8px; }
.overlay[hidden] { display: none; }
@media (max-width: 760px) {
  .jog { width: calc(100% - 16px); }
  body.jog-on #waterfallControls, body.jog-on #waterfallGear { bottom: 48px; }
}

/* The Mem button (shows and hides the grid) and the floating form of the grid on touch screens */
#memToggle[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
#memories[hidden] { display: none; }
#memories.floating { position: fixed; right: 12px; bottom: 64px; z-index: 30; width: 252px; padding: 8px; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); }
#memories.floating .memgrid { grid-template-columns: repeat(2, 1fr); }
#memories.floating .memhead { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
#memories.floating .memhead.dragging { cursor: grabbing; }

/* the receiver's sliders are 20% narrower; the Squelch word is a switch */
#receiverRows .slider { min-width: 0; width: 120px; }
.sqhead { display: flex; align-items: baseline; gap: 6px; }
.linkbtn { background: none; border: none; padding: 0; color: inherit; font: inherit; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.linkbtn:hover { color: var(--accent); border: none; }
#squelchToggle, #squelchToggle[aria-pressed="true"] { text-decoration: none; } /* the Squelch word is a switch, but needs no dotted line to say so */
.linkbtn[aria-pressed="true"] { color: var(--accent); text-decoration-style: solid; }

/* on a touch screen the tuning hint and the pointer readout have no use and the height is needed */
@media (pointer: coarse) { #cursor { display: none; } }

/* the people panel: opened from the Control/Monitor label when more than one person is on the radio */
.role.more { cursor: pointer; }
.role.more::after { content: " \25BE"; }
.people { position: fixed; z-index: 30; min-width: 220px; max-width: min(340px, calc(100vw - 16px)); max-height: 60vh; overflow: auto; background: var(--panel, #1b2028); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5); }
.people[hidden] { display: none; }
.profiles { min-width: 300px; max-width: min(420px, calc(100vw - 16px)); }
.profrow { display: grid; grid-template-columns: minmax(110px, 1fr) 64px 22px; gap: 6px; align-items: center; }
.profrow { padding: 3px 0; }
.profrow input { font: inherit; font-size: 13px; background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px; min-width: 0; }
.profrow button { font-size: 12px; padding: 3px 4px; }
.profrow button.cell.full { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
.profrow button.cell.empty { color: var(--muted, #8a94a3); }
.profrow button.x { background: transparent; border: none; color: var(--muted, #8a94a3); padding: 0 2px; }
.profactions { margin-top: 6px; }
.rightblock { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; } /* right end of the frequency bar, under the Control / Monitor label */
.rbrow { display: flex; gap: 6px; }
.assetslist .arow { display: grid; grid-template-columns: auto 1fr auto; gap: 4px 8px; align-items: center; padding: 4px 0; border-bottom: 1px solid var(--line); }
.assetslist .arow:last-child { border-bottom: none; }
.assetslist .adot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted, #8a94a3); display: inline-block; }
.assetslist .adot.on { background: #3fb950; }
.assetslist .aname { color: var(--accent); cursor: pointer; background: none; border: none; text-align: left; padding: 0; font-size: 14px; }
.assetslist .aname[aria-current="true"] { font-weight: 700; }
.assetslist .ainfo { grid-column: 2 / 4; font-size: 12px; }
.assetspanel { min-width: 300px; max-width: 420px; }
.profilebtn { cursor: pointer; color: #fff; background: #000; border: 1px solid var(--line); font-weight: 400; }
.profilebtn[aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: #000; font-weight: 600; }
.peoplehead { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.peoplelist { list-style: none; margin: 0; padding: 0; }
.peoplelist li { display: flex; justify-content: space-between; gap: 16px; padding: 3px 0; font-size: 14px; }
.peoplelist .since { color: var(--muted, #8a94a3); white-space: nowrap; }
.peoplelist .tag { color: var(--muted, #8a94a3); font-size: 12px; margin-left: 6px; }
.peoplehead .panel-x { position: static; }
#calButton.on { border-color: var(--accent); }
#calButton { white-space: nowrap; }

.calerr { font-size: 13px; font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; color: var(--text); min-width: 11.5em; padding: 2px 6px; border: 1px solid var(--line); border-radius: 6px; white-space: nowrap; }
.calerr.off { opacity: 0.45; }
/* Joined: the controller's channel is shown and cannot be changed here */
body.joined #modes, body.joined #bands, body.joined #agc, body.joined #nb, body.joined #bwBox, body.joined #rfBox, body.joined #sqBox, body.joined #lowBox,
body.joined #tunedDisplay, body.joined #step, body.joined #fine { pointer-events: none; opacity: 0.55; }

/* FreeDV */
.fdvstatus { display: none !important; } /* the status text is kept (see showFdv) but not shown beside the S-meter; it is in the bank header and the FreeDV text area */
.fdvstatus.sync { color: #3fb950; }
.fdvinfo { font-size: 13px; line-height: 1.5; padding: 4px 2px; min-width: 200px; }
.fdvinfo .call { font-size: 20px; font-weight: 600; letter-spacing: .04em; }
#fdvButton[aria-pressed="true"].through { background: #3fb950; border-color: #3fb950; color: #04121f; }

/* the Tune Line: where a click would tune (an option in the buttons list) */
.tuneline { position: absolute; top: 0; bottom: 0; width: 1px; margin-left: -0.5px; background: rgba(230, 237, 243, 0.55); pointer-events: none; z-index: 3; }
.tunelabel { position: absolute; top: 4px; padding: 0 4px; font: 12px/16px ui-monospace, "SFMono-Regular", Consolas, monospace; color: #f2cc60; background: rgba(0, 0, 0, 0.6); border-radius: 2px; pointer-events: none; z-index: 3; white-space: nowrap; }
.tuneline[hidden], .tunelabel[hidden] { display: none; }

/* the offer of control, when the controller has left */
.offerbox { position: fixed; z-index: 70; left: 50%; top: 22%; transform: translateX(-50%); width: min(92vw, 380px); padding: 14px 16px; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 24px rgba(0,0,0,.6); font-size: 14px; }
.offerbox .offerhead { font-weight: 600; margin-bottom: 6px; }
.offerbox .offerrow { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* VFOs: extra tuned frequencies under buttons at the top left of the spectrum; thin yellow lines mark the others that are in view */
.vfobar { display: flex; gap: 6px; align-items: flex-start; }
.vfobar[hidden] { display: none; }
.vfobtn { height: 32px; padding: 0 9px; font-size: 12px; color: #fff; background: #000; border: 1px solid var(--line); white-space: nowrap; }
.vfobtn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #000; font-weight: 600; }
.vfoline { position: absolute; top: 0; bottom: 0; width: 1px; margin-left: -0.5px; background: #f2cc60; opacity: 0.85; pointer-events: none; z-index: 1; }
.vfoline[hidden] { display: none; }
.vfoctl { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; padding-right: 24px; } /* keeps < and > clear of the panel's close x */
.vfoctl span { flex: 1; }
.vfoctl button { min-width: 30px; padding: 2px 8px; }

/* following the controller: the display settings are the controller's (shown, not changeable here) */
body.joined #displayControls, body.joined #waterfallControls, body.joined #axisBar, body.joined #wide, body.joined #track { pointer-events: none; opacity: 0.55; }

/* the FreeDV Reporter panel: the stations on the current band, floating */
#dvRep[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #000; }
.dvpanel { position: fixed; z-index: 35; right: 12px; top: 120px; width: 360px; height: 340px; max-width: calc(100vw - 8px); max-height: calc(100vh - 8px); display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); }
.dvpanel[hidden] { display: none; }
.dvhead { display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; border-bottom: 1px solid var(--line); }
.dvhead.dragging { cursor: grabbing; }
.dvtitle { font-weight: 600; font-size: 13px; }
.dvstate { flex: 1; font-size: 11px; text-align: right; }
.dvhead .panel-x { position: static; }
.dvlist { flex: 1; min-height: 0; overflow-y: auto; padding: 4px; display: flex; flex-direction: column; gap: 2px; min-height: 40px; }
.dvrow { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 34px 52px; gap: 6px; align-items: center; width: 100%; padding: 3px 6px; font: 12px/1.3 ui-monospace, "SFMono-Regular", Consolas, monospace; text-align: left; color: var(--fg, #e6edf3); background: #000; border: 1px solid transparent; border-radius: 4px; cursor: pointer; }
.dvrow:hover { border-color: var(--accent); }
.dvrow.tx { background: #5a1d1d; border-color: #f85149; }
.dvrow.here { border-color: var(--good); }
.dvrow .snr { text-align: right; color: #8b949e; }
.dvrow .grid { color: #8b949e; text-align: right; }
.dvnote { padding: 4px 8px 6px; font-size: 11px; }

/* the grips on the panel's edges and corners: drag to resize */
.dvedge { position: absolute; z-index: 2; touch-action: none; }
.dvedge.n, .dvedge.s { left: 10px; right: 10px; height: 8px; cursor: ns-resize; }
.dvedge.e, .dvedge.w { top: 10px; bottom: 10px; width: 8px; cursor: ew-resize; }
.dvedge.n { top: -4px; } .dvedge.s { bottom: -4px; } .dvedge.e { right: -4px; } .dvedge.w { left: -4px; }
.dvedge.ne, .dvedge.nw, .dvedge.se, .dvedge.sw { width: 14px; height: 14px; }
.dvedge.ne { top: -5px; right: -5px; cursor: nesw-resize; } .dvedge.sw { bottom: -5px; left: -5px; cursor: nesw-resize; }
.dvedge.nw { top: -5px; left: -5px; cursor: nwse-resize; } .dvedge.se { bottom: -5px; right: -5px; cursor: nwse-resize; }
.dvedge:hover { background: rgba(88, 166, 255, 0.35); }
@media (pointer: coarse) { .dvedge.n, .dvedge.s { height: 16px; } .dvedge.e, .dvedge.w { width: 16px; } .dvedge.ne, .dvedge.nw, .dvedge.se, .dvedge.sw { width: 24px; height: 24px; } }

/* Station ID: the best guess over the tuned frequency, the last overlay on the spectrum (everything else is under it) */
.stlabel { position: absolute; top: 6px; z-index: 9; max-width: 70%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 2px 9px; font: 13px/18px ui-sans-serif, system-ui, sans-serif; color: #e6edf3; background: rgba(8, 12, 18, 0.9); border: 1px solid #5cc8ff; border-radius: 4px; pointer-events: none; }
.stlabel[hidden] { display: none; }
.stlabel.likely { border-color: #3fb950; }
.stlabel.possible { border-color: #5cc8ff; }
.stlabel.unlikely { border-color: #6e7781; color: #b6c0ca; }
.stwhere { margin-left: 8px; padding: 0 6px; font-size: 11px; line-height: 16px; }
.stidform { position: fixed; z-index: 80; left: 50%; top: 16%; transform: translateX(-50%); width: min(94vw, 420px); padding: 14px 16px; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.6); font-size: 14px; display: flex; flex-direction: column; gap: 8px; }
.stidform h3 { margin: 0; font-size: 16px; }
.stidform .hint { margin: 0; color: var(--muted); font-size: 13px; }
.stidform .opt { display: flex; align-items: center; gap: 6px; }
.stidform input[type="text"] { width: 100%; box-sizing: border-box; padding: 5px 8px; }
.stidform .llrow { display: flex; gap: 8px; }
.stidform .preview { min-height: 18px; font-size: 13px; color: #3fb950; }
.stidform .preview.bad { color: #f85149; }
.stidform .btnrow { display: flex; gap: 8px; justify-content: flex-end; align-items: center; }
.stidform .unitsrow { display: flex; align-items: center; gap: 10px; margin-right: auto; font-size: 13px; color: var(--muted); }
.stidform .unitsrow label { display: flex; align-items: center; gap: 4px; color: var(--text); }
.stidform input:disabled { opacity: 0.45; }
#layouts button { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 8px 12px; max-width: 190px; }
#layouts button.on { background: var(--accent); border-color: var(--accent); color: #04121f; }
#layouts button.on .muted { color: #04121f; }
#setupBody h3 { margin: 4px 0; }
.stlabel .stsub { font-size: 11px; line-height: 15px; color: #9fb3c8; }

/* Audio only: the spectrum and waterfall are not shown (and the web server does not send them) */
body.audio-only main { display: none; }
.audioonly { margin: 12px 16px; padding: 14px 16px; border: 1px solid var(--line, #30363d); border-radius: 8px; background: var(--panel, #161b22); }
.audioonly[hidden] { display: none; }
.audioonly p { margin: 0 0 10px; }

/* Audio only: white on black like the Mute button, red while audio-only mode is on */
#audioOnlyBtn { background: #000; border-color: var(--line); color: #fff; font-weight: 600; }
#audioOnlyBtn.tabbtn { width: auto; padding-left: 10px; padding-right: 10px; } /* the same button as Lock, Step and Cal, wide enough for its text */
#audioOnlyBtn[aria-pressed="true"] { background: #d73a3a; border-color: #d73a3a; color: #fff; }

/* a title row with the close X, and a line under it, on the Spectrum chooser and the Scaling / VFOs panel */
.chead { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-bottom: 1px solid #3a4654; padding-bottom: 3px; margin-bottom: 8px; font-size: 13px; color: var(--muted); }
.chead .panel-x, .chooser .chead .panel-x { position: static; display: block; margin: 0; }

/* the Floor and Ceiling sliders run the other way: moving to the right lowers the level */
input[type="range"].reversed { direction: rtl; }

/* past S9 the S-meter bar is red, and the gap to the peak marker a paler red */
#smeterOver { position: absolute; top: 0; bottom: 0; left: 0; width: 0; background: #d73a3a; pointer-events: none; }
#smeterOverGap { position: absolute; top: 0; bottom: 0; left: 0; width: 0; background: rgba(215, 58, 58, 0.5); pointer-events: none; }
#smeterMid { position: absolute; top: 0; bottom: 0; left: 0; width: 0; background: #e3b341; pointer-events: none; }
#smeterMidGap { position: absolute; top: 0; bottom: 0; left: 0; width: 0; background: rgba(227, 179, 65, 0.5); pointer-events: none; }
#smeterFill { position: absolute !important; left: 0; }
#smeterCues { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
#smeterCues span { position: absolute; top: 0; bottom: 0; width: 1px; background: rgba(0, 0, 0, 0.75); }
#fPlain[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }

/* the bandwidth readout above the pointer while a passband edge can be dragged */
.bwtip { position: fixed; z-index: 70; transform: translateX(-50%); padding: 1px 7px; background: #0e1116; border: 1px solid #ff8c00; border-radius: 4px; color: #ff8c00; font: 12px/18px var(--mono, monospace); pointer-events: none; white-space: nowrap; }
.bwtip[hidden] { display: none; }
.vfobtn.saved { box-shadow: 0 0 0 2px #3fb950; } /* a VFO that has just been stored */

/* the console's list of who is on a radio now */
.cpeople { flex-basis: 100%; display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.cperson { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }

#stats.lost { color: #f85149; font-weight: 600; } /* the radio is lost and being brought back */
.keeprow { display: flex; align-items: center; gap: 8px; font-size: 14px; margin: 4px 0 10px; }
.linkbanner { position: fixed; top: 0; left: 0; right: 0; z-index: 60; text-align: center; padding: 6px 12px; font-size: 14px; font-weight: 600; color: #fff; }
.linkbanner[hidden] { display: none; }
.linkbanner.bad { background: #b3261e; }
.linkbanner.warn { background: #a8670a; }
.linkbanner.ok { background: #1f7a3a; }

#smeterBox .smscale span:first-child { transform: none; } /* the ends stay inside the bar: "1" starts at its left edge ... */
#smeterBox .smscale span:last-child { transform: translateX(-100%); } /* ... and "+20" ends at its right edge */

/* ---- Themes (experimental; the Themes button) ----------------------------------------------------------------------------------------
   A theme is a set of colour variables here, the waterfall palette and trace colour in app.js, and for the 3D themes (data-3d on the page: Studio,
   Studio grain, Studio brushed) bevelled buttons and sliders and sunken panels. With no data-theme the page has its original look. --btn-face is
   what an ordinary button is painted with. */
:root { --btn-face: var(--bg); --on-accent: #04121f; }
:root[data-theme="amber"] { --bg: #120c04; --panel: #1c1308; --line: #4a3515; --text: #f2d9a8; --muted: #a58a58; --accent: #ffb000; --bad: #ff6a3d; --good: #9acd32; color-scheme: dark; }
:root[data-theme="ocean"] { --bg: #07131a; --panel: #0c1f2a; --line: #1d4252; --text: #d3eef0; --muted: #7fa9b3; --accent: #4fe3c1; --bad: #f5a25d; --good: #5fd38d; color-scheme: dark; }
:root[data-theme="nightred"] { --bg: #0b0000; --panel: #150404; --line: #4a1212; --text: #ff6b5e; --muted: #b3443c; --accent: #ff3b30; --bad: #ff8a00; --good: #ff6b5e; --on-accent: #1a0000; color-scheme: dark; }
:root[data-theme="highcontrast"] { --bg: #000; --panel: #0a0a0a; --line: #ffffff; --text: #ffffff; --muted: #d0d0d0; --accent: #ffe600; --bad: #ff7b00; --good: #00ff66; --on-accent: #000; color-scheme: dark; }
:root[data-theme="nord"] { --bg: #2e3440; --panel: #3b4252; --line: #4c566a; --text: #eceff4; --muted: #a3adc0; --accent: #88c0d0; --bad: #d08770; --good: #a3be8c; color-scheme: dark; }
:root[data-theme="solarized"] { --bg: #002b36; --panel: #073642; --line: #1d5563; --text: #93a1a1; --muted: #657b83; --accent: #268bd2; --bad: #cb4b16; --good: #859900; --on-accent: #fdf6e3; color-scheme: dark; }
:root[data-theme="phosphor"] { --bg: #021002; --panel: #041a04; --line: #0f4a0f; --text: #46ff6e; --muted: #2da64a; --accent: #46ff6e; --bad: #ffb000; --good: #46ff6e; --on-accent: #021002; color-scheme: dark; }
:root[data-3d] { --bg: #20242b; --panel: #2c323b; --line: #444c58; --text: #e8ecf1; --muted: #9aa4b2; --accent: #4a9eff; --bad: #f0883e; --good: #4cc268; --on-accent: #04121f; color-scheme: dark;
  --btn-face: linear-gradient(#4a525e, #2b3038); --btn-pressed-face: linear-gradient(#6db3ff, #2f78c4); }
/* the dead area behind the controls: Studio is plain, Studio grain has a fine noise, Studio brushed has fine horizontal brushing (both very faint) */
:root[data-theme="studiograin"] :is(header, #freqbar, #receiver, footer) { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.09 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"); }
:root[data-theme="studiobrushed"] :is(header, #freqbar, #receiver, footer) { background-image: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.035) 0, rgba(255, 255, 255, 0.035) 1px, rgba(0, 0, 0, 0.05) 1px, rgba(0, 0, 0, 0.05) 2px, transparent 2px, transparent 3px); }

/* Mute and Audio only are black buttons on the original page: in a theme they are drawn like the other buttons (their red states stay) */
:root[data-theme] #listen[aria-pressed="true"], :root[data-theme] #listenC[aria-pressed="true"], :root[data-theme] #audioOnlyBtn:not([aria-pressed="true"]) { background: var(--btn-face); border-color: var(--line); color: var(--text); font-weight: 400; }

/* 3D themes: bevelled buttons, sliders that look like fader tracks and knobs, sunken fields and panels */
:root[data-3d] button { background: var(--btn-face); border: 1px solid rgba(0, 0, 0, 0.55); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 2px 3px rgba(0, 0, 0, 0.45); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.6); }
:root[data-3d] button:hover { border-color: var(--accent); }
/* active: the accent blue, pressed in (the same as Mem when it is on) */
:root[data-3d] :is(.btns button, .overlay-right button, .tabbtn, .profilebtn, #memToggle, .vfobtn, #fPlain, .role.followbtn, #controlsToggle, #dvRep, #ovGear, .cactions button.on, #layouts button.on)[aria-pressed="true"],
:root[data-3d] .profilebtn[aria-expanded="true"],
:root[data-3d] button:active { background: var(--btn-pressed-face); color: var(--on-accent); border-color: rgba(0, 0, 0, 0.6); text-shadow: none; box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.5); }
:root[data-3d] #lockButton[aria-pressed="true"], :root[data-3d] #listen[aria-pressed="false"], :root[data-3d] #listenC[aria-pressed="false"], :root[data-3d] #audioOnlyBtn[aria-pressed="true"] { background: linear-gradient(#ef5a5a, #b02a2a); border-color: rgba(0, 0, 0, 0.6); color: #fff; box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.45); }
/* the Control / Monitor label keeps its meaning: green for Control, blue for Monitor, bevelled like the buttons */
:root[data-3d] .role:not(.followbtn):not(.profilebtn) { background: linear-gradient(#6db3ff, #2f78c4); color: #04121f; border-color: rgba(0, 0, 0, 0.6); text-shadow: none; font-weight: 600; }
:root[data-3d] .role.control:not(.followbtn) { background: linear-gradient(#6fd98a, #2c9a4d); }
/* Follow Control: white text while it can be used, blue and dark text once it is selected (greyed out when it cannot be used) */
.role.followbtn:not(:disabled) { color: #fff; }
.role.followbtn[aria-pressed="true"] { color: #000; }
:root[data-3d] input[type="range"]::-webkit-slider-runnable-track { height: 8px; border-radius: 4px; background: linear-gradient(#14171b, #3a414b); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.8), 0 1px 0 rgba(255, 255, 255, 0.14); }
:root[data-3d] input[type="range"]::-moz-range-track { height: 8px; border-radius: 4px; background: linear-gradient(#14171b, #3a414b); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.8); }
:root[data-3d] input[type="range"]::-webkit-slider-thumb { width: 20px; height: 20px; margin-top: -6px; background: radial-gradient(circle at 35% 30%, #f7fafc, #8d98a6 55%, #4a525e); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.7), inset 0 -2px 3px rgba(0, 0, 0, 0.35); }
:root[data-3d] input[type="range"]::-moz-range-thumb { width: 20px; height: 20px; background: radial-gradient(circle at 35% 30%, #f7fafc, #8d98a6 55%, #4a525e); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.7); }
:root[data-3d] select, :root[data-3d] input[type="text"] { background: linear-gradient(#1a1d22, #262b32); box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.6); }
/* the frequency readout and the whole spectrum / waterfall panel are sunk into the page */
:root[data-3d] .fdisplay { border: 2px solid #0a0c0f; border-radius: 10px; background: linear-gradient(#000, #0c1410); box-shadow: inset 0 4px 10px rgba(0, 0, 0, 0.95), inset 0 -1px 0 rgba(255, 255, 255, 0.08), 0 1px 0 rgba(255, 255, 255, 0.22); }
:root[data-3d] main { position: relative; margin: 4px 10px 10px; border-radius: 10px; overflow: clip; border: 2px solid #0a0c0f; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22); }
:root[data-3d] main::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: 8px; z-index: 6; box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.85), inset 0 0 0 1px rgba(255, 255, 255, 0.06); }

/* open drop-down lists: the theme's colours, the selected entry in the accent */
select, select option { background-color: var(--bg); color: var(--text); }
select option:checked, select option:hover { background-color: var(--accent); color: var(--on-accent); }

/* the close "x" of every panel turns accent blue under the pointer */
.panel-x:hover, .chooser .panel-x:hover, .peoplehead .panel-x:hover, .profrow button.x:hover, #cwClose:hover, #assetsClose:hover { color: var(--accent) !important; }

.themepanel { min-width: 190px; display: flex; flex-direction: column; gap: 4px; }
.themepanel button { text-align: left; }
.themepanel button[aria-selected="true"] { border-color: var(--accent); color: var(--accent); }
.cwline { display: flex; align-items: baseline; gap: 12px; margin: 4px 0 2px; }
.cwline .cwout { font-family: ui-monospace, Consolas, monospace; font-size: 18px; color: var(--text); }
.cwpanel input[type="range"] { width: 100%; margin: 4px 0 8px; }
/* the mode buttons are one width, so CWR does not push the row out of place; CWR has a smaller face */
#modes button[data-mode] { width: 52px; min-width: 0; padding-left: 0; padding-right: 0; text-align: center; }
#modes button[data-mode].cwr { font-size: 12.5px; }

/* the Spectrum chooser and the Scaling / VFOs box match: the same translucent dark face and the accent border; their close buttons are the same size and
   sit in the same place, with the line under the title a little lower */
.chooser, #displayControls { background: rgba(14, 17, 22, 0.72); border: 1px solid var(--accent); }
#displayControls { padding-right: 12px; }
.chead { padding-bottom: 7px; margin-bottom: 9px; }
.chead .panel-x, .chooser .chead .panel-x, .overlay .chead .panel-x { position: static; display: block; margin: -2px -4px -2px 0; padding: 2px 10px; font-size: 14px; line-height: 1.2; }
.chooser .panel-x { margin: -2px -4px 2px auto; }
.mgrip.both::after { background: #ff8c00; } /* AM, SAM, FM, CW: both passband edges move together, so both are bright */
.bwtip-af { font-size: 0.85em; opacity: 0.9; margin-bottom: 1px; }
.bwtip-af[hidden] { display: none; }

/* the frequency display's colour (Themes list, "Frequency: ..."), in any theme; "backlit" adds a soft glow behind the digits inside the box */
:root[data-freq="blue"] .fdisplay, :root[data-freq="blueglow"] .fdisplay { color: #6cb8ff; }
:root[data-freq="blue"] .fdisplay .sep::after, :root[data-freq="blueglow"] .fdisplay .sep::after { background: #6cb8ff; }
:root[data-freq="greenglow"] .fdisplay { background: radial-gradient(ellipse at 50% 50%, rgba(70, 200, 110, 0.38) 0%, rgba(30, 110, 60, 0.20) 45%, #000 90%); text-shadow: 0 0 10px rgba(126, 231, 135, 0.55); }
:root[data-freq="blueglow"] .fdisplay { background: radial-gradient(ellipse at 50% 50%, rgba(150, 205, 255, 0.42) 0%, rgba(70, 130, 200, 0.22) 45%, #000 90%); text-shadow: 0 0 10px rgba(130, 200, 255, 0.6); }
.themepanel hr { width: 100%; border: none; border-top: 1px solid var(--line); margin: 4px 0; }

/* S-meter: the black cue lines are 2 px; the lines halfway between them hang from the top of the bar and are shorter */
#smeterCues span { width: 2px; margin-left: -1px; }
#smeterCues span.half { bottom: 50%; }

/* the Spectrum options list scrolls when the window is too short for all of it (its height is set by the page when it opens) */
.chooser { overflow-y: auto; }

/* the Band row: the category drop-down, then ten ham buttons or eight buttons of the person's own stretched to the same width */
.bandrow { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; }
.bandrow select { font-size: 15px; padding: 4px 6px; min-width: 64px; }
.bandbtns { display: flex; gap: 6px; }
.bandbtns.custom button { flex: 1 1 0; min-width: 0; padding-left: 2px; padding-right: 2px; white-space: nowrap; overflow: hidden; text-align: center; }
.bandbtns button.tiny1 { font-size: 13px; }
.bandbtns button.tiny2 { font-size: 12px; }
.bandbtns button.empty { opacity: 0.6; }
.bandtip { position: fixed; z-index: 70; transform: translateX(-50%); padding: 4px 9px; background: #0e1116; border: 1px solid var(--accent); border-radius: 6px; color: #e8ecf1; font-size: 13px; white-space: nowrap; pointer-events: none; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5); }
.bandtip[hidden] { display: none; }
.bandname { position: fixed; z-index: 70; width: 400px; max-width: calc(100vw - 16px); padding: 12px 14px; background: var(--panel); border: 1px solid var(--accent); border-radius: 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5); }
.bandname[hidden] { display: none; }
.bandname .bnrow { display: flex; gap: 22px; align-items: flex-end; }
.bandname .bnlab { color: var(--muted); font-size: 12px; margin-bottom: 4px; }
.bandname .bnname { width: 104px; font-size: 14px; }
.bandname .bnsee { display: flex; align-items: center; gap: 10px; padding-bottom: 2px; }
.bandname .bnsee .bnlab { margin: 0; }
.bandname .bnpreview { flex: none; padding-left: 2px; padding-right: 2px; white-space: nowrap; overflow: hidden; text-align: center; cursor: default; }
.bandname .bnpreview.tiny1 { font-size: 13px; }
.bandname .bnpreview.tiny2 { font-size: 12px; }
.bandname .bnalias { display: flex; gap: 6px; align-items: center; }
.bandname .bnaliasin { flex: 1; min-width: 0; font-size: 14px; }
.bandname .bnclear { flex: none; padding: 3px 10px; }
.bandname .bnbtns { display: flex; justify-content: flex-end; margin-top: 12px; }
