Ctrl K
ComunidadGuías…

public/css/style.css

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/* style.css — Ham Radio Control UI v3.0 (kafelkowy layout + wysuwany panel RF) */

@import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Orbitron:wght@400;700;900&family=Inter:wght@300;400;500;600&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ── Paleta "SDR Studio Pro" (przejete z forka 2026-10-16, na zadanie
     uzytkownika "chce uzyskac tamten wyglad z nasza uzytecznoscia") —
     gleboki granat/slate, elektryczny cyjan/blekit jako glowny akcent
     (VFO, aktywne stany), bursztyn dla pasm/ostrzezen, rose-red dla
     TX/PTT. Zastepuje poprzednia "natural sage" (oliwkowo-zielona). Nazwy
     zmiennych BEZ ZMIAN — tylko wartosci — zeby wszystkie regulki
     korzystajace z var(--green) itp. automatycznie dziedziczyly nowa
     paleta. ── */
  --bg:      #070b14;
  --panel:   #0d1424;
  --panel2:  #131c31;
  --panel3:  #1c2944;
  --border:  rgba(var(--green-rgb),0.12);
  --border2: rgba(var(--green-rgb),0.28);
  --green:   #38bdf8;
  --green2:  #0284c7;
  --amber:   #fbbf24;
  --red:     #f43f5e;
  --dim:     rgba(148,163,184,0.65);
  --text:    #f1f5f9;
  /* Czarny tekst/obwodka dla wypelnionych (solid) elementow — przyciski
     aktywne, kciuki sliderow, znaczniki — zapewnia kontrast na jasnym
     tle akcentu (--green/--amber). */
  --on-accent: #070b14;
  /* Rozpakowane R,G,B (bez "rgba()") dla --green/--green2/--amber/--red -
     pozwala inline-stylom i regulkom nizej budowac rgba(var(--green-rgb),
     ALPHA) zamiast wpisywac na sztywno wartosci liczbowe. Dodane
     2026-10-15: masowe podmienianie literalow na te zmienne to byl
     wlasciwy fix na "kolory... malo widoczne" w jasnym motywie — bez
     tego dziesiatki tel/obwodek odznak w ogole nie reagowaly na motyw. */
  --green-rgb:  56,189,248;
  --green2-rgb: 2,132,199;
  --amber-rgb:  251,191,36;
  --red-rgb:    244,63,94;
  /* Rowek miernikow (S-metr/TX-metr) — celowo ciemniejszy niz --panel w
     OBU motywach (wyglada jak wnetrze fizycznego wskaznika), nie po
     prostu var(--panel3). */
  --meter-track: #020617;
  /* Pola tekstowe/liczbowe (RIT Hz, edycja makr CW, numery portow COM itp.)
     uzywaly "var(--input-bg,#0a0a0a)" wszedzie - --input-bg nigdy nie byl
     jawnie zdefiniowany, wiec kazde z tych pol ZAWSZE dostawalo ten sam
     twardy fallback #0a0a0a bez wzgledu na motyw (live report 2026-10-16:
     "caly blok frq jest na ciemno" - pole RIT Hz tuz przy VFO to jeden z
     tych inputow). */
  --input-bg: #0a101d;
  /* --fg: uzywany w kilku inline-stylach (COM Bridge, PROFIL audio TEST,
     itp.) - domyslnie = --text, chyba ze konkretny motyw (np.
     amber-classic nizej) jawnie go nadpisuje. Bez tej linii --fg byl
     NIGDZIE niezdefiniowany poza amber-classic, wiec w kazdym innym
     motywie/trybie po prostu dziedziczyl --text przez CSS fallback -
     dzialalo przypadkiem, ale jawna definicja jest jasniejsza i bezpieczniejsza. */
  --fg: var(--text);
  --mono:    'JetBrains Mono', 'Share Tech Mono', monospace;
  --display: 'JetBrains Mono', 'Orbitron', monospace;
  --ui:      'Plus Jakarta Sans', 'Inter', sans-serif;
}

html {
  /* body.width jest ustawiane przez JS (updateScale) na scale*REF_W.
     Wysokosc NIE jest sztywno ograniczana — strony dluzsze niz 1080px
     (np. USTAWIENIA z wieloma sekcjami, CZAT z dluga historia) moga
     przewijac sie wertykalnie (scroll na html/body), przy zachowanym
     skalowaniu X/Y. Tlo (--bg) wypelnia pillarbox gdy proporcje viewportu
     odbiegaja od 16:9.
     scrollbar-gutter: stable — rezerwuje miejsce na pionowy scrollbar
     ZAWSZE (nawet gdy strona nie przewija sie), zeby clientWidth (uzywane
     w updateScale) bylo stale i nie zmienialo sie przy przelaczaniu
     zakladek krotszych/dluzszych niz viewport — zapobiega "skakaniu"
     calego layoutu o szerokosc scrollbara. */
  background: #070b14;
  scrollbar-gutter: stable;
}
html[data-mode="light"] { background: #f8fafc; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  /* width ustawiane dynamicznie przez JS (updateAppScale) na scale*REF_W —
     dopasowane do #app-scale po transformacji. Wysokosc auto: pozwala na
     scroll gdy zawartosc strony przekracza REF_H. */
}

/* ── #app-scale: caly UI w referencyjnym rozmiarze 1440px szerokosci ──
   Wszystkie elementy wewnatrz zachowuja absolutnie identyczne proporcje
   i pozycje wzgledem siebie na kazdym ekranie — JS aplikuje
   transform:scale() (patrz <script> na koncu index.html) tak, aby
   szerokosc #app-scale (1440px) zmiescila sie w viewporcie. Wysokosc
   min 1080px, ale moze rosnac (strony z duza iloscia tresci) — w takim
   przypadku strona przewija sie wertykalnie. */
#app-scale {
  width: 1440px;
  min-height: 1080px;
  transform-origin: top left;
  position: relative;
}

/* Nowoczesne, czyste tlo — bez artefaktow CRT (usuniete 2026-10-16 razem
   z przejsciem na paleta "SDR Studio Pro", ktora celowo rezygnuje z
   retro-skanlinii na rzecz czystego, nowoczesnego wygladu). */
body::after {
  display: none;
}

/* ── TOPBAR ── */
/* "Opcja 2" (2026-10-16, user decision): .topbar zyje TERAZ wewnatrz
   #app-scale (skaluje sie razem z reszta UI) i ma STALA wysokosc 52px,
   bez position:sticky (i tak nie dzialal poprawnie na potomku
   transform:scale — patrz historia tego pliku w git log). Dzieki stalej
   wysokosci (gridH w index.html::updateScale() odejmuje dokladnie 52px)
   caly widok RADIO/FT8 miesci sie w jednym ekranie bez przewijania
   strony. Szerokosc 1440px (= REF_W) zamiast 100% — topbar jest teraz
   childem #app-scale, ktory sam ma width:1440px, wiec musi dopasowac sie
   do tej samej referencyjnej szerokosci zamiast do (nieskalowanego)
   viewportu. */
.topbar {
  background: var(--panel);
  border-bottom: 1px solid var(--border2);
  padding: 0 20px;
  height: 52px;
  box-sizing: border-box;
  width: 1440px;
  display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap; gap: 12px;
}

/* Presence bar usunieta — funkcje przeniesione do panelu OPERATORZY w tile-cw */

/* white-space:nowrap + flex-shrink:0 — bez tego logo lamalo sie na 3 linie
   i bylo ucinane zamiast zostac w calosci na jednej linii. */
.logo { font-family: var(--ui); font-size: 12px; font-weight: 800; letter-spacing: 1px; color: var(--text); white-space: nowrap; flex-shrink: 0; }
.logo-accent { color: var(--green); text-shadow: 0 0 12px rgba(var(--green-rgb),0.4); }
.nav-tabs { display: flex; align-items: center; gap: 2px; flex-wrap: nowrap; flex-shrink: 1; min-width: 0; overflow: hidden; }
.tab-btn {
  background: transparent; border: 1px solid transparent; padding: 4px 6px; border-radius: 5px;
  color: var(--dim); font-family: var(--ui); font-size: 10px; font-weight: 600; cursor: pointer;
  letter-spacing: 0.2px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); flex-shrink: 0;
  white-space: nowrap;
}
.tab-btn:hover  { color: var(--text); background: var(--panel2); }
.tab-btn.active {
  color: var(--green); background: rgba(var(--green-rgb),0.14); border: 1px solid rgba(var(--green-rgb),0.35);
  box-shadow: 0 0 16px -2px rgba(var(--green-rgb),0.25); font-weight: 700;
}
/* Status-row + wylogowanie sa teraz grupowane w .topbar-right, zeby latwo
   trzymac sie po prawej stronie stalej 52px-wysokiej belki, bez zawijania
   (wrap nie jest juz potrzebny — belka ma stala wysokosc, wiec druga linia
   po prostu zostalaby obcieta zamiast sie pokazac). */
.topbar-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.status-row { display: flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end; gap: 10px; flex-shrink: 0; }
.indicator  { display: flex; align-items: center; gap: 5px; }
.dot        { width:8px; height:8px; border-radius:50%; background:var(--dim); }
.dot.green  { background:var(--green); box-shadow:0 0 8px rgba(var(--green-rgb),0.7); animation:blink 2s ease-in-out infinite; }
.dot.red    { background:var(--red);   box-shadow:0 0 8px rgba(var(--red-rgb),0.7); }
.dot.amber  { background:var(--amber); box-shadow:0 0 8px rgba(var(--amber-rgb),0.7); animation:blink 0.5s ease-in-out infinite; }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0.35} }
.logout-btn {
  background: none; border: 1px solid var(--border); border-radius: 4px;
  color: var(--dim); font-family: var(--mono); font-size: 11px; padding: 5px 10px;
  cursor: pointer; transition: all 0.2s; flex-shrink: 0;
}
.logout-btn:hover { border-color: var(--red); color: var(--red); }
.lang-switch-btn {
  background: none; border: 1px solid var(--border); border-radius: 4px;
  color: var(--dim); font-family: var(--mono); font-size: 10px; font-weight: 700;
  padding: 5px 8px; cursor: pointer; transition: all 0.2s; letter-spacing: 1px;
  min-width: 28px;
}
.lang-switch-btn:hover { border-color: var(--green2); color: var(--green); }

/* ── RADIO PAGE WRAPPER ── */
#page-radio { padding: 0; position: relative; }

/* Sekcje (TX/RX/FILTR/AUDIO/RADIO) — uzywane w tile-left po przeniesieniu
   z usunietego wysuwanego panelu RF/AF. */
.rf-section { padding: 8px 10px 4px; }
.rf-section-title {
  font-family: var(--mono);
  font-size: 8px;
  color: var(--border2);
  letter-spacing: 2px;
  text-transform: uppercase;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 5px;
}
.rf-divider { height: 1px; background: var(--border); margin: 4px 10px; }

input[type="range"].rf-range {
  -webkit-appearance: none; width: 100%; height: 3px;
  background: var(--panel3); border-radius: 2px; outline: none; cursor: pointer; min-width: 0;
}
input[type="range"].rf-range::-webkit-slider-thumb {
  -webkit-appearance: none; width: 11px; height: 11px; border-radius: 50%;
  background: var(--green); cursor: pointer; box-shadow: 0 0 4px rgba(var(--green-rgb),0.4);
}

/* ── Kompaktowe kafelki sliderow (dynamiczne, RadioFunctions) ── */
/* Pojedyncza kolumna — kazdy slider w swoim wierszu, jeden pod drugim. */
#rig-dynamic-sliders {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.rf-slider-tile {
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
}
.rf-slider-tile-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 4px;
}
.rf-slider-tile-left {
  display: flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 11px; color: var(--dim); letter-spacing: 0.5px;
  overflow: hidden; white-space: nowrap;
}
.rf-slider-tile-left .ti { font-size: 13px; flex-shrink: 0; }
.rf-slider-tile-lbl { overflow: hidden; text-overflow: ellipsis; }
.rf-slider-tile-val {
  font-family: var(--mono); font-size: 12px; color: var(--green);
  flex-shrink: 0; margin-left: 6px;
}

/* Select BW i przyciski audio (przeniesione do tile-left) */
.rf-sub-lbl { font-family: var(--mono); font-size: 10px; color: var(--dim); letter-spacing: 1px; display: block; margin-bottom: 3px; }
.rf-section select {
  width: 100%;
  background: var(--panel2); border: 1px solid var(--border2); border-radius: 3px;
  color: var(--green); font-family: var(--mono); font-size: 11px; padding: 5px 7px;
  outline: none;
}
.audio-toggle-btn {
  width: 100%; margin-top: 4px; padding: 7px;
  background: rgba(var(--green-rgb),0.06); border: 1px solid var(--border); border-radius: 3px;
  color: var(--dim); font-family: var(--mono); font-size: 11px; cursor: pointer; letter-spacing: 1px;
  transition: all 0.15s;
}
.audio-toggle-btn:hover { color: var(--green); border-color: var(--green2); }

#wj-mute-btn.active { color: var(--red); border-color: var(--red) !important; background: rgba(var(--red-rgb),0.1); }
#wj-mute-btn { flex-shrink: 0; } /* see .wj-period-switch's comment - don't get squeezed by the TX-wait status pill */

/* ── Czarne obwodki na przyciskach/sliderach ──
   Paleta sage jest spokojna/naturalna — czarna obwodka 1px na elementach
   interaktywnych (przyciski, select, range input) daje wyrazna definicje
   krawedzi bez dodawania jaskrawego koloru. Kolorowy border (--border2 itp.)
   pozostaje przez box-shadow inset, wiec stan hover/active (zmiana
   border-color na --green/--amber) wciaz jest widoczny jako wewnetrzny
   pasek koloru, a zewnetrzna czarna linia daje kontrast wzgledem tla. */
button, select, input[type="range"].rf-range,
.step-btn, .mode-btn, .band-btn, .go-btn, .ptt-btn,
.btn-vfo-select, .btn-func-toggle, .btn-power-toggle,
.audio-toggle-btn, .tab-btn, .memory-del {
  border-color: #000 !important;
  box-shadow: inset 0 0 0 1px var(--border2);
}
button:hover, .step-btn:hover, .mode-btn:hover, .band-btn:hover,
.go-btn:hover, .ptt-btn:hover, .btn-vfo-select:hover, .btn-func-toggle:hover,
.btn-power-toggle:hover, .audio-toggle-btn:hover, .tab-btn:hover {
  box-shadow: inset 0 0 0 1px var(--green);
}
.mode-btn.active, .band-btn.active, .step-btn.active, .tab-btn.active,
.btn-vfo-select.active, .btn-func-toggle.active, .btn-power-toggle.active {
  box-shadow: inset 0 0 0 1px var(--green);
}
input[type="range"].rf-range::-webkit-slider-thumb {
  border: 1px solid #000;
}

/* ── KAFELKOWY GRID ── */
/* grid-template-rows ma teraz 3 wiersze (nie 4) — rotator i CW keyer nie sa
   juz osobnymi komorkami siatki, tylko jednym polaczonym kafelkiem
   .tile-right (patrz index.html) zajmujacym cala wysokosc kolumny 4.
   Wysokosc liczona z --radio-grid-h (ustawianej w JS, updateScale() w
   index.html) zamiast sztywnego "calc(1080px - 52px)", zeby dokladnie
   wypelnic dostepna wysokosc okna bez przewijania strony ("opcja 2",
   2026-10-16). */
.tile-grid {
  display: grid;
  width: 100%;
  grid-template-columns: 250px 1fr 1fr 250px;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: 1px;
  background: var(--border);
  height: var(--radio-grid-h, calc(1080px - 52px));
  max-height: var(--radio-grid-h, calc(1080px - 52px));
  overflow: hidden;
}

/* Pozycje kafelków */
.tile-left       { grid-column: 1; grid-row: 1 / 4; }
.tile-vfo        { grid-column: 2 / 4; grid-row: 1; }
.tile-rigfeatures{ grid-column: 2 / 4; grid-row: 2; }
.tile-wf         { grid-column: 2 / 4; grid-row: 3; min-height: 0; }
.tile-right      { grid-column: 4; grid-row: 1 / 4; }
.tile-rotator    { font-size: 125%; background: var(--bg); }
.tile-cw         { font-size: 125%; }

/* Wspólne style kafelka */
.tile {
  background: var(--bg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── BOX / HEADER (zachowane ze starego CSS) ── */
.box { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.box-header {
  /* FIX: byl hardcoded rgba(19,28,49,0.7) - to akurat ciemny granat
     (#131c31 = dzisiejsze --panel2 w trybie ciemnym), wiec w nocy wygladalo
     ok, ale w jasnym motywie zostawalo tym samym ciemnym paskiem na bialym
     tle .box. Zgloszone na zywo: "w trybie nocnym jest zgodne z kolorami
     tryb dzienny juz nie" (okno LOG QSO / przyciski ADIF). */
  padding: 8px 14px; background: var(--panel2); border-bottom: 1px solid var(--border);
  font-family: var(--ui); font-size: 12px; font-weight: 700; letter-spacing: 1.5px; color: var(--dim);
  text-transform: uppercase; display: flex; align-items: center; justify-content: space-between;
}
.box-body { padding: 12px; }

/* Nagłówek kafelka (bez ramki box) */
.tile-header {
  background: var(--panel2);
  padding: 5px 10px;
  font-family: var(--mono);
  font-size: 9px;
  color: var(--dim);
  letter-spacing: 2px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.tile-header-val { color: var(--green); font-size: 10px; }
.tile-divider { height: 1px; background: var(--border); flex-shrink: 0; }

/* ── LEWA KOLUMNA ── */
.tile-left { background: var(--bg); overflow-y: auto; overflow-x: hidden; min-height: 0; height: 100%; font-size: 125%; }

/* ── PRAWA KOLUMNA (rotator + CW keyer + czat w jednym, scrollowanym kafelku) ── */
.tile-right {
  background: var(--panel);
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  height: 100%;
}

/* Siatka Tryb / Pasmo — identyczny rozmiar */
.mode-band-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3px;
  padding: 7px 8px;
}
.mode-btn, .band-btn {
  background: var(--panel2); border: 1px solid var(--border); border-radius: 3px;
  color: var(--dim); font-family: var(--mono); font-size: 11px; padding: 7px 4px;
  cursor: pointer; text-align: center; letter-spacing: 0.5px; transition: all 0.15s;
}
.mode-btn:hover  { border-color: var(--border2); color: var(--text); }
.band-btn:hover  { border-color: var(--border2); color: var(--text); }
.mode-btn.active { background: rgba(var(--green-rgb),0.12); border-color: var(--green); color: var(--green); }
.band-btn.active { background: rgba(var(--amber-rgb),0.10); border-color: var(--amber); color: var(--amber); }

/* Szybki Log QSO */
.qso-form {
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1;
}
.form-label { font-family: var(--mono); font-size: 9px; color: var(--dim); letter-spacing: 1px; margin-bottom: 2px; }
.form-row { display: flex; gap: 5px; }
.form-row input { flex: 1; }
.log-btn {
  width: 100%; margin-top: auto;
  background: rgba(var(--green-rgb),0.12); border: 1px solid var(--green2); border-radius: 4px;
  color: var(--green); font-family: var(--mono); font-size: 10px; letter-spacing: 1px;
  padding: 8px; cursor: pointer; transition: all 0.15s;
}
.log-btn:hover { background: rgba(var(--green-rgb),0.2); }

/* ── VFO ── */
.vfo-display {
  text-align: left;
  padding: 3px 10px 2px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.vfo-label { font-family: var(--mono); font-size: 9px; letter-spacing: 2px; color: var(--dim); margin-bottom: 2px; }
.vfo-badges { display: flex; gap: 4px; margin-bottom: 4px; align-items: center; flex-wrap: wrap; }
.vfo-badge {
  font-family: var(--mono); font-size: 9px; font-weight: 700; padding: 2px 7px;
  border-radius: 4px; border: 1px solid; cursor: default;
}
.freq-big {
  font-family: var(--mono); font-size: 32px; font-weight: 800;
  color: var(--green); letter-spacing: -1px; line-height: 1;
  text-shadow: 0 0 20px rgba(var(--green-rgb),0.5);
  cursor: pointer; user-select: none;
}
.freq-big:hover { text-shadow: 0 0 30px rgba(var(--green-rgb),0.85); }
.freq-unit { font-family: var(--mono); font-size: 10px; font-weight: 700; color: var(--dim); margin-bottom: 2px; }

/* Kroki strojenia */
.tuning-steps { display: flex; gap: 2px; padding: 2px 0; flex-wrap: wrap; }
.step-btn {
  /* FIX: bylo rgba(19,28,49,.7)/rgba(255,255,255,.08) na sztywno (wartosci
     dobre tylko na ciemnym tle - w jasnym motywie dawaly ciemny prostokat
     z prawie niewidoczna ramka) - patrz ten sam fix w .box-header. */
  background: var(--panel2); border: 1px solid var(--border2); border-radius: 3px;
  color: var(--dim); font-family: var(--mono); font-size: 9.5px; font-weight: 600; padding: 1px 6px;
  cursor: pointer; transition: all 0.15s;
}
.step-btn:hover  { background: var(--panel3); border-color: var(--green); color: var(--green); }
.step-btn:active { transform: scale(0.95); }
.step-btn.active { border-color: var(--green); color: var(--green); background: rgba(var(--green-rgb),0.16); font-weight: 700; }

.go-btn {
  background: rgba(var(--green-rgb),0.12); border: 1px solid var(--green); border-radius: 4px;
  color: var(--green); font-family: var(--mono); font-size: 12px; font-weight: 700; padding: 3px 8px;
  cursor: pointer; flex-shrink: 0; transition: all 0.15s;
}
.go-btn:hover { background: rgba(var(--green-rgb),0.25); }

/* ── S-METER ── */
.smeter-wrap { padding: 3px 10px 3px; }
.smeter-scale {
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 8.5px; font-weight: 600; color: var(--dim); margin-bottom: 1px; padding: 0 2px;
}
.smeter-bar-wrap {
  position: relative; height: 11px; background: var(--meter-track);
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: 3px; overflow: hidden;
}
.smeter-fill {
  height: 100%; width: 100%; border-radius: 2px;
  background: linear-gradient(90deg,var(--green2) 0%,var(--green2) 55%,var(--amber) 55%,var(--amber) 75%,var(--red) 75%,var(--red) 100%);
  clip-path: inset(0 100% 0 0); transition: clip-path 0.1s ease;
}
.smeter-value {
  font-family: var(--mono); font-size: 11px; font-weight: 800;
  color: var(--green); margin-top: 1px;
  text-shadow: 0 0 10px rgba(var(--green-rgb),0.4);
}

/* ── TX Meter (ALC/PWR/SWR/VOLT) — bargraf kompaktowy pod S-metrem ──
   Jeden wiersz: nazwa funkcji | pasek | wartosc. Wybor funkcji jest TYLKO
   w lewej kolumnie (sekcja TRX FUNKCJE pod PASMO) — patrz UI.setTxMeter(). */
/* ── TX Meter (ALC/PWR/SWR/VOLT) — bargraf kompaktowy pod S-metrem ──
   Jeden wiersz: nazwa funkcji | pasek+podzialka | wartosc. Wybor funkcji
   jest TYLKO w lewej kolumnie (sekcja TRX FUNKCJE pod PASMO) — patrz
   UI.setTxMeter(). Podzialka pod paskiem dopasowana do realnego zakresu
   odczytu z radia, inna dla kazdej funkcji (patrz UI._renderTxMeter()). */
.txmeter-wrap {
  display: flex; align-items: center; gap: 6px;
  margin-top: 2px; padding-top: 2px;
  border-top: 1px solid var(--border);
}
.txmeter-label-name {
  font-family: var(--mono); font-size: 9px; font-weight: 700;
  color: var(--dim); letter-spacing: 1px; flex-shrink: 0;
  min-width: 24px;
}
.txmeter-bar-col { flex: 0 0 50%; display: flex; flex-direction: column; gap: 1px; }
.txmeter-bar-wrap {
  position: relative; height: 8px; background: var(--meter-track);
  border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 2px; overflow: hidden;
}
.txmeter-fill {
  height: 100%; width: 0%;
  border-radius: 2px;
  /* Backend odswieza te mierniki co ~300ms (civ.py, petla pollera) — czas
     przejscia dobrany blisko tego odstepu (nie krotszy), zeby pasek byl w
     ciaglym ruchu miedzy odczytami zamiast skoku + zamrożenia (co dawalo
     wrazenie "szarpanego" bargrafu przy krotszym 0.12s). */
  transition: width 0.28s linear;
  background: linear-gradient(90deg, var(--green2) 0%, var(--amber) 60%, var(--red) 85%);
}
/* Kolor bargrafów wg metra */
.txmeter-fill.alc  { background: linear-gradient(90deg, #4a7a9a 0%, var(--amber) 70%, var(--red) 90%); }
.txmeter-fill.pwr  { background: linear-gradient(90deg, var(--green2) 0%, var(--green) 55%, var(--amber) 75%, var(--red) 90%); }
.txmeter-fill.swr  { background: linear-gradient(90deg, var(--green2) 0%, var(--green2) 40%, var(--amber) 60%, var(--red) 80%); }
.txmeter-fill.volt { background: linear-gradient(90deg, var(--red) 0%, var(--amber) 40%, var(--green2) 70%); }
/* Podzialka pod paskiem — pozycjonowanie absolutne (left:%), bo punkty SWR
   (1.0/1.5/2.0/3.0) NIE sa rownomiernie rozstawione w skali procentowej
   (patrz civ.py: pct = min(1.0, swr_raw/120), nieliniowe wzgledem wartosci). */
.txmeter-scale {
  position: relative; height: 9px;
  font-family: var(--mono); font-size: 8px; color: var(--dim);
}
.txmeter-scale span {
  position: absolute; transform: translateX(-50%);
}
.txmeter-scale span:first-child  { transform: translateX(0); }
.txmeter-scale span:last-child   { transform: translateX(-100%); }
.txmeter-value {
  font-family: var(--mono); font-size: 11px; color: var(--amber);
  font-weight: 700; letter-spacing: 0.5px; flex-shrink: 0; min-width: 38px; text-align: right;
}

/* ── PTT ── */
.ptt-btn {
  padding: 3px 48px; border-radius: 5px; border: 1px solid var(--border2);
  background: var(--panel2); color: var(--text); font-family: var(--ui);
  font-size: 12.5px; font-weight: 800; letter-spacing: 2px; cursor: pointer; transition: all 0.2s;
  height: 25px;
}
.ptt-btn:hover  { border-color: var(--green); color: var(--green); }
.ptt-btn.active {
  background: rgba(var(--red-rgb),0.2); border-color: var(--red); color: var(--red);
  box-shadow: 0 0 20px rgba(var(--red-rgb),0.3); animation: ptt-pulse 0.8s ease-in-out infinite;
}
.ptt-btn.crossband-blocked,
.ptt-btn:disabled {
  background: rgba(var(--red-rgb),0.05); border-color: rgba(var(--red-rgb),0.35);
  color: rgba(var(--red-rgb),0.55); cursor: not-allowed;
  box-shadow: none; animation: none;
}
.ptt-btn.crossband-blocked:hover,
.ptt-btn:disabled:hover {
  border-color: rgba(var(--red-rgb),0.35); color: rgba(var(--red-rgb),0.55);
}

/* Radio readonly mode — user nie ma TRX lock, moze tylko ogladac.
 * Wyszarzamy wszystkie interaktywne kontrolki (przyciski, suwaki, pola input)
 * poza panelem OPERATORZY (bo tam jest przycisk PRZEJMIJ TRX). Waterfall,
 * S-meter, VFO display pozostaja pelnokolorowe (readonly nie ukrywa
 * odczytow z radia, tylko blokuje ZMIANY). */
.radio-readonly button:not(.op-btn-take):not(.op-btn-request):not(.op-btn-release):not(.op-btn-force):not(#tab-radio):not(.tab-btn):not(.vfo-badge):not([id*="chat"]):not([id*="op-"]),
.radio-readonly input[type="range"],
.radio-readonly input[type="number"]:not([id*="chat"]),
.radio-readonly select:not([id*="chat"]) {
  opacity: 0.4;
  pointer-events: none;
  filter: grayscale(0.6);
}
.radio-readonly .ptt-btn {
  opacity: 0.35;
  pointer-events: none;
  filter: grayscale(0.8);
  border-color: var(--dim) !important;
  color: var(--dim) !important;
  background: transparent !important;
  box-shadow: none !important;
  animation: none !important;
}
/* Makra CW (F1-F6) sa <div onclick=...>, nie <button> — selektor
 * ".radio-readonly button:..." powyzej ich nie lapie, wiec wygladaly na
 * aktywne mimo ze backend i tak odrzuca wysylke (/api/cw/send) gdy ktos
 * inny trzyma radio. Wykryte w audycie zakladki RADIO 2026-08-15. */
.radio-readonly .cw-macro-card {
  opacity: 0.4;
  pointer-events: none;
  filter: grayscale(0.6);
}
/* Zasada blokady: kto NIE trzyma TRX jest traktowany prawie jak viewer —
 * ALE zawsze ma dostep do wlasnego logu QSO (i do zakladki Ustawienia, ktora
 * jest osobna strona spoza #page-radio i tak nigdy nie byla dotykana przez
 * .radio-readonly). Sam pasek "LOG QSO" jest jedynym elementem logu we-
 * wnatrz zakladki RADIO, wiec wylaczamy go z ogolnej blokady przyciskow
 * powyzej. Pola tekstowe (CALL/RST/GRID) i tak nigdy nie byly blokowane —
 * ogolna reguła gasi tylko input[type=number/range] i select. 2026-08-15. */
.radio-readonly #quick-log-bar button {
  opacity: 1;
  pointer-events: auto;
  filter: none;
}
/* Wyraznie oznaczmy panel OPERATORZY zeby user wiedzial gdzie kliknac PRZEJMIJ */
.radio-readonly #op-list {
  border: 1px solid var(--amber);
  background: rgba(var(--amber-rgb),0.05);
  animation: readonly-highlight 2.5s ease-in-out infinite;
}
@keyframes readonly-highlight {
  0%,100% { box-shadow: 0 0 0 rgba(var(--amber-rgb),0); }
  50%     { box-shadow: 0 0 12px rgba(var(--amber-rgb),0.35); }
}
/* Odblokuj przyciski PRZEJMIJ/POPROŚ/ODDAJ zeby user mogl przejac radio */
.radio-readonly #op-btn-take,
.radio-readonly #op-btn-request,
.radio-readonly #op-btn-release,
.radio-readonly #op-btn-force {
  opacity: 1 !important;
  pointer-events: auto !important;
  filter: none !important;
}

/* ── Waterfall fullscreen ── */
.tile-wf.wf-fullscreen {
  position: fixed !important;
  top: 0 !important; left: 0 !important;
  width: 100vw !important; height: 100vh !important;
  z-index: 9999 !important;
  padding: 20px !important;
  background: #000 !important;
  display: flex !important;
  flex-direction: column !important;
}
.tile-wf.wf-fullscreen canvas#wf-waterfall { max-height: none !important; flex: 1 !important; }
.tile-wf.wf-fullscreen canvas#wf-spectrum { height: 120px !important; }

/* ── Waterfall collapsed (np. rig bez CI-V scope'u - IC-746 itp.) ──
   Ukrywa tylko canvasy - tile-wf zostaje w TYM SAMYM miejscu siatki
   (grid-column/grid-row bez zmian), wiec zadne inne kafelki sie nie
   przesuwaja. Naglowek (span/peak/badge/S-metr/przyciski) zostaje
   widoczny, zeby dalo sie jednym klikiem rozwinac z powrotem. */
.tile-wf.wf-collapsed canvas#wf-spectrum,
.tile-wf.wf-collapsed canvas#wf-waterfall,
.tile-wf.wf-collapsed canvas#wf-axis { display: none; }

/* ── Motywy kolorów (data-theme na <html>) ── */
/* Domyślny: green-amber (IC-7300 feel) — juz w :root */
html[data-theme="blue"] {
  --green:  #6db4e5;
  --green2: rgba(109,180,229,0.4);
  --amber:  #f0b429;
}
html[data-theme="mono"] {
  --green:  #e0e0e0;
  --green2: rgba(224,224,224,0.4);
  --amber:  #c0c0c0;
  --red:    #ff8080;
}
html[data-theme="amber-classic"] {
  --green:  #ffb84d;
  --green2: rgba(255,184,77,0.4);
  --amber:  #ff8c42;
  --fg:     #ffb84d;
  --text:   #ffdba0;
}

/* ── Jasny motyw (dzien/noc, approved 2026-10-15) ─────────────────────────
   Live report: "na tym co jest slabo widac" (niektore teksty/panele slabo
   widoczne) - niektorzy userzy wola jasne tlo. Zachowujemy TA SAMA
   tozsamosc kolorystyczna ("natural sage": szalwiowa zielen / bursztyn /
   czerwien) dla motywu DOMYSLNEGO - zmieniaja sie neutralne kolory tla/
   tekstu (--bg, --panel*, --text, --dim, --border*) ORAZ akcenty (--green/
   --green2/--amber/--red, przeliczone na ciemniejsze/bardziej nasycone
   odcienie tej samej barwy - te same pastelowe wartosci z ciemnego motywu
   mialyby ZA MALY kontrast na jasnym tle, czyli dokladnie ten sam problem
   widocznosci co user zglasza, tylko w nowym miejscu).
   PRZELACZANE przez toggle w theme.js, atrybut data-mode (NIE data-theme!)
   - localStorage 'ham_theme', jak PL/EN w i18n.js - domyslnie ciemny
   (obecny wyglad, bez zmian dla kogos kto nic nie kliknie).
   FIX KRYTYCZNY (2026-10-15, live report "przestaly dzialac kolory
   bursztyn/crt"): ten blok pierwotnie uzywal TEGO SAMEGO atrybutu
   data-theme co blok "Motywy kolorow" nad tym komentarzem (blue/mono/
   amber-classic, wybierane w PROFIL -> UI.setTheme, zapisywane w
   localStorage per-user jako "theme_<uid>") - obie funkcje (jasny/ciemny
   motyw i wybor wariantu koloru) walczyly o jeden atrybut na <html> i sie
   nawzajem nadpisywaly (theme.js'owy MutationObserver non-stop resetowal
   wybrany przez usera wariant z powrotem na light/dark). Rozdzielone na
   dwa niezalezne atrybuty: data-theme = wariant koloru (ui.js), data-mode
   = jasny/ciemny (theme.js) - teraz moga dzialac jednoczesnie.
   Ten blok jest CELOWO PO blokach wariantow kolorow wyzej (ta sama
   specificznosc selektora :root[attr], remis idzie do kolejnosci w
   pliku) - w trybie jasnym kazdy wariant koloru (blue/mono/amber-classic)
   wraca do czytelnej domyslnej palety zamiast zostawiac blade kolory
   dobrane pod ciemne tlo nieczytelne na jasnym - to jedyny rozsadny
   kompromis bez recznego dostrajania osobnej jasnej wersji kazdego z 3
   wariantow.
   UWAGA (znane ograniczenie): sporo odznak/plakietek w index.html ma
   WPISANY NA SZTYWNO kolor tla (np. "background:rgba(var(--amber-rgb),0.2)"
   zamiast var(--amber)) - te tla NIE zmienia sie w jasnym motywie (zostaja
   w odcieniu dobranym pod ciemne tlo), tylko sam tekst (ktory juz uzywa
   var(--amber) itp.) sie przelacza - drobna kosmetyczna niespojnosc,
   zaakceptowana zamiast przepisywania dziesiatek inline-stylow. Wodospad/
   scope/kompas rotora (canvas, nie CSS) CELOWO zostaja ciemne w obu
   motywach - to wykresy RF, nie tekst, i tak jest w kazdym programie SDR. */
:root[data-mode="light"] {
  /* Jasny wariant palety "SDR Studio Pro" (przejety z forka 2026-10-16,
     razem z ciemnym wariantem powyzej). --dim jest tu PELNYM kolorem
     (nie rgba() na przezroczystosci) - fork tak to rozwiazal, i daje to
     wystarczajacy kontrast bez potrzeby osobnego dostrajania alpha jak w
     poprzedniej (sage) palecie. */
  --bg:      #f8fafc;
  --panel:   #ffffff;
  --panel2:  #f1f5f9;
  --panel3:  #e2e8f0;
  --border:  rgba(15,23,42,0.09);
  --border2: rgba(15,23,42,0.20);
  --green:   #0284c7;
  --green2:  #0369a1;
  --amber:   #d97706;
  --red:     #dc2626;
  --dim:     #64748b;
  --text:    #0f172a;
  --on-accent: #ffffff;
  --fg:      var(--text);
  --green-rgb:  2,132,199;
  --green2-rgb: 3,105,161;
  --amber-rgb:  217,119,6;
  --red-rgb:    220,38,38;
  --meter-track: #e2e8f0;
  --input-bg: #ffffff;
}
@media (prefers-color-scheme: light) {
  /* Tylko gdy user NIGDY nie kliknal przelacznika (brak zapisu w
     localStorage) - JS (theme.js) i tak ustawia data-mode explicite na
     starcie, wiec to tylko fallback zanim JS zdazy sie wykonac. */
  :root:not([data-mode]) {
    --bg:      #f8fafc;
    --panel:   #ffffff;
    --panel2:  #f1f5f9;
    --panel3:  #e2e8f0;
    --border:  rgba(15,23,42,0.09);
    --border2: rgba(15,23,42,0.20);
    --green:   #0284c7;
    --green2:  #0369a1;
    --amber:   #d97706;
    --red:     #dc2626;
    --dim:     #64748b;
    --text:    #0f172a;
    --on-accent: #ffffff;
    --fg:      var(--text);
    --green-rgb:  2,132,199;
    --green2-rgb: 3,105,161;
    --amber-rgb:  217,119,6;
    --red-rgb:    220,38,38;
    --meter-track: #e2e8f0;
    --input-bg: #ffffff;
  }
}

@keyframes ptt-pulse { 0%,100%{box-shadow:0 0 20px rgba(var(--red-rgb),0.3)} 50%{box-shadow:0 0 35px rgba(var(--red-rgb),0.6)} }

/* Neon text-shadow glows (big blur radii, designed for a dark background -
   the VFO digits, S-meter reading, logo accent) read as thick/blurry
   rather than crisp on a LIGHT panel instead of adding a "CRT glow" effect
   - live report 2026-10-16: "czcionka nadal malo czytelna kolorystycznie"
   (after the --dim contrast fix above, this was the other half of it).
   Turned off in light mode; dark mode keeps every glow exactly as-is. */
:root[data-mode="light"] .freq-big,
:root[data-mode="light"] .freq-big:hover,
:root[data-mode="light"] .smeter-value,
:root[data-mode="light"] .logo-accent,
:root[data-mode="light"] .vfo-digit.active:hover,
:root[data-mode="light"] .vfo-digit.selected,
:root[data-mode="light"] .vfo-arrow:hover {
  text-shadow: none;
}

/* ── PANEL FUNKCJI RADIA (VFO A/B, func toggle) ── */
.tile-rigfeatures { padding: 0; }
/* Jeden zwarty wiersz przyciskow (VFO A/B, Zasilanie, funkcje) miedzy PTT
   i waterfallem. Nie zawija sie — w razie nadmiaru elementow przewija
   horyzontalnie (scrollbar maskowany, widoczny tylko na hover/drag). */
.rf-buttons-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 3px;
  padding: 2px 8px;
}
/* Wszystkie grupy/przyciski trzymaja sie jednego wiersza (scroll-x w razie
   przepelnienia) — nie kurcza sie i nie zawijaja. */
.rf-buttons-row .rig-action-group,
.rf-buttons-row .btn-vfo-select,
.rf-buttons-row .btn-power-toggle,
.rf-buttons-row .btn-func-toggle { flex-shrink: 0; white-space: nowrap; }

/* Zunifikowany przycisk dla rf-buttons-row — jeden rozmiar dla wszystkich */
.rf-btn {
  /* FIX: bylo rgba(19,28,49,.75)/rgba(255,255,255,.08) na sztywno - patrz
     ten sam fix w .box-header (dobre tylko na ciemnym tle). */
  padding: 3px 9px; border-radius: 4px; border: 1px solid var(--border2);
  background: var(--panel2); color: var(--dim); font-family: var(--mono);
  font-size: 10px; font-weight: 600; letter-spacing: 0.5px; cursor: pointer; transition: all 0.15s;
  white-space: nowrap; flex-shrink: 0;
}
.rf-btn:hover { border-color: var(--green); color: var(--green); background: var(--panel3); }
.rf-btn.active {
  background: rgba(var(--green-rgb), 0.18); border-color: var(--green); color: var(--green);
  box-shadow: 0 0 10px rgba(var(--green-rgb), 0.25); font-weight: 700;
}
.rf-btn-power { color: var(--green); }
.rf-btn-power:hover { border-color: var(--red); color: var(--red); }
.rf-btn-power.active {
  background: rgba(var(--red-rgb),0.18); border-color: var(--red); color: var(--red);
  box-shadow: 0 0 10px rgba(var(--red-rgb), 0.3);
}
/* Zachowane dla kompatybilnosci wstecznej */
.btn-vfo-select, .btn-func-toggle, .btn-power-toggle { padding: 6px 15px; border-radius: 6px; border: 1px solid var(--border2); background: var(--panel2); color: var(--dim); font-family: var(--mono); font-size: 12px; font-weight: 600; letter-spacing: 0.5px; cursor: pointer; transition: all 0.15s; }
.btn-vfo-select:hover, .btn-func-toggle:hover { border-color: var(--green); color: var(--green); background: var(--panel3); }
.btn-vfo-select.active, .btn-func-toggle.active { background: rgba(var(--green-rgb),0.18); border-color: var(--green); color: var(--green); box-shadow: 0 0 10px rgba(var(--green-rgb), 0.25); font-weight: 700; }
.btn-power-toggle { color: var(--green); }
.btn-power-toggle:hover { border-color: var(--red); color: var(--red); }
.btn-power-toggle.active { background: rgba(var(--red-rgb),0.18); border-color: var(--red); color: var(--red); }

/* ── WATERFALL ── */
.wf-header {
  background: var(--panel2); padding: 3px 10px;
  display: flex; justify-content: space-between; align-items: center;
  border-bottom: 1px solid var(--border); flex-shrink: 0;
}
#wf-spectrum  { width: 100%; flex: 0 0 clamp(60px, 30%, 110px); min-height: 50px; max-height: 110px; display: block; background: #060806; }
#wf-axis      { width: 100%; height: 20px; display: block; background: #0a0c0a; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); flex-shrink: 0; }
#wf-waterfall { width: 100%; display: block; background: #060806; flex: 1 1 0; min-height: 60px; }

/* ── PASEK SOFTKEYS (ekranowe przyciski radia, jak w IC-7300) ── */
.wf-softkeys {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 3px;
  padding: 3px 5px;
  background: var(--panel2);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.wf-softkey-btn {
  background: var(--panel3);
  border: 1px solid var(--border2);
  border-radius: 4px;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  padding: 4px 2px;
  text-align: center;
  cursor: pointer;
  transition: all 0.15s;
  user-select: none;
  white-space: nowrap;
}
.wf-softkey-btn:hover { border-color: var(--green); color: var(--text); }
.wf-softkey-btn.active {
  background: rgba(var(--green-rgb),0.18);
  border-color: var(--green);
  color: var(--green);
  box-shadow: inset 0 0 6px rgba(var(--green-rgb),0.25);
}
/* SPAN jako rozwijane menu zamiast przycisku-cyklu - zgloszone na zywo:
   "span na waterfallu nie przelacza sie normalnie" (klikanie przez 7
   wartosci kazdorazowo bylo niewygodne - teraz wybor od razu). */
.wf-softkey-select {
  background: var(--panel3);
  border: 1px solid var(--border2);
  border-radius: 4px;
  color: var(--green);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  padding: 4px 2px;
  text-align: center;
  text-align-last: center;
  cursor: pointer;
  transition: all 0.15s;
}
.wf-softkey-select:hover { border-color: var(--green); }

/* ── ROTATOR ── */
.rotator-inner { padding: 4px 10px 6px; }
#rot-compass { width: 205px !important; height: 205px !important; }
.rot-az-display { font-family: var(--display); font-size: 45px; font-weight: 900; color: var(--green); text-align: center; line-height: 1; }
.rot-unit-label { font-family: var(--mono); font-size: 9px; color: var(--dim); text-align: center; margin-bottom: 6px; }
.rot-target-inp {
  width: 100%; margin-bottom: 5px;
  background: var(--panel2); border: 1px solid var(--border2); border-radius: 3px;
  color: var(--text); font-family: var(--mono); font-size: 11px; padding: 5px 8px; outline: none;
}
.rot-btns { display: flex; gap: 4px; }
.rot-go-btn {
  flex: 1; background: rgba(var(--green-rgb),0.1); border: 1px solid var(--green2);
  border-radius: 3px; color: var(--green); font-family: var(--mono); font-size: 12px;
  padding: 9px; cursor: pointer; letter-spacing: 1px; transition: all 0.15s;
}
.rot-stop-btn {
  flex: 1; background: rgba(var(--red-rgb),0.08); border: 1px solid rgba(var(--red-rgb),0.3);
  border-radius: 3px; color: var(--red); font-family: var(--mono); font-size: 10px;
  padding: 7px; cursor: pointer; letter-spacing: 1px; transition: all 0.15s;
}

/* ── CW KEYER ── */
.cw-macros-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 3px;
  padding: 6px 8px;
}
.cw-macro-card {
  background: var(--panel2); border: 1px solid var(--border); border-radius: 3px;
  padding: 5px 7px; cursor: pointer; transition: all 0.12s;
  min-height: 38px; max-height: 52px; overflow: hidden;
  display: flex; flex-direction: column; gap: 2px; position: relative;
}
.cw-macro-card:hover { border-color: var(--green2); background: rgba(var(--green-rgb),0.06); }
.cw-macro-card.empty { border-style: dashed; opacity: 0.5; }
.cw-macro-card.empty:hover { opacity: 0.8; }
.cw-macro-header {
  display: flex; align-items: center; gap: 4px;
}
.cw-macro-label {
  font-family: var(--mono); font-size: 8px; color: var(--amber);
  letter-spacing: 0.5px; display: block; text-transform: uppercase;
}
.cw-macro-text {
  font-family: var(--mono); font-size: 8px; color: var(--dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  flex: 1; min-width: 0; display: block;
}
.cw-macro-num { font-family: var(--mono); font-size: 8px; color: var(--dim); }
.cw-macro-edit-btn {
  display: none; margin-left: auto;
  background: transparent; border: 1px solid var(--border2); border-radius: 2px;
  color: var(--dim); font-size: 9px; line-height: 1; padding: 0px 3px; cursor: pointer;
}
.cw-macro-edit-btn:hover { color: var(--amber); border-color: var(--amber); }
.cw-macro-card:hover .cw-macro-edit-btn { display: inline-block; }

/* ── TX VU METER + AUDIO SLIDERS ── */
#tx-vu-bar {
  flex: 1; height: 6px; background: var(--panel3);
  border-radius: 3px; overflow: hidden; position: relative;
}
#tx-vu-fill {
  height: 100%; width: 0%; background: var(--green);
  border-radius: 3px; transition: width 0.05s;
}
#tx-gain-slider, #rx-vol-slider {
  width: 100%; cursor: pointer; height: 3px;
  -webkit-appearance: none; appearance: none;
  background: var(--panel3); border-radius: 2px; outline: none;
}
#tx-gain-slider::-webkit-slider-thumb,
#rx-vol-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--green); cursor: pointer;
  border: 1px solid #000;
}
#tx-gain-slider::-moz-range-thumb,
#rx-vol-slider::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--green); cursor: pointer;
  border: 1px solid #000;
}

/* ── FOX / HOUND MODE ── */
.wj-hound-step {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 6px; border-radius: 2px;
  font-family: var(--mono); font-size: 9px;
  color: #555; border: 1px solid transparent;
  transition: all 0.2s;
}
.wj-hound-step.active {
  color: #f90; border-color: rgba(255,140,0,0.3);
  background: rgba(255,140,0,0.08);
}
.wj-hound-step.done {
  color: #4c8; border-color: rgba(76,200,140,0.2);
  background: rgba(76,200,140,0.06);
}
.wj-hound-step.failed {
  color: #f66; border-color: rgba(255,80,80,0.3);
  background: rgba(255,80,80,0.06);
}
.wj-hound-step-num {
  width: 14px; height: 14px; border-radius: 50%;
  background: #222; border: 1px solid #444;
  display: flex; align-items: center; justify-content: center;
  font-size: 8px; flex-shrink: 0;
}
.wj-hound-step.active .wj-hound-step-num { background: #f90; border-color: #f90; color: #000; }
.wj-hound-step.done   .wj-hound-step-num { background: #4c8; border-color: #4c8; color: #000; }
.wj-hound-step.failed .wj-hound-step-num { background: #f44; border-color: #f44; color: #fff; }
.wj-hound-step-label  { flex: 1; }
.wj-hound-step-status { font-size: 9px; color: #888; }

/* ── LOG QSO ── */
.log-th {
  padding: 7px 10px; text-align: left; font-family: var(--mono);
  font-size: 10px; color: var(--dim); letter-spacing: 1px;
  border-right: 1px solid var(--border); white-space: nowrap;
}
.log-th:last-child { border-right: none; }
.log-th:hover { color: var(--green); }
#log-table tbody tr {
  border-bottom: 1px solid var(--border);
  transition: background 0.1s;
}
#log-table tbody tr:hover { background: var(--panel2); }
#log-table tbody td {
  padding: 6px 10px; font-family: var(--mono); font-size: 11px;
  color: var(--text); border-right: 1px solid var(--border); white-space: nowrap;
}
#log-table tbody td:last-child { border-right: none; }
.log-call { color: var(--green); font-weight: bold; }
.log-mode-cw  { color: var(--amber); }
.log-mode-ft8 { color: #7ec8e3; }
.log-mode-ft4 { color: #5bb8d4; }
.log-action-btn {
  background: none; border: 1px solid var(--border2); border-radius: 3px;
  color: var(--dim); font-family: var(--mono); font-size: 9px;
  padding: 2px 6px; cursor: pointer; transition: all 0.1s;
}
.log-action-btn:hover { border-color: var(--green); color: var(--green); }
.log-action-btn.del:hover { border-color: var(--red); color: var(--red); }

/* ── FORMY globalne (zachowane) ── */
input[type="text"], input[type="number"], input[type="password"], input[type="email"], select {
  background: var(--panel2); border: 1px solid var(--border2); border-radius: 4px;
  color: var(--green); font-family: var(--mono); font-size: 12px; padding: 7px 10px;
  outline: none; width: 100%; transition: border-color 0.2s;
}
input:focus, select:focus { border-color: var(--green); box-shadow: 0 0 4px rgba(var(--green-rgb),0.15); }
input::placeholder { color: var(--dim); }

/* ── TOAST ── */
.toast {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%) translateY(-20px);
  background: var(--panel); border: 1px solid var(--green2); border-radius: 8px;
  padding: 14px 28px; font-family: var(--mono); font-size: 14px; color: var(--green);
  z-index: 99999; opacity: 0; transition: all 0.25s; pointer-events: none;
  box-shadow: 0 4px 24px rgba(0,0,0,0.6); white-space: nowrap; max-width: 90vw;
  text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.error { border-color: var(--red); color: var(--red); }
.toast.warning { border-color: var(--amber); color: var(--amber); }

/* ── SCROLLBAR ── */
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

/* ── PAGES ── */
.page-content { display: none; padding: 14px; }
.page-content.active { display: block; }
#page-wsjtx { padding: 0; }
#page-wsjtx.active { display: flex; flex-direction: column; height: var(--wsjtx-h, 1028px); overflow: hidden; }
body.page-wsjtx-active, html.page-wsjtx-active { overflow: hidden; scrollbar-gutter: auto; }
#page-radio { padding: 0; }
#page-radio.active { display: block; height: var(--radio-grid-h, calc(1080px - 52px)); max-height: var(--radio-grid-h, calc(1080px - 52px)); overflow: hidden; }
body.page-radio-active, html.page-radio-active { overflow: hidden; scrollbar-gutter: auto; }

/* DX Cluster — pelna wysokosc, bez scrolla strony. Lista spotow scrolluje
   wewnetrznie, reszta (pasek gorny, config, CLI) jest staticzna. */
#page-dxcluster { padding: 8px; }
#page-dxcluster.active { display: flex; flex-direction: column; height: calc(100vh - 90px); overflow: hidden; }
#page-dxcluster .page-col { max-width: 100%; padding-bottom: 0; gap: 6px; }

/* ── LOG TABLE ── */
.log-table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 11px; }
.log-table th { padding: 6px 8px; text-align: left; color: var(--dim); font-weight: 400; border-bottom: 1px solid var(--border); font-size: 10px; letter-spacing: 1px; }
.log-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); color: var(--text); }
.log-table tr:hover td { background: var(--panel2); }
.log-table .call { color: var(--green); font-weight: bold; }
.log-table .freq { color: var(--amber); }
.del-btn { background: none; border: none; color: var(--dim); cursor: pointer; font-size: 13px; transition: color 0.1s; }
.del-btn:hover { color: var(--red); }

/* ── SETTINGS ── */
.settings-layout { display: flex; flex-direction: column; gap: 18px; padding: 0 0 25px; }
/* Jednolity wrapper dla stron admin/settings/internet — jedna kolumna, max-width */
.page-col {
  display: flex; flex-direction: column; gap: 18px;
  max-width: 1075px; padding-bottom: 30px;
}
.page-col .box { width: 100%; }
.page-col .box-header { font-size: 15px; padding: 9px 15px; letter-spacing: 2px; }
.page-col .box-body   { padding: 15px; font-size: 13px; }
.page-col input[type="text"],
.page-col input[type="number"],
.page-col input[type="password"],
.page-col input[type="email"],
.page-col select,
.page-col textarea {
  font-size: 13px; padding: 7px 10px;
}
/* PROFIL: pary bokow obok siebie (MOJ PROFIL+HASLO, AUDIO+WYGLAD), TX EQ
   sam na cala szerokosc. Staly grid bez @media — zgodny z zasada #app-scale
   nizej (caly UI renderowany w stalym 1440px i skalowany transform:scale(),
   wiec proporcje kolumn sa identyczne na kazdej fizycznej rozdzielczosci,
   nie trzeba przelamywac ukladu przy roznych ekranach). */
.profile-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }

.settings-inner  { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 13px 15px; }
.sg { display: flex; flex-direction: column; gap: 5px; }
.sg label { font-family: var(--mono); font-size: 13px; color: var(--dim); letter-spacing: 1px; }
.save-btn {
  background: rgba(var(--green-rgb),0.12); border: 1px solid var(--green2); border-radius: 4px;
  color: var(--green); font-family: var(--mono); font-size: 14px; letter-spacing: 1.5px;
  padding: 11px; cursor: pointer; width: 100%; transition: all 0.15s;
}
.save-btn:hover { background: rgba(var(--green-rgb),0.2); }

/* ── ADMIN ── */
.admin-btn {
  background: rgba(var(--green-rgb),0.1); border: 1px solid var(--green2); border-radius: 4px;
  color: var(--green); font-family: var(--mono); font-size: 10px; padding: 4px 10px; cursor: pointer;
}
.admin-table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 11px; }
.admin-table th { padding: 7px 10px; text-align: left; color: var(--dim); font-size: 10px; letter-spacing: 1px; border-bottom: 1px solid var(--border); font-weight: 400; }
.admin-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); color: var(--text); }
.admin-table tr:hover td { background: var(--panel2); }

/* ── Transfer Widget (wybor przyciskow / sliderow) ── */
.tw-widget { background: var(--panel2); border: 1px solid var(--border); border-radius: 5px; padding: 12px; }
.tw-body { display: grid; grid-template-columns: 1fr 90px 1fr; gap: 8px; align-items: start; }
.tw-col { display: flex; flex-direction: column; gap: 4px; }
.tw-col-header {
  font-family: var(--mono); font-size: 9px; color: var(--dim); letter-spacing: 1px;
  display: flex; justify-content: space-between; align-items: center;
  padding: 3px 0; border-bottom: 1px solid var(--border); margin-bottom: 2px;
}
.tw-count {
  background: var(--panel3); color: var(--green); font-size: 9px;
  padding: 1px 5px; border-radius: 8px; font-family: var(--mono);
}
.tw-list {
  min-height: 160px; max-height: 240px; overflow-y: auto;
  background: var(--bg); border: 1px solid var(--border); border-radius: 3px;
  padding: 2px;
}
.tw-list.tw-drag-over { border-color: var(--green); background: rgba(var(--green-rgb),0.05); }
.tw-item {
  display: flex; justify-content: space-between; align-items: center;
  padding: 5px 8px; font-family: var(--mono); font-size: 10px; color: var(--text);
  border-radius: 2px; cursor: pointer; user-select: none; gap: 6px;
  border-bottom: 1px solid var(--border);
}
.tw-item:last-child { border-bottom: none; }
.tw-item:hover { background: var(--panel2); }
.tw-item.tw-selected { background: rgba(var(--green-rgb),0.12); color: var(--green); border-color: rgba(var(--green-rgb),0.2); }
.tw-item[draggable="true"]:active { opacity: 0.5; }
.tw-sub { font-size: 8px; color: var(--dim); letter-spacing: 0.5px; flex-shrink: 0; }
.tw-buttons {
  display: flex; flex-direction: column; gap: 4px;
  padding-top: 20px; /* wyrownaj z lista */
}
.tw-btn {
  background: var(--panel3); border: 1px solid var(--border); border-radius: 3px;
  color: var(--dim); font-family: var(--mono); font-size: 9px; padding: 5px 4px;
  cursor: pointer; text-align: center; letter-spacing: 0.5px; white-space: nowrap;
  transition: all 0.1s;
}
.tw-btn:hover { border-color: var(--green); color: var(--green); background: rgba(var(--green-rgb),0.06); }
.tw-hint { font-family: var(--mono); font-size: 8px; color: var(--dim); text-align: center; padding-top: 2px; }


/* ── MODAL ── */
.modal-overlay {
  display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.7);
  z-index: 1000; align-items: center; justify-content: center;
}
.modal-overlay.active,
.modal-overlay[style*="flex"] { display: flex; }
.modal-box {
  background: var(--panel); border: 1px solid var(--border2); border-radius: 8px;
  padding: 20px; max-width: 480px; width: 90%; max-height: 90vh; overflow-y: auto;
}
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 16px; font-family: var(--mono); font-size: 12px; color: var(--text); letter-spacing: 2px;
}
.modal-close {
  background: none; border: none; color: var(--dim); cursor: pointer; font-size: 16px; transition: color 0.2s;
}
.modal-close:hover { color: var(--red); }
.modal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.full-row { grid-column: 1 / -1; }
.change-pwd-form { display: flex; flex-direction: column; gap: 12px; padding: 12px; }
.change-pwd-form .field { display: flex; flex-direction: column; gap: 4px; }
.change-pwd-form label { font-family: var(--mono); font-size: 10px; color: var(--dim); letter-spacing: 1px; }
.role-badge {
  font-family: var(--mono); font-size: 10px; padding: 2px 8px; border-radius: 3px;
  border: 1px solid var(--border); color: var(--dim); background: var(--panel2);
}

/* ── VFO CYFRY (zachowane z oryginalnego) ── */
.vfo-digit { display: inline-block; min-width: 30px; text-align: center; border-radius: 4px; padding: 0 2px; transition: background 0.12s, color 0.15s; }
.vfo-digit.active { cursor: ns-resize; }
.vfo-digit.active:hover { background: rgba(var(--green-rgb),0.12); text-shadow: 0 0 20px rgba(var(--green-rgb),1); }
.vfo-digit.selected { background: rgba(var(--green-rgb),0.18); outline: 1px solid rgba(var(--green-rgb),0.5); text-shadow: 0 0 25px rgba(var(--green-rgb),1); }
.vfo-sep { color: rgba(var(--green-rgb),0.3); padding: 0 2px; font-size: 36px; line-height: 1; }
.vfo-sep.sep-mhz { color: rgba(var(--green-rgb),0.5); font-size: 40px; }
/* Up/down arrow triangles above/below each VFO digit — click bumps that
   digit's position by one step, same effect as scrolling on it (an
   alternative for touchscreens/mice where wheel-over-a-digit isn't
   obvious). */
/* min-width matches .vfo-digit's own min-width — locks each column to a
   fixed, non-overlapping slot in the row, so an arrow is always centered
   over its OWN digit and never visually bleeds toward a neighbor
   (reported live: clicking the arrow shown over one digit changed a
   DIFFERENT, adjacent one instead). letter-spacing:-1px is set on the
   #vfo-digits row itself (inline style) for the bare digit characters —
   reset to normal here so it doesn't also compress/shift the arrow
   glyphs relative to their column. */
.vfo-digit-col { display: inline-flex; flex-direction: column; align-items: center;
  line-height: 1; min-width: 30px; letter-spacing: normal; }
.vfo-arrow { font-size: 9px; line-height: 1; padding: 1px 0; color: rgba(var(--green-rgb),0.3);
  cursor: pointer; user-select: none; transition: color 0.12s, text-shadow 0.12s;
  width: 100%; text-align: center; }
.vfo-arrow:hover { color: rgba(var(--green-rgb),0.95); text-shadow: 0 0 8px rgba(var(--green-rgb),0.7); }

/* ── CHAT (operator chat, embedded in the OPERATORZY panel — chat.js) ── */
.chat-msg { font-family: var(--mono); font-size: 10px; line-height: 1.4; padding: 3px 5px;
  border-radius: 3px; background: transparent; }
.chat-msg.chat-mine { background: rgba(var(--green-rgb),0.06); }
.chat-msg.chat-system { display: flex; align-items: center; gap: 5px; color: var(--dim);
  font-size: 9px; padding: 1px 5px; }
.chat-header { display: flex; align-items: center; gap: 4px; margin-bottom: 1px; }
.chat-role-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.chat-user { font-weight: bold; }
.chat-call { color: var(--dim); font-size: 9px; }
.chat-time { color: var(--dim); font-size: 8px; margin-left: auto; }
.chat-text { color: var(--text); word-break: break-word; }
.chat-sys-text { font-style: italic; }
.chat-badge {
  position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px;
  border-radius: 8px; background: var(--red); color: #fff; font-size: 9px;
  line-height: 15px; text-align: center; padding: 0 3px; font-weight: bold;
}

/* ── RESPONSIVE ── */
/* RESPONSYWNOSC: brak @media breakpoints — caly layout jest renderowany w
   stalym rozmiarze referencyjnym 1440x1080 (#app-scale) i skalowany
   jednolicie (transform:scale) wg viewportu w index.html. Reflow przez
   @media kolidowalby z tym podejsciem (zmienialby pozycje elementow przy
   przeskalowanym, ale wciaz "logicznie 1440px" widoku). */

/* Selektor radia */
#rig-selector-row select {
  width: 100%; font-family: var(--mono); font-size: 11px;
  background: var(--panel2); border: 1px solid var(--border);
  color: var(--green); border-radius: 4px; padding: 6px 8px;
}

/* ══════════════════════════════════════════════════════════════════════════════
   WSJT-X PAGE — ciemny motyw zbliżony do oryginału WSJT-X
   ══════════════════════════════════════════════════════════════════════════════ */

/* Layout */
/* ── 1. GÓRNY PASEK STATUSU I STEROWANIA (DWIE LINIE, przejete z forka 2026-10-17) ── */
.wsjtx-layout {
  display: flex; flex-direction: column;
  flex: 1; height: 100%;
  background: var(--wj-bg); color: var(--wj-text); overflow: hidden;
  font-family: var(--ui); user-select: none;
}

.wsjtx-topbar {
  /* FIX (2026-10-17, live report: chce wiekszy wodospad, "wyciagnac okna
     band i rx wyzej") - caly pasek nad wodospadem (ten blok + cycle-bar +
     scope-toolbar ponizej) scisniety, zeby zwolnic wysokosc dla wodospadu
     i okien dekodowan pod nim. */
  display: flex; flex-direction: column; gap: 5px;
  background: var(--wj-topbar); border-bottom: 2px solid var(--wj-border);
  padding: 5px 10px; flex-shrink: 0; z-index: 10;
  box-shadow: 0 2px 10px rgba(0,0,0,0.15);
}
.wj-topbar-row-1, .wj-topbar-row-2 {
  display: flex; align-items: center; gap: 10px; width: 100%; flex-wrap: nowrap;
}
.wj-topbar-left {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0;
}
.wj-topbar-right {
  width: 380px; min-width: 380px; display: flex; align-items: center;
  box-sizing: border-box; padding-left: 6px;
}

.wsjtx-freq {
  font-family: var(--mono); font-size: 18px; font-weight: 800;
  color: #fff; letter-spacing: 0.6px;
  background: var(--wj-input-bg); padding: 4px 10px; border-radius: 6px;
  border: 1px solid var(--wj-border-bright);
  display: flex; align-items: center; gap: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
  min-width: 158px; white-space: nowrap; flex-shrink: 0; box-sizing: border-box;
}
.wsjtx-freq::before {
  content: ''; display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--green); box-shadow: 0 0 8px var(--green); flex-shrink: 0;
}
html[data-mode="light"] .wsjtx-freq { color: #0284c7; background: #ffffff; border-color: #cbd5e1; }

.wj-mode-switch {
  display: inline-flex; border: 1px solid var(--wj-border-bright); border-radius: 6px;
  overflow: hidden; background: var(--wj-input-bg); flex-shrink: 0;
}
.wj-mode-btn {
  font-family: var(--mono); font-size: 12px; font-weight: 800; letter-spacing: 0.5px;
  color: var(--wj-text-dim); background: transparent; border: none;
  padding: 4px 11px; cursor: pointer; transition: all 0.15s;
}
.wj-mode-btn:hover { background: rgba(255,255,255,0.08); color: var(--wj-text); }
.wj-mode-btn.active { background: #0284c7 !important; color: #fff !important; }

.wj-band-select {
  /* Natural (auto) width on purpose - checked live 2026-10-21: both 80px
     and 19ch cut the selected option to "20m (14.074 ..." because the
     native dropdown arrow eats into the box. Auto sizes to the widest
     option, which is the smallest width that shows the full text. */
  font-family: var(--mono); font-size: 12px; font-weight: 800;
  background: var(--wj-input-bg); border: 1px solid var(--wj-border-bright);
  color: var(--green); padding: 5px 9px; border-radius: 6px; outline: none; cursor: pointer;
  width: auto; flex-shrink: 0;
}

.wj-topbar-check {
  font-size: 12px; font-family: var(--mono); font-weight: 800; color: var(--wj-text);
  display: flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 4px 9px; border-radius: 6px; border: 1px solid var(--wj-border-bright);
  background: var(--wj-card); transition: all 0.15s;
  flex-shrink: 0; /* see .wj-period-switch's comment - don't get squeezed by the TX-wait status pill */
}
.wj-topbar-check:hover { background: var(--wj-card-sub); border-color: #0284c7; }
.wj-topbar-check input { cursor: pointer; accent-color: var(--green); width: 15px; height: 15px; }
.wj-topbar-check.hound-box {
  color: #f97316; border-color: rgba(249,115,22,0.55); background: rgba(249,115,22,0.12);
}
.wj-topbar-check.hound-box input { accent-color: #f97316; }

.wj-period-switch {
  /* flex-shrink:0 (2026-10-20, live request: "jak [status pill] sie pojawi
     przycina 1st/2nd") - #wj-tx-wait-status sharing this row starts at
     display:none and only appears during TX wait/transmit; the row is
     flex-wrap:nowrap, so without this, the newly-visible pill's width
     squeezed the OTHER items (this one included) to make room instead of
     the pill's own ellipsis/overflow handling absorbing it alone. */
  display: inline-flex; border: 1px solid var(--wj-border-bright); border-radius: 6px; overflow: hidden;
  flex-shrink: 0;
}
.wj-period-switch .wj-mode-btn.active { background: #0284c7 !important; color: #fff !important; }

.wsjtx-clock-wrap {
  display: flex; align-items: center; gap: 6px;
  background: var(--wj-input-bg); border: 1px solid var(--wj-border-bright);
  padding: 3px 8px; border-radius: 6px;
  flex-shrink: 0; /* see .wj-period-switch's comment above */
}
#wj-clock-s {
  font-family: var(--mono); font-size: 17px; font-weight: 800; color: var(--wj-text);
  min-width: 22px; text-align: right;
}

.wsjtx-status-pill {
  font-family: var(--mono); font-size: 11px; font-weight: 800;
  padding: 4px 10px; border-radius: 6px; border: 1px solid var(--wj-border-bright);
  color: var(--wj-text-dim); background: var(--wj-card);
  display: flex; align-items: center; gap: 6px; white-space: nowrap;
}
.wsjtx-status-pill.online   { color: #22c55e; border-color: rgba(34,197,94,0.4); background: rgba(34,197,94,0.15); }
.wsjtx-status-pill.tx       { color: #ef4444; border-color: rgba(239,68,68,0.4); background: rgba(239,68,68,0.15); }
.wsjtx-status-pill.decoding { color: var(--amber); border-color: rgba(var(--amber-rgb),0.4); background: rgba(var(--amber-rgb),0.15); }

/* Przyciski topbar */
.wj-btn {
  font-family: var(--mono); font-size: 12px; font-weight: 800;
  padding: 5px 11px; cursor: pointer; border-radius: 6px;
  border: 1px solid var(--wj-border-bright); background: var(--wj-card); color: var(--wj-text);
  transition: all 0.15s; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
}
.wj-btn:hover { background: var(--wj-card-sub); border-color: #0284c7; color: #fff; }
html[data-mode="light"] .wj-btn:hover { color: #0284c7; }

.wj-btn-tune {
  background: rgba(239,68,68,0.15); border-color: rgba(239,68,68,0.5); color: #ef4444;
}
.wj-btn-tune:hover, .wj-btn-tune.active { background: #ef4444 !important; color: #fff !important; border-color: #ef4444 !important; }

#wj-own-rx-btn {
  width: 100%; justify-content: center; font-size: 12.5px; font-weight: 800; padding: 6px 14px;
  background: rgba(34,197,94,0.2); border-color: #22c55e; color: #22c55e;
}
#wj-own-rx-btn.active { background: rgba(34,197,94,0.25); border-color: #22c55e; color: #22c55e; }
#wj-own-rx-btn.active:hover { background: rgba(34,197,94,0.4); color: #fff; }
#wj-own-rx-btn.stopped { background: rgba(245,158,11,0.18); border-color: #f59e0b; color: #f59e0b; }
#wj-own-rx-btn.stopped:hover { background: rgba(245,158,11,0.35); color: #fff; }

/* ── 1.5. PASEK POSTĘPU CYKLU UTC ── */
.cycle-bar-wrap {
  background: #03060a; border-bottom: 1px solid var(--wj-border);
  padding: 4px 12px; flex-shrink: 0; box-sizing: border-box;
}
.cycle-bar-header {
  display: flex; justify-content: space-between; align-items: center;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  margin-bottom: 3px; color: var(--wj-text-dim);
}
.cycle-progress-outer {
  position: relative; height: 16px; background: #020408;
  border: 1px solid var(--wj-border-bright); border-radius: 5px; overflow: hidden; display: flex;
}
.cycle-progress-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, #10b981 0%, #06b6d4 75%, #f59e0b 84%, #f43f5e 100%);
  transition: width 0.1s linear;
}
.cycle-markers-overlay {
  position: absolute; inset: 0; display: flex; pointer-events: none;
  font-family: var(--mono); font-size: 9.5px; font-weight: 800; line-height: 16px;
}
.c-marker-rx  { position: absolute; left: 8px;  color: #4ade80; }
.c-marker-dec { position: absolute; left: 82%;  color: #facc15; }
.c-marker-tx  { position: absolute; left: 93%;  color: #f87171; }
html[data-mode="light"] .cycle-bar-wrap { background: #f1f5f9; border-bottom: 1px solid var(--wj-border); }
html[data-mode="light"] .cycle-progress-outer { background: #e2e8f0; border-color: #cbd5e1; }
html[data-mode="light"] .cycle-bar-header { color: #475569; }

/* ── 2. WODOSPAD / SCOPE I TOOLBAR CZĘSTOTLIWOŚCI (przejete z forka 2026-10-17) ── */
.wsjtx-scope-wrap {
  flex-shrink: 0; border-bottom: 1px solid var(--wj-border); background: #020408;
  width: 100%; min-width: 0; display: flex; flex-direction: column;
}
.wsjtx-scope-toolbar {
  display: flex; align-items: center; gap: 8px; padding: 3px 10px;
  background: var(--wj-card); border-bottom: 1px solid var(--wj-border);
  font-family: var(--mono); font-size: 11px; color: var(--wj-text-dim);
}
.wsjtx-scope-canvas {
  /* Halved (2026-10-20, live request: "ramka w ktorej sie znajduje wybor
     jest za duza") - this is the clickable waterfall used to pick the TX
     audio frequency; the backing bitmap resolution tracks this CSS height
     dynamically (see wsjtx_scope.js's resize handler), so no JS change
     needed alongside this. */
  display: block; width: 100%; height: 80px; cursor: crosshair;
  background: #020408;
}
.wsjtx-scope-axis {
  position: relative; height: 20px; background: var(--wj-topbar);
  border-bottom: 1px solid var(--wj-border); overflow: hidden;
  font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--wj-text-dim);
}
.wsjtx-scope-axis .wj-axis-tick {
  position: absolute; top: 3px; transform: translateX(-50%);
  white-space: nowrap;
}
/* Flagi stacji wolających CQ na wodospadzie FT8 (klikalne — QSY do nich) */
.wj-cq-flag {
  position: absolute; top: 2px; transform: translateX(-50%);
  pointer-events: auto; cursor: pointer;
  display: flex; flex-direction: column; align-items: center;
  font-family: var(--mono); font-size: 9px; line-height: 1.1;
  z-index: 5;
}
.wj-cq-flag::after {
  content: ''; width: 1px; height: 6px; background: rgba(var(--green-rgb),0.67);
  margin-top: 1px;
}
.wj-cq-flag-call {
  background: rgba(2,8,16,0.82); border: 1px solid var(--green); color: var(--green);
  border-radius: 2px; padding: 1px 4px; white-space: nowrap; box-shadow: 0 0 4px rgba(0,0,0,0.6);
}
.wj-cq-flag:hover .wj-cq-flag-call {
  background: var(--green); color: var(--on-accent); border-color: var(--green);
}
#wj-tx-freeze-btn.active { border-color: #2a6a8a; color: #4cf; background: #05202a; }
#wj-fake-split-toggle.active { border-color: #8a6a2a; color: #fc0; background: #2a1f05; }

/* Edytowalne pola czestotliwosci RX/TX w toolbarze scope'a */
.wj-freq-field {
  font-family: var(--mono); font-size: 11.5px; font-weight: 800;
  display: inline-flex; align-items: center; gap: 5px;
}
.wj-freq-input {
  width: 56px; background: var(--wj-input-bg); border: 1px solid var(--wj-border-bright);
  color: inherit; font-family: var(--mono); font-size: 12px; font-weight: 800;
  padding: 2px 5px; border-radius: 4px; text-align: right; outline: none;
}
.wj-freq-input:focus { border-color: #0284c7; }
/* Ukryj strzalki spinner w number input dla czystszego wygladu */
.wj-freq-input::-webkit-inner-spin-button,
.wj-freq-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.wj-freq-input[type=number] { -moz-appearance: textfield; }

/* ── 3. POZIOMY SPLITTER MIĘDZY WODOSPADEM A DEKODOWANIAMI ── */
.wj-h-split-resizer {
  height: 7px; background: var(--wj-card);
  border-top: 1px solid var(--wj-border); border-bottom: 1px solid var(--wj-border);
  cursor: row-resize; display: flex; align-items: center; justify-content: center;
  transition: background 0.15s; z-index: 10; flex-shrink: 0;
}
.wj-h-split-resizer:hover, .wj-h-split-resizer.dragging { background: #0284c7; }
.wj-h-split-grip { width: 60px; height: 3px; border-radius: 2px; background: rgba(255,255,255,0.4); }
html[data-mode="light"] .wj-h-split-grip { background: rgba(0,0,0,0.3); }

/* ── 4. OKNA DEKODOWAŃ: BAND ACTIVITY & RX FREQUENCY ── */
.wsjtx-main {
  display: flex; flex-direction: row; flex: 1;
  overflow: hidden; gap: 0; min-height: 0; align-items: stretch;
}

.wsjtx-decodes-wrap {
  display: flex; flex-direction: row; flex: 1; width: 100%;
  min-height: 0; overflow: hidden; position: relative; background: var(--wj-bg);
}

.wj-split-pane {
  display: flex; flex-direction: column; overflow: hidden;
  min-width: 140px; flex-grow: 1; flex-shrink: 1; min-height: 0;
}
.wj-split-resizer {
  flex: 0 0 6px; cursor: col-resize; background: var(--wj-card);
  border-left: 1px solid var(--wj-border); border-right: 1px solid var(--wj-border);
  position: relative; transition: background 0.2s;
}
.wj-split-resizer:hover, .wj-split-resizer.dragging { background: #0284c7; }
.wj-split-resizer::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%,-50%); width: 2px; height: 30px;
  background: rgba(255,255,255,0.3); border-radius: 1px;
}
.wj-btn-xs {
  font-size: 10px; padding: 1px 5px; line-height: 1.4;
}
/* Poziomy resizer gora/dol miedzy wodospadem a oknami dekodow (Band Activity / RX Frequency) */
.wj-h-split-resizer {
  height: 7px; background: var(--wj-card);
  border-top: 1px solid var(--wj-border); border-bottom: 1px solid var(--wj-border);
  cursor: row-resize; display: flex; align-items: center; justify-content: center;
  transition: background 0.15s; z-index: 10; flex-shrink: 0;
}
.wj-h-split-resizer:hover, .wj-h-split-resizer.dragging { background: #0284c7; }
.wj-h-split-grip { width: 60px; height: 3px; border-radius: 2px; background: rgba(255,255,255,0.4); }
html[data-mode="light"] .wj-h-split-grip { background: rgba(0,0,0,0.3); }

.wj-panel-title {
  background: var(--wj-card); border-bottom: 1px solid var(--wj-border);
  padding: 6px 12px; display: flex; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: 13px; font-weight: 800;
  color: var(--wj-text); letter-spacing: 0.5px;
}

.wsjtx-decode-header {
  /* FIX (2026-10-17, live report: "band i rx maja za duza czcionke nie
     miesci sie pelen opis dekodow"): kolumny i font przejete 1:1 z forka
     byly za duze na realna tresc (dluzsze prawdziwe znaki/lokatory/raporty
     niz testowe skroty) - zmniejszone kolumny Grid/Country/czas/dB/DT/Freq,
     zwezony gap i font, zeby oddac wiecej miejsca kolumnie Message (1fr). */
  display: grid; grid-template-columns: 50px 38px 38px 48px 1fr 42px 44px;
  column-gap: 5px; padding: 4px 8px;
  background: var(--wj-card-sub); border-bottom: 1px solid var(--wj-border);
  font-family: var(--mono); font-size: 10px; color: var(--wj-text-dim);
  font-weight: 800; letter-spacing: 0.3px; flex-shrink: 0; box-sizing: border-box;
}
.wsjtx-decode-header .wjh-r { text-align: right; }
.wjh {
  padding: 0 4px; white-space: nowrap; user-select: none;
}
.wjh-r { text-align: right; }

.wsjtx-decode-list {
  flex: 1; overflow-y: auto; overflow-x: hidden; min-height: 0;
  background: var(--wj-bg); font-family: var(--mono); font-size: 11.5px;
}
.wsjtx-decode-list::-webkit-scrollbar { width: 5px; }
.wsjtx-decode-list::-webkit-scrollbar-track { background: var(--wj-bg); }
.wsjtx-decode-list::-webkit-scrollbar-thumb { background: var(--wj-border-bright); border-radius: 3px; }

/* Wiersz zdekodowanej stacji */
.wj-decode-row {
  display: grid; grid-template-columns: 50px 38px 38px 48px 1fr 42px 44px;
  column-gap: 5px; align-items: center; padding: 3px 8px; line-height: 20px;
  cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.04);
  font-weight: 600; color: var(--wj-text); font-size: 11.5px;
  transition: background 0.1s; white-space: nowrap; overflow: hidden; box-sizing: border-box;
}
.wj-decode-row .wj-d-snr, .wj-decode-row .wj-d-dt, .wj-decode-row .wj-d-freq { text-align: right; }
.wj-decode-row .wj-d-msg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="light"] .wj-decode-row { border-bottom: 1px solid rgba(0,0,0,0.06); }
.wj-decode-row:hover { background: rgba(255,255,255,0.08); }
html[data-mode="light"] .wj-decode-row:hover { background: rgba(2,132,199,0.08); }
.wj-decode-row.wj-cq     { color: #38bdf8; font-weight: 700; }   /* CQ — jasny niebieski jak w WSJT-X */
.wj-decode-row.wj-mycall  { color: #fca5a5; background: rgba(239,68,68,0.2) !important; font-weight: 800; border-left: 3px solid #ef4444; }  /* własny callsign */
.wj-decode-row.wj-dx      { color: #22c55e; font-weight: 700; }  /* odpowiedź do DX — zielony */
.wj-decode-row.wj-73      { color: #fbbf24; font-weight: 700; }  /* 73/RR73 — bursztyn */
.wj-decode-row.wj-worked  { color: var(--wj-text-dimmer); text-decoration: line-through; opacity: 0.6; } /* juz w logu */
.wj-decode-row.wj-own-tx  { color: #fef08a; background: rgba(245,158,11,0.16) !important; font-weight: 700; border-left: 3px solid #f59e0b; }  /* nasz TX */
/* Tryb jasny: kolory wierszy powyzej (pastelowe, dobrane pod ciemne tlo)
   zlewaly sie z jasnym tlem - zgloszenie 2026-11-02 (zrzut ft8.bmp: nasze
   TX, 73/RR73 i CQ prawie niewidoczne). Te same barwy, ciemniejsze odcienie.
   !important przy TX - tlo i znacznik "TX" sa ustawiane inline w wsjtx.js. */
html[data-mode="light"] .wj-decode-row.wj-cq     { color: #0369a1; }
html[data-mode="light"] .wj-decode-row.wj-mycall { color: #991b1b; background: rgba(239,68,68,0.14) !important; border-left-color: #dc2626; }
html[data-mode="light"] .wj-decode-row.wj-dx     { color: #15803d; }
html[data-mode="light"] .wj-decode-row.wj-73     { color: #b45309; }
html[data-mode="light"] .wj-decode-row.wj-worked { color: #64748b; opacity: 0.8; }
html[data-mode="light"] .wj-decode-row.wj-own-tx { color: #78350f !important; background: rgba(245,158,11,0.22) !important; border-left: 3px solid #d97706 !important; }
html[data-mode="light"] .wj-decode-row.wj-own-tx .wj-tx-mark { color: #b45309 !important; }
html[data-mode="light"] .wj-tx-btn { color: #334155; }
html[data-mode="light"] .wj-tx-btn:hover { color: #0f172a; }
html[data-mode="light"] .wj-tx-btn.active { color: #92400e !important; }
html[data-mode="light"] .wj-tx-num { color: #b45309; }
html[data-mode="light"] #wj-autoqso-status { color: #0f172a !important; }
.wj-decode-row.selected   { outline: 1px solid var(--green); background: rgba(56,189,248,0.15) !important; }

/* ── Belka separatora periodow dekodowania (dashed line + badge) —
   zastepuje pojedynczy <div class="wj-period-sep"> generowany w
   wsjtx.js (_renderDecodes) prostym, tematycznym podzialem zamiast
   pelnej struktury sep-line/sep-badge z forka, bo JS nie generuje
   tych dodatkowych elementow potomnych. ── */
.wj-period-sep {
  border-top: 2px solid var(--wj-period-bar-border); margin: 4px 6px 2px;
  opacity: 0.9;
}

.wj-d-time { color: var(--wj-text-dimmer); font-size: 11px; }
.wj-d-dt, .wj-d-freq { color: var(--wj-text-dim); }
.wj-d-grid { min-width: 52px; color: var(--wj-text-dimmer); font-size: 10px; }
.wj-d-country { min-width: 60px; color: var(--wj-text-dimmer); font-size: 10px; overflow: hidden; text-overflow: ellipsis; }

.wj-empty {
  padding: 20px; text-align: center;
  font-family: var(--mono); font-size: 11px; color: var(--wj-text-dimmer);
}

/* ── Zmienne FT8/WSJT-X (przejete z forka 2026-10-16, panel prawy) —
   oddzielny, lokalny zestaw tokenow dla tej strony (karty/obwodki
   dopasowane do ciemnej "karty" w stylu oryginalnego WSJT-X), poza
   glownymi --panel/--border uzywanymi wszedzie indziej. ── */
:root {
  --wj-bg:          #070c14;
  --wj-card:        #0b111a;
  --wj-card-sub:    #0f1724;
  --wj-topbar:      #090e18;
  --wj-border:      rgba(var(--green-rgb),0.12);
  --wj-border-bright: rgba(var(--green-rgb),0.28);
  --wj-text:        #e2e8f0;
  --wj-text-dim:    #94a3b8;
  --wj-text-dimmer: #64748b;
  --wj-input-bg:    var(--input-bg);
  --wj-period-bar-bg:     #081220;
  --wj-period-bar-border: #0284c7;
  --wj-period-bar-text:   #38bdf8;
  --wj-badge-bg:    rgba(2, 132, 199, 0.25);
  --wj-badge-border: rgba(56, 189, 248, 0.4);
}
:root[data-mode="light"] {
  --wj-bg:          #f8fafc;
  --wj-card:        #ffffff;
  --wj-card-sub:    #f1f5f9;
  --wj-topbar:      #ffffff;
  --wj-border:      rgba(15, 23, 42, 0.09);
  --wj-border-bright: rgba(15, 23, 42, 0.20);
  --wj-text:        #0f172a;
  --wj-text-dim:    #475569;
  --wj-text-dimmer: #64748b;
  --wj-period-bar-bg:     #e0f2fe;
  --wj-period-bar-border: #0284c7;
  --wj-period-bar-text:   #0369a1;
  --wj-badge-bg:    rgba(2, 132, 199, 0.15);
  --wj-badge-border: rgba(2, 132, 199, 0.4);
}

/* Prawa kolumna */
.wsjtx-right {
  width: 380px; min-width: 380px; flex-shrink: 0;
  display: flex; flex-direction: column;
  background: var(--wj-card);
  border-left: 2px solid var(--wj-border);
  overflow-y: auto;
  gap: 10px; padding: 12px; box-sizing: border-box;
  /* Kolumna zaczyna sie od linii waterfalla —
     wsjtx-main jest flex-row i zaczyna sie po topbarze+scope */
}
.wsjtx-right input[type="text"],
.wsjtx-right select {
  background: var(--wj-input-bg) !important;
  border: 1px solid var(--wj-border-bright) !important;
  color: var(--text) !important;
  border-radius: 4px !important;
}
.wsjtx-right input[type="text"]:focus,
.wsjtx-right select:focus {
  border-color: var(--green2) !important;
}
.wj-panel-title {
  font-family: var(--mono); font-size: 13.5px; font-weight: 800;
  color: var(--green); letter-spacing: 0.8px; margin-bottom: 8px;
}
.wj-panel-title label {
  font-size: 10px; color: var(--dim); display: flex; align-items: center;
  gap: 4px; cursor: pointer; font-weight: normal; text-transform: none;
  letter-spacing: normal;
}

/* Automatyka QSO — "status box" (przejete z forka): karta z wyrazniejszym
   stanem GOTOWY/trwajace QSO, zamiast samej linii tekstu jak poprzednio */
.auto-qso-box {
  background: var(--wj-card-sub);
  border: 1px solid var(--wj-border-bright);
  border-radius: 6px;
  padding: 10px 12px;
  font-family: var(--mono);
}
.auto-qso-box.active {
  border-color: rgba(34, 197, 94, 0.6);
  background: rgba(34, 197, 94, 0.08);
}

/* TX panel - FIX (2026-10-17, live report: "makra nie sa w stanie pokazac
   pelnego wypelnienia czcionka"): fork's own 13px/380px combo still wasn't
   enough for REALNA wypelniona tresc makra (dlugi prawdziwy znak + lokator
   + raport, np. "DL1ABC SQ3MZM R-15" - dluzsze niz skrocone dane testowe) -
   zmniejszony font i padding daja wiecej znakow na linie. */
.wsjtx-tx-panel {
  padding: 10px 12px; border: 1px solid var(--wj-border); border-radius: 6px;
  background: var(--wj-card-sub); flex-shrink: 0;
}
.wsjtx-tx-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-top: 8px;
}
.wj-tx-btn {
  display: flex; align-items: center; gap: 4px; min-width: 0;
  background: var(--wj-input-bg); border: 1px solid var(--wj-border-bright); border-radius: 5px;
  padding: 5px 6px; cursor: pointer; text-align: left;
  font-family: var(--mono); color: #cbd5e1; font-size: 10px; font-weight: 700;
  transition: all 0.15s; overflow: hidden;
}
.wj-tx-btn:hover { border-color: var(--green2); background: var(--wj-card); color: #fff; }
.wj-tx-btn.active {
  background: rgba(245, 158, 11, 0.28) !important; border-color: #f59e0b !important;
  color: #fbbf24 !important; font-weight: 800;
}
.wj-tx-num  { font-size: 10px; font-weight: 800; color: #f59e0b; flex-shrink: 0; }
.wj-tx-text {
  font-size: inherit; line-height: 1.3; flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Pola DX i SNR */
/* Font shrunk 15.5px -> 12px (2026-10-21, live request: the DX field's
   placeholder "-- KLIKNIJ WIERSZ LUB WPISZ --" didn't fit the field at the
   old size) - kept identical between DX and Grid on purpose, so the two
   fields still look consistent with each other, per the same request. */
#wj-dx-call { font-size: 12px !important; font-weight: 800 !important; color: var(--green) !important; padding: 7px 10px !important; }
#wj-dx-grid { width: 68px !important; font-size: 12px !important; font-weight: 800 !important; color: var(--green) !important; padding: 7px 8px !important; text-align: center; }
#wj-dx-snr  { font-size: 15px !important; font-weight: 800 !important; color: #22c55e !important; }

/* Antena i Rotor */
#wj-beam-row { font-size: 12.5px !important; padding: 8px 10px !important; border-radius: 5px !important; }
#wj-beam-az  { font-size: 20px !important; font-weight: 800 !important; color: #f59e0b !important; }
#wj-rotor-az { font-size: 13px !important; font-weight: 800 !important; color: #22c55e !important; }

/* Log QSO */
.wsjtx-log-panel {
  padding: 12px 14px; border: 1px solid var(--wj-border); border-radius: 6px;
  background: var(--wj-card-sub); display: flex; flex-direction: column; gap: 8px;
}
#wj-log-call, #wj-log-grid { font-size: 13.5px !important; padding: 6px 10px !important; }
#wj-log-mode, #wj-log-rst-sent, #wj-log-rst-rcvd { font-size: 12.5px !important; padding: 5px 8px !important; }
#wj-log-comment { font-size: 12px !important; padding: 5px 8px !important; }

/* Legenda kolorow wierszy dekodowania (zastepuje martwy panel "konfiguracja
   WSJT-X" - HAMCTRL ma wlasny dekoder, zewnetrzny WSJT-X nigdy nie jest
   wymagany, wiec ta instrukcja konfiguracji nie miala tu racji bytu) */
.wsjtx-config-panel {
  padding: 10px 12px; flex-shrink: 0; border: 1px solid var(--wj-border);
  border-radius: 6px; background: var(--wj-card-sub);
}
.wj-legend-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px;
}
.wj-legend-item {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--wj-text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wj-legend-dot {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}

/* Dolny pasek */
.wsjtx-bottombar {
  display: flex; align-items: center; gap: 10px;
  background: var(--wj-topbar); border-top: 1px solid var(--wj-border);
  padding: 5px 14px; flex-shrink: 0;
  font-family: var(--mono); font-size: 12px; color: var(--dim);
}

/* TX pulse animation */
@keyframes wj-tx-pulse {
  from { opacity: 1; } to { opacity: 0.5; }
}

/* Podswietlenie pola "callsign DX" w formularzu logowania, gdy automatyka
   QSO konczy polaczenie i czeka na zatwierdzenie przez uzytkownika */
@keyframes wj-pending-log-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(140, 190, 255, 0); }
  50% { box-shadow: 0 0 0 4px rgba(140, 190, 255, 0.5); }
}
.wj-pending-log-highlight {
  animation: wj-pending-log-pulse 0.6s ease-in-out 3;
  border-color: #8be !important;
}

/* Page layout override dla WSJTX — pełna wysokość */


/* ── Log QSO w zakładce WSJT-X ── */
.wj-log-row {
  border-bottom: 1px solid #111;
  transition: background 0.05s;
}
.wj-log-row:hover { background: #141414; }
.wj-log-row td    { padding: 2px 4px; color: #888; white-space: nowrap; }
.wj-log-call      { color: #4cf !important; font-weight: bold; }
.wj-log-empty     {
  padding: 16px; text-align: center;
  font-family: 'Share Tech Mono', monospace;
  font-size: 10px; color: #333;
}

/* Tryby cyfrowe (USB-D, LSB-D, PKTUSB, PKTLSB) — wyróżnienie */
.mode-btn-digital {
  border-color: rgba(var(--amber-rgb),0.4) !important;
  color: var(--amber) !important;
}
.mode-btn-digital.active {
  background: rgba(var(--amber-rgb),0.15) !important;
  border-color: var(--amber) !important;
  color: var(--amber) !important;
}