/* ============================================================
   Tibia AI — styl UI (klimat klasycznego klienta)
   ============================================================ */

:root{
  --bg:        #232323;
  --panel:     #3b3733;
  --panel-lo:  #2a2724;
  --panel-hi:  #5a544c;
  --bevel-lo:  #171514;
  --bevel-hi:  #6d675d;
  --ink:       #c8bda6;
  --ink-dim:   #8d8571;
  --gold:      #d8b25a;
  --hp:        #b02020;
  --mp:        #2f5fd0;
  --xp:        #b0a020;
  --slot:      #221f1c;
  --font: "Lucida Console", "DejaVu Sans Mono", Consolas, monospace;
}

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

html,body{
  height:100%;
  background:#101010;
  color:var(--ink);
  font-family:var(--font);
  font-size:12px;
  overflow:hidden;
  user-select:none;
  -webkit-user-select:none;
}

body{
  background:
    radial-gradient(ellipse at 50% 0%, #2c2822 0%, #0d0c0b 70%);
}

.hidden{display:none !important;}

/* ---------- układ ---------- */
#app{
  display:flex;
  height:100vh;
  gap:6px;
  padding:6px;
  align-items:stretch;
  justify-content:center;
}

.game-col{
  display:flex;
  flex-direction:column;
  gap:4px;
  min-width:0;
}

#viewport{
  position:relative;
  background:#000;
  border:3px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  line-height:0;
  align-self:flex-start;
}

#game{
  image-rendering:pixelated;
  image-rendering:crisp-edges;
  display:block;
  cursor:crosshair;
}

/* Uzbrojony celownik ([TD-228]) — rzecz z paska skrótów czeka na wskazanie
   pola. Kursor nad kadrem jest krzyżykiem **zawsze**, więc sam z siebie nic
   tu nie mówi: stan modalny widać po obwódce kadru. Na dotyku kursora nie ma
   w ogóle i wtedy obwódka jest jedyną zapowiedzią. */
body.aiming #viewport{ border-color:#d8b45a; }
body.aiming #game{ cursor:cell; }

#overlay{
  position:absolute;
  inset:0;
  pointer-events:none;
  z-index:5;
}

/* Komunikaty nad kadrem ([TD-224]). Kolor należy do **miejsca**, nie do
   wołającego — dokładnie jak w oryginale, gdzie `centerGreen` i `centerWhite`
   niosą kolor razem z `screenTarget`. Napisy nie łapią myszy: pod nimi leży
   mapa, po której się klika. */
.screen-msg{
  position:absolute;
  left:0; right:0;
  z-index:6;
  pointer-events:none;
  text-align:center;
  padding:0 6px;
  line-height:1.25;
  word-wrap:break-word;
  text-shadow:1px 1px 0 #000,-1px 1px 0 #000,1px -1px 0 #000,-1px -1px 0 #000;
}
#msg-high  {top:22%;   color:#6fdb6f; font-size:13px;}
#msg-center{top:44%;   color:#e8e2d4; font-size:14px;}
#msg-status{bottom:5px;color:#e8e2d4; font-size:11.5px;}

#tooltip{
  position:absolute;
  pointer-events:none;
  background:#0f0e0dee;
  border:1px solid var(--panel-hi);
  color:var(--ink);
  padding:3px 6px;
  font-size:11px;
  line-height:1.35;
  max-width:230px;
  z-index:40;
  white-space:pre-wrap;
}

/* ---------- hotbar ---------- */
#hotbar{
  display:flex;
  gap:3px;
  flex-wrap:wrap;
}
.hot{
  width:38px; height:38px;
  background:var(--slot);
  border:2px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  position:relative;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  font-size:9px;
  color:var(--ink-dim);
  text-align:center;
  overflow:hidden;
}
.hot .hk{
  position:absolute; top:0; left:2px;
  font-size:9px; color:var(--gold);
  text-shadow:1px 1px 0 #000;
}
.hot .hcount{
  position:absolute; bottom:0; right:2px;
  font-size:9px; color:#fff; text-shadow:1px 1px 0 #000;
}
/* Znacznik trybu użycia ([TD-228]) — bez niego dwa sloty z tą samą runą
   wyglądają identycznie, a robią co innego. Górny prawy róg, bo lewy zajmuje
   podpis klawisza, a dolny prawy — liczba sztuk. */
.hot .hmode{
  position:absolute; top:0; right:2px;
  font-size:9px; color:var(--gold); text-shadow:1px 1px 0 #000;
}
.hot canvas{image-rendering:pixelated;}
.hot.cool::after{
  content:''; position:absolute; inset:0;
  background:#000a;
}

/* ---------- konsola ---------- */
#console-wrap{
  border:3px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  background:var(--panel-lo);
  display:flex; flex-direction:column;
  flex:1;
  min-height:110px;
}
/* Pasek zakładek kanałów ([TD-225]). Przewija się w poziomie, bo kanałów
   przybywa w trakcie gry, a szerokość konsoli jest stała. */
#console-tabs{
  display:flex; gap:2px;
  padding:2px 3px 0;
  background:var(--panel);
  border-bottom:2px solid var(--bevel-lo);
  overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none;
  flex:0 0 auto;
}
#console-tabs::-webkit-scrollbar{display:none;}
.ctab{
  background:linear-gradient(#3f3a35,#2a2724);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  border-bottom:none;
  color:var(--ink-dim); font-family:var(--font); font-size:11px;
  padding:2px 8px; cursor:pointer; white-space:nowrap; flex:0 0 auto;
}
.ctab.on{background:linear-gradient(#5c5347,#463f38); color:var(--gold);}
/* Znak nieprzeczytanego ([TD-274]) — zakładka kanału, do którego przybył wiersz,
   gdy gracz czytał inny. Kolor jest ten, co w oryginale: „its tab … turns red
   indicating that there are messages not read yet". Gaśnie po wejściu w kanał. */
.ctab.unread{color:#ff5a5a;}
/* Krzyżyk kanału dokładanego ([TD-468]) — stałe dwa go nie mają.
   Podświetlenie pod kursorem stoi w bloku `@media (hover: hover)` niżej,
   razem z resztą — na dotyku przykleiłoby się po dotknięciu. */
.ctab-x{margin-left:6px; opacity:.55; font-size:12px; line-height:1;}
/* Kanał niewidoczny znika z układu — `#console` przewija tylko ten czytany. */
.console-page[hidden]{display:none;}
#console{
  flex:1;
  overflow-y:auto;
  padding:3px 5px;
  line-height:1.4;
  font-size:11.5px;
  scrollbar-width:thin;
  scrollbar-color:var(--panel-hi) var(--panel-lo);
}
#console::-webkit-scrollbar{width:10px;}
#console::-webkit-scrollbar-track{background:var(--panel-lo);}
#console::-webkit-scrollbar-thumb{background:var(--panel);border:1px solid var(--bevel-lo);}
#console div{word-wrap:break-word;}

.c-white  {color:#e8e2d4;}
.c-advance{color:#e8e2d4;}
.c-desc   {color:#6fdb6f;}
.c-info   {color:#8bd1ff;}
.c-green  {color:#6fdb6f;}
.c-orange {color:#e0973a;}
.c-red    {color:#ff5a5a;}
.c-yellow {color:#ffe36b;}
.c-say    {color:#ffe36b;}
/* Własne zdanie do NPC-a ([TD-276]) — ten sam kolor, co zwykła mowa; różni je
   wyłącznie kanał, w którym stoi. */
.c-say-npc{color:#ffe36b;}
.c-npc    {color:#5ad0ff;}
/* Cudza rozmowa z NPC-em podsłuchana obok ([TD-678]) — ten sam kolor, co
   własna, bo to dalej mowa NPC-a; różni je wyłącznie to, że nie zabiera
   graczowi zakładki, którą sobie ustawił. */
.c-npc-near{color:#5ad0ff;}
/* Rozmowa prywatna ([TD-422]) — kolor z oryginału (`SpeakTypesSettings.private`
   w `modules/game_console/console.lua`: `#5FF7F7`). */
.c-private{color:#5ff7f7;}
/* Kanał gildii ([TD-424]) — zieleń, jak w oryginale, gdzie mowa na kanale
   gildii ma własny kolor odróżniający ją od rozmowy dookoła postaci. */
.c-guild{color:#7ad07a;}
.c-loot   {color:#c8a2ff;}
.c-dim    {color:#8d8571;}

#chat-row{
  display:flex; align-items:center; gap:4px;
  border-top:2px solid var(--bevel-lo);
  padding:2px 4px;
  background:var(--panel);
}
/* Przełącznik trybu mowy ([TD-226]). Wygląda jak dawna etykieta — złoty
   napis przy polu — ale kliknięcie coś robi, więc dostaje kursor wskazujący
   i podświetlenie pod myszą. Szerokość jest stała, żeby pole czatu nie
   przeskakiwało w bok przy każdej zmianie trybu. */
#chat-mode{
  color:var(--gold); font-size:11px; white-space:nowrap;
  background:none; border:none; padding:0 2px; margin:0;
  font-family:var(--font); cursor:pointer;
  min-width:58px; text-align:left;
}
#chat-mode.yell{color:#ff8f5a;}
#chat-mode.whisper{color:#9fd6ff;}
#chat-input{
  flex:1;
  background:#191817;
  border:1px solid var(--bevel-lo);
  color:#e8e2d4;
  font-family:var(--font);
  font-size:12px;
  padding:2px 4px;
  outline:none;
}
#chat-input:focus{border-color:var(--gold);}

/* ---------- sidebar ---------- */
#sidebar{
  width:212px;
  flex:0 0 212px;
  display:flex;
  flex-direction:column;
  gap:4px;
  overflow-y:auto;
  scrollbar-width:thin;
  scrollbar-color:var(--panel-hi) var(--panel-lo);
}
#sidebar::-webkit-scrollbar{width:8px;}
#sidebar::-webkit-scrollbar-thumb{background:var(--panel);}

.panel{
  background:var(--panel);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  flex:0 0 auto;
}
.panel.grow{flex:1 1 auto; min-height:120px; display:flex; flex-direction:column;}
.panel.grow .panel-b{flex:1; overflow-y:auto;}

.panel-h{
  background:linear-gradient(#4f4842,#332f2b);
  border-bottom:1px solid var(--bevel-lo);
  padding:2px 6px;
  font-size:11px;
  color:var(--gold);
  letter-spacing:.5px;
  display:flex; justify-content:space-between; align-items:center;
}
.panel-b{padding:4px;}
.panel-b.center{display:flex; justify-content:center;}

.mini-btn{
  background:var(--panel-lo); color:var(--ink);
  border:1px solid var(--bevel-lo);
  width:16px; height:14px; line-height:1;
  cursor:pointer; font-family:var(--font); font-size:11px;
}

#minimap{
  image-rendering:pixelated;
  border:2px solid var(--bevel-lo);
  cursor:pointer;
  background:#000;
}

/* ---------- paski ---------- */
.bar{
  position:relative;
  height:15px;
  background:#141312;
  border:1px solid var(--bevel-lo);
  margin-bottom:3px;
  overflow:hidden;
}
.bar-fill{height:100%; width:100%; transition:width .18s linear;}
.hp-bar .bar-fill{background:linear-gradient(#e04a4a,var(--hp));}
.mp-bar .bar-fill{background:linear-gradient(#5a8bff,var(--mp));}
.xp-bar .bar-fill{background:linear-gradient(#e8d45a,var(--xp));}
.bar-txt{
  position:absolute; inset:0;
  text-align:center; line-height:13px;
  font-size:10.5px; color:#fff;
  text-shadow:1px 1px 0 #000, -1px 0 0 #000;
}

#cond-row{display:flex; gap:3px; flex-wrap:wrap; min-height:0;}
.cond{
  width:18px;height:18px;
  border:1px solid var(--bevel-lo);
  display:flex;align-items:center;justify-content:center;
  font-size:11px;
  background:var(--slot);
}

/* ---------- przyciski ---------- */
.btn-row{display:flex; gap:3px; margin-bottom:3px; align-items:center;}
.tgl,.wbtn{
  background:linear-gradient(#4f4842,#332f2b);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--ink);
  font-family:var(--font);
  font-size:12px;
  cursor:pointer;
  padding:2px 4px;
}
.tgl{width:26px; height:22px;}
.wbtn{flex:1; font-size:11px; height:20px;}
.tgl.on{
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  background:#5c5347; color:var(--gold);
}
.sep{width:6px;}

/* ---------- lista bitwy ---------- */
#battle-list{max-height:118px; overflow-y:auto;}
.bl-row{
  display:flex; align-items:center; gap:4px;
  padding:1px 2px; cursor:pointer;
}
.bl-row.target{background:#5a1a1a; outline:1px solid #ff5a5a;}
.bl-row canvas{image-rendering:pixelated; flex:0 0 auto;}
.bl-info{flex:1; min-width:0;}
.bl-name{font-size:10.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.bl-hp{height:4px; background:#141312; border:1px solid #000;}
.bl-hp i{display:block; height:100%; background:#3fbf3f;}
.empty-note{color:var(--ink-dim); font-size:10.5px; padding:4px; text-align:center;}

/* ---------- ekwipunek ---------- */
#equipment{
  display:grid;
  grid-template-columns:repeat(3,38px);
  gap:3px;
  justify-content:center;
  margin-bottom:4px;
}
.eq-slot,.slot{
  width:38px;height:38px;
  background:var(--slot);
  border:2px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  position:relative;
  display:flex;align-items:center;justify-content:center;
}
.eq-feet{grid-column:2;}
.eq-slot::before{
  content:attr(data-ph);
  position:absolute;
  font-size:7.5px;
  color:#4d4740;
  pointer-events:none;
}
.eq-slot.has::before,.slot.has::before{display:none;}
.eq-slot.drop-ok,.slot.drop-ok{border-color:var(--gold);}

.item-grid{
  display:grid;
  grid-template-columns:repeat(4,38px);
  gap:3px;
  justify-content:center;
}
.slot::before{content:'';}

.item{
  width:100%;height:100%;
  display:flex;align-items:center;justify-content:center;
  cursor:grab;
  position:relative;
}
.item canvas{image-rendering:pixelated; pointer-events:none;}
.item .cnt{
  position:absolute; right:1px; bottom:0;
  font-size:9.5px; color:#fff;
  text-shadow:1px 1px 0 #000,-1px 0 0 #000;
  pointer-events:none;
}
#drag-ghost{
  position:fixed; z-index:200; pointer-events:none;
  opacity:.85; transform:translate(-16px,-16px);
}
#drag-ghost canvas{image-rendering:pixelated;}

#cap-row{
  display:flex;justify-content:space-between;
  font-size:10.5px;color:var(--ink-dim);
  padding:0 2px;
}
#gold-txt{color:var(--gold);}

/* ---------- menu kontekstowe ---------- */
#ctx-menu{
  position:fixed; z-index:210;
  background:var(--panel);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  min-width:110px;
  padding:2px;
}
#ctx-menu div{
  padding:2px 8px; cursor:pointer; font-size:11.5px;
}
#ctx-menu hr{border:none;border-top:1px solid var(--bevel-lo);margin:2px 0;}

/* ---------- okna modalne ---------- */
.win{
  position:fixed;
  background:var(--panel);
  border:3px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  z-index:100;
  min-width:240px;
  box-shadow:0 6px 24px #000a;
  display:flex; flex-direction:column;
  max-height:88vh;
}
.win-h{
  background:linear-gradient(#5b534a,#38332e);
  border-bottom:1px solid var(--bevel-lo);
  padding:3px 6px;
  color:var(--gold);
  cursor:move;
  display:flex; justify-content:space-between; align-items:center;
  flex:0 0 auto;
}
.win-x{cursor:pointer; color:var(--ink); padding:0 3px;}
.win-b{padding:8px; overflow-y:auto; flex:1;}

/* ---------- okna zadokowane: pojemniki w prawej kolumnie ([TD-231]) ---------- */
/* Reguła jest jedna i przecząca: `position:static` zamiast `fixed`, bez
   `left`, `top` i `z-index`. Okno bez współrzędnych nie ma jak zasłonić kadru
   mapy — układa je kolumna `#sidebar`, a ta jest osobną kolumną `#app`.
   Pilnuje tego `test/ui-dock.test.js`; `.win.docked{position:fixed}` byłoby
   powrotem dokładnie do wady, którą ta sekcja zamyka. */
#cont-dock{display:flex; flex-direction:column; gap:4px; flex:0 0 auto;}
#cont-dock:empty{display:none;}
.win.docked{
  position:static;
  width:auto; min-width:0;
  max-height:none;
  box-shadow:none;
  border-width:2px;
  flex:0 0 auto;
}
/* Nagłówka nie ma dokąd przeciągać — `windows.js` nie podpina tam gestu. */
.win.docked .win-h{cursor:default;}
/* Własny pasek przewijania, tak jak w oryginale: trzeci otwarty pojemnik
   ma się zmieścić w kolumnie, a nie zepchnąć plecak poza ekran. */
.win.docked .win-b{padding:4px; max-height:172px;}

table.kv{width:100%; border-collapse:collapse; font-size:11.5px;}
table.kv td{padding:1px 3px;}
table.kv td:last-child{text-align:right; color:#e8e2d4;}
table.kv tr.hdr td{color:var(--gold); border-bottom:1px solid var(--bevel-lo); padding-top:6px;}
.skbar{height:5px;background:#141312;border:1px solid #000;margin-top:1px;}
.skbar i{display:block;height:100%;background:var(--xp);}

/* handel z NPC */
/* Okno pytania (`showAsk`) — zastąpiło natywny `prompt()`, [TD-136].
   Pole i przyciski w stylu ekranu wejścia, żeby to było widocznie okno gry,
   a nie dialog przeglądarki. */
.ask-in{
  width:100%; background:#191817; border:2px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  color:#e8e2d4; font-family:var(--font); font-size:13px; padding:4px 6px;
  outline:none; margin-top:5px;
}
.ask-in:focus{border-color:var(--gold);}
.ask-btns{display:flex;gap:4px;margin-top:8px;}

.trade-tabs{display:flex;gap:3px;margin-bottom:5px;}
.trade-tabs button{flex:1;}
.trade-list{max-height:260px;overflow-y:auto;}
.trade-row{
  display:flex;align-items:center;gap:6px;
  padding:2px;border-bottom:1px solid #00000040;
}
.trade-row canvas{image-rendering:pixelated;flex:0 0 auto;}
.trade-nm{flex:1;font-size:11px;}
.trade-pr{color:var(--gold);font-size:11px;}
/* Cena z obietnicy NPC, nie z cennika ([TD-62]) — wyróżniona, bo różni się
   od tego, co ten sam wiersz pokazuje reszcie świata. */
.trade-pr.promised{color:#7fe07f;font-weight:bold;}
.trade-row button{
  background:linear-gradient(#4f4842,#332f2b);
  border:1px solid var(--bevel-lo);color:var(--ink);
  cursor:pointer;font-family:var(--font);font-size:11px;padding:1px 6px;
}
.trade-row.dis{opacity:.45;}
/* Podpis klawisza w oknie skrótów ([TD-227]). Stała szerokość, żeby nazwy
   czarów zaczynały się w jednej kolumnie mimo „Shift+F1" obok „F9". */
.hk-key{flex:0 0 62px;color:var(--gold);font-size:11px;}

/* ---------- tworzenie postaci ---------- */
/* Ekran logowania (8.6) dzieli tło i pudełko z ekranem tworzenia postaci —
   to ta sama scena, tylko o krok wcześniej. */
#creation, #login{
  position:fixed; inset:0;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(ellipse at 50% 30%, #2e2a22, #090807 75%);
  z-index:300;
  overflow:auto;
}
#login.hidden{display:none;}
.lg-alt{display:flex; justify-content:center; gap:14px; margin-top:8px;}
.lnk-btn{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:var(--font); font-size:10.5px; color:var(--ink);
  text-decoration:underline; text-underline-offset:2px;
}
.lnk-btn:disabled{opacity:.4; cursor:default;}
.cr-msg{
  margin-top:10px; padding:6px 8px; font-size:11px; line-height:1.4;
  color:#bcd8a8; background:rgba(40,90,30,.24); border-left:3px solid #4a7a32;
}
.cr-box{
  width:440px;
  background:var(--panel);
  border:3px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  padding:18px 22px 14px;
  text-align:center;
}
.cr-box h1{
  font-size:30px; color:var(--gold); letter-spacing:5px;
  text-shadow:2px 2px 0 #000; font-weight:normal;
}
.cr-box h1 span{color:#8a7a52; font-size:20px;}
.cr-sub{color:var(--ink-dim); font-size:11px; margin:2px 0 14px;}
.cr-lbl{display:block; text-align:left; color:var(--gold); font-size:11px; margin:10px 0 3px;}
/* Pola ekranu wejścia — imię postaci i (od 8.6) konto platformy. Wspólna reguła,
   bo to ta sama scena; osobne dawały pola w domyślnej bieli przeglądarki. */
#cr-name, #login input[type=email], #login input[type=password]{
  width:100%; background:#191817; border:2px solid;
  border-color:var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
  color:#e8e2d4; font-family:var(--font); font-size:14px; padding:4px 6px; outline:none;
}
#cr-name:focus, #login input:focus{border-color:var(--gold);}
/* Kafelków profesji nie ma od [TD-427] — profesję nadaje Wyrocznia w grze,
   a nie formularz tworzenia postaci. Razem z nimi zeszły reguły `#cr-vocs`,
   `.voc` i `#cr-voc-desc`: styl bez elementu jest martwym kodem. */
#cr-outfit{display:flex; align-items:center; gap:14px; justify-content:center;}
#cr-preview{image-rendering:pixelated; background:#1a1917; border:2px solid var(--bevel-lo);}
#cr-colors{display:grid; grid-template-columns:repeat(9,16px); gap:3px;}
.swatch{width:16px;height:16px;border:1px solid #000;cursor:pointer;}
.swatch.on{outline:2px solid var(--gold);}
/* Okno wyglądu ([TD-419]) — podgląd nad paletą, paleta w pięciu kolumnach
   jak na ekranie tworzenia postaci. Próbka „bez koloru" jest przekreślona,
   bo pusty kwadrat na ciemnym tle nie różniłby się od dziury w układzie. */
.outfit-preview{display:flex;justify-content:center;padding:4px 0 8px;}
.outfit-colors{display:grid;grid-template-columns:repeat(5,16px);gap:6px;justify-content:center;}
.swatch-none{background:linear-gradient(135deg,#2a2620 45%,#8a8276 45%,#8a8276 55%,#2a2620 55%);}
html[data-touch="1"] .outfit-colors{grid-template-columns:repeat(5,44px);}
.cr-actions{display:flex; gap:8px; margin-top:16px;}
.big-btn{
  flex:1;
  background:linear-gradient(#6a5f4e,#3d372f);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--gold); font-family:var(--font); font-size:14px;
  padding:8px; cursor:pointer;
}
.big-btn.alt{color:var(--ink); font-size:12px;}
.big-btn:disabled{opacity:.4; cursor:default;}
.cr-foot{margin-top:12px; font-size:9.5px; color:#6b645a; line-height:1.4;}
.cr-err{
  margin-top:10px; padding:6px 8px; font-size:11px; line-height:1.4;
  color:#ff9a9a; background:rgba(120,20,20,.28); border-left:3px solid #a02a2a;
}
/* Zapowiedź nowej wersji na ekranach wejścia ([TD-500]). Ton złoty, nie
   czerwony: to nie jest błąd gracza ani awaria, tylko powód, dla którego gra
   może się zachowywać dziwnie — i jeden przycisk, który go usuwa. */
.cr-update{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-top:10px; padding:6px 8px; font-size:11px; line-height:1.4;
  color:var(--gold); background:rgba(120,95,25,.24); border-left:3px solid #8a7a52;
  text-align:left;
}
.cr-update .lnk-btn{color:var(--gold); flex:none;}
#cr-logout{display:block; margin:12px auto 0;}

/* lista postaci konta — ekran wyboru (zadanie 8.7) */
#cr-chars{display:flex; flex-direction:column; gap:4px; margin-top:4px; max-height:220px; overflow-y:auto;}
.cr-empty{font-size:11px; color:var(--ink-dim); text-align:left; margin:4px 0;}
.cr-char-row{display:flex; gap:4px; align-items:stretch;}
.cr-char-btn{
  flex:1; text-align:left;
  background:linear-gradient(#4f4842,#332f2b);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--ink); cursor:pointer; padding:6px 8px;
  font-family:var(--font); font-size:12px;
}
/* utrata połączenia i — od zadania 8.1 — jego wznawianie */
#disconnected, #resuming{
  position:fixed; inset:0; z-index:9000;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:12px;
  background:rgba(8,7,6,.92); text-align:center; padding:20px;
}
#disconnected h2, #resuming h2{color:var(--gold); font-size:18px; font-weight:normal;}
#disconnected p, #resuming p{color:var(--ink-dim); font-size:12px;}
#disconnected .big-btn{flex:0 0 auto; min-width:200px;}
/* zasłona wznawiania jest lżejsza: gra nie skończyła się, tylko czeka */
#resuming{background:rgba(8,7,6,.78);}

/* pomoc */
.help-b h3{color:var(--gold);font-size:12px;margin:10px 0 3px;font-weight:normal;}
.help-b p, .help-b li{font-size:11.5px;line-height:1.5;}
.help-b ul{margin-left:16px;}
.help-b kbd{
  background:#191817;border:1px solid var(--bevel-hi);
  padding:0 4px;color:var(--gold);font-size:11px;
}

/* ekran śmierci */
#death-veil{
  position:fixed; inset:0; background:#300000; opacity:0;
  pointer-events:none; z-index:90; transition:opacity .4s;
}
#death-veil.on{opacity:.55;}

@media (max-width:1150px){
  #sidebar{width:190px;flex:0 0 190px;}
  #equipment{grid-template-columns:repeat(3,34px);}
  .eq-slot,.slot{width:34px;height:34px;}
  .item-grid{grid-template-columns:repeat(4,34px);}
}

/* ============================================================
   PODŚWIETLENIA POD KURSOREM  ([DEC-256])
   ============================================================

   Wszystkie reguły `:hover` z tego arkusza stoją tutaj, w jednym bloku,
   i to jest jedyne miejsce, w którym wolno ich szukać.

   Powód nie jest porządkowy. Na ekranie dotykowym `:hover` **zapala się przy
   dotknięciu i zostaje zapalony** aż do dotknięcia czegoś innego — przeglądarka
   nie ma jak zgasić stanu, który opisuje kursor, skoro kursora nie ma. Skutkiem
   jest złota ramka przyklejona do ostatnio dotkniętego slotu i wiersz listy
   bitwy udający zaznaczony. Zapytanie `(hover: hover)` pyta dokładnie o to,
   czy urządzenie w ogóle umie najechać, a nie o rozmiar ekranu — więc laptop
   z ekranem dotykowym podświetlenia zachowuje, a telefon ich nie dostaje.

   Zebranie ich w jeden blok zamiast dwunastu osobnych `@media` ma drugi powód:
   przeoczenie jednej reguły daje przyklejony stan na dotyku, a przeniesienie
   o jeden nawias za daleko gasi podświetlenia **na desktopie** i nikt tego nie
   zauważy. Jeden blok jest sprawdzalny jednym strażnikiem (`test/css-touch.test.js`). */
@media (hover: hover){
  .hot:hover{border-color:var(--gold);}
  .mini-btn:hover{color:var(--gold);}
  .tgl:hover,.wbtn:hover{color:var(--gold);}
  .bl-row:hover{background:#00000040;}
  #ctx-menu div:hover{background:#5c5347; color:var(--gold);}
  .win-x:hover{color:#ff5a5a;}
  .ctab-x:hover{opacity:1; color:var(--gold);}
  .trade-row:hover{background:#00000040;}
  .trade-row button:hover{color:var(--gold);}
  .lnk-btn:hover{color:var(--gold);}
  .big-btn:hover{background:linear-gradient(#7d7059,#4a4238);}
  .cr-char-btn:hover{color:var(--gold); border-color:var(--gold);}
  #chat-mode:hover{color:#fff;}
}

/* Potwierdzenie naciśnięcia. Do tej zmiany cały arkusz nie miał ani jednej
   reguły `:active` — na myszy uchodziło to płazem, bo rolę potwierdzenia grał
   hover. Po zdjęciu hovera z dotyku nie zostałoby **nic**: gracz naciska
   i nie wie, czy trafił. */
.tgl:active,.wbtn:active,.mini-btn:active,.big-btn:active,.lnk-btn:active,
.tbtn:active,.abtn:active,.dtab:active,.hot:active,.trade-row button:active,#chat-mode:active{
  filter:brightness(1.45);
}
.bl-row:active,#ctx-menu div:active,.cr-char-btn:active{background:#5c5347;}

/* ============================================================
   HIGIENA DOTYKU
   ============================================================ */

html,body{
  /* Gest przeciągnięcia palcem po grze nie może odświeżać strony ani odbijać
     jej sprężyście od krawędzi — w obu wypadkach gracz traci rozpoczęty ruch. */
  overscroll-behavior:none;
  -webkit-tap-highlight-color:transparent;
}
#app{
  /* `100dvh`, nie `100vh`: w karcie przeglądarki `vh` liczy się do wysokości
     **bez** chowającego się paska adresu, więc dolny pasek akcji wychodziłby
     poza ekran dokładnie do chwili przewinięcia — którego w tej grze nie ma. */
  height:100dvh;
  /* Wcięcie ekranu i pasek gestów. Działa wyłącznie razem z `viewport-fit=cover`
     w znaczniku `viewport` (`index.html`). */
  padding:calc(6px + env(safe-area-inset-top)) calc(6px + env(safe-area-inset-right))
          calc(6px + env(safe-area-inset-bottom)) calc(6px + env(safe-area-inset-left));
}
#game,#overlay,#viewport{
  /* Kadr obsługujemy sami: bez tego przeglądarka zabiera gest na przewijanie
     i podwójne stuknięcie, a długie przytrzymanie kończy się systemową lupą
     zaznaczania zamiast menu pola. `-webkit-touch-callout` jest potrzebne
     OSOBNO od `user-select` — na iOS lupa wychodzi mimo niego. */
  touch-action:none;
  -webkit-touch-callout:none;
}
/* Elementy przewijane zatrzymują przewijanie u siebie i przyjmują wyłącznie
   ruch w pionie — inaczej przeciągnięcie rzeczy z plecaka w bok bywa czytane
   jako przewijanie panelu i przedmiot zostaje w miejscu. */
#sidebar,#console,#battle-list,.win-b,.trade-list,#cr-chars{
  overscroll-behavior:contain;
  touch-action:pan-y;
}

/* Nowe elementy dotykowe nie istnieją, dopóki profil nie powie, że jest dotyk.
   Sterowanie idzie z atrybutów `data-ui` / `data-touch` na `<html>`, które
   wpisuje `uiProfile` — jedna reguła, jedno źródło.

   UWAGA przy dopisywaniu tu czegokolwiek: element schowany tą listą i **nie**
   przywrócony niżej jest niewidoczny na każdym urządzeniu, a jego przycisk
   dalej się zapala — czyli funkcja wygląda na działającą i nie działa nigdzie.
   Pilnuje tego `test/css-touch.test.js` („każdy element schowany domyślnie
   wraca w trybie dotykowym"); lista poniżej i lista przywracająca muszą się
   zgadzać co do sztuki. */
#hud-top,#hud-bars,#touch-actions,#drawer-tabs,#carry-bar,#dpad,#press-ring,
#chat-send,#chat-hide{display:none;}

/* ============================================================
   TRYB DOTYKOWY — wspólne dla telefonu i tabletu
   ============================================================

   Rozmiary celów rosną do 44 px. To nie jest zaokrąglenie w górę „dla wygody":
   opuszka palca ma około 9 mm, a `.mini-btn` mierzy dziś 16 × 14 px i przy
   dwóch przyciskach obok siebie trafienie w zamierzony jest kwestią szczęścia. */
/* Sterowanie dotykowe należy do **każdego** urządzenia dotykowego, nie tylko
   do telefonu: tablet dostaje z profilu `touch: true`, więc gesty, progi
   i odmowa budzenia klawiatury już go obowiązują. Gdyby przyciski zostały
   bramkowane samym telefonem, tablet miałby zachowanie dotykowe bez interfejsu
   do niego — czat nie do otwarcia (bo `⌨` niewidoczne) i rzecz wzięta „do ręki"
   bez paska mówiącego, że się ją trzyma. Szuflada zostaje przy telefonie
   osobno (niżej): na tablecie panel boczny mieści się obok kadru. */
html[data-touch="1"] #hud-top,
html[data-touch="1"] #touch-actions{display:flex;}
html[data-touch="1"] #carry-bar:not(.hidden){display:flex;}
html[data-touch="1"] #chat-send,
html[data-touch="1"] #chat-hide{display:block;}
/* Krzyżak i pierścień długiego przytrzymania są nakładkami na kadrze i chowa
   je klasa `hidden`, którą zdejmuje skrypt — ale bez tej reguły zostawały
   niewidoczne mimo zdjętej klasy, bo pasowały do listy domyślnej wyżej. */
html[data-touch="1"] #dpad:not(.hidden),
html[data-touch="1"] #press-ring:not(.hidden){display:block;}

html[data-touch="1"] .tgl{width:44px;height:44px;font-size:18px;}
html[data-touch="1"] .wbtn{height:40px;font-size:12px;}
html[data-touch="1"] .mini-btn{width:44px;height:44px;font-size:16px;}
html[data-touch="1"] .win-x{padding:6px 12px;font-size:16px;}
/* Pasek zakładek konsoli na dotyku ([TD-567]). Krzyżyk jest tu **jedyną**
   drogą zamknięcia kanału ([DEC-375]) — `Ctrl+E` na telefonie nie istnieje —
   a siedzi **w** zakładce, tuż przy jej napisie. Bez własnego pola i odstępu
   cel zamykający przykleja się do przełączającego: gracz celujący w zakładkę,
   żeby ją przeczytać, trafia o kilka pikseli w prawo i zamiast przełączyć —
   zamyka. Rozmiar krzyżyka jak w bliźniaczym `.win-x` niżej, bo to ten sam
   gest na tym samym urządzeniu; prawy odstęp zakładki oddaje mu `padding`,
   żeby pole krzyżyka nie wystawało poza jej ramkę. */
html[data-touch="1"] .ctab{min-height:44px;font-size:13px;padding:2px 4px 2px 12px;}
html[data-touch="1"] .ctab-x{margin-left:12px;padding:6px 12px;font-size:16px;}
html[data-touch="1"] #ctx-menu{min-width:200px;}
html[data-touch="1"] #ctx-menu div{padding:12px 14px;font-size:14px;}
html[data-touch="1"] .bl-row{padding:7px 4px;}
html[data-touch="1"] .bl-name{font-size:13px;}
html[data-touch="1"] .trade-row{padding:8px 2px;}
html[data-touch="1"] .trade-row button{padding:9px 12px;font-size:13px;}
html[data-touch="1"] .lnk-btn{padding:10px 6px;font-size:13px;}
html[data-touch="1"] .cr-char-btn{padding:12px 10px;font-size:14px;}
/* Dziewięć próbek koloru w jednym rzędzie znaczyło na telefonie 30 px na
   próbkę — sąsiadujące cele tej wielkości trafia się co drugi raz. Pięć
   kolumn po 44 px mieści się w 375 px i daje dwa rzędy zamiast jednego. */
html[data-touch="1"] .swatch{width:44px;height:44px;}
html[data-touch="1"] #cr-colors{grid-template-columns:repeat(5,44px);}
/* Ikony stanów są **wskaźnikiem**, nie celem — nic się po nich nie klika,
   więc rosną tylko na tyle, żeby dało się je odczytać. */
html[data-touch="1"] .cond{width:30px;height:30px;font-size:16px;}
/* Ekran wejścia był sztywnym pudełkiem 440 px — na telefonie 390 px wystawał
   poza ekran razem z przyciskiem „Wejdź do świata". */
html[data-touch="1"] .cr-box{width:auto;max-width:440px;margin:0 10px;}
html[data-touch="1"] #creation,html[data-touch="1"] #login{
  padding:env(safe-area-inset-top) 0 env(safe-area-inset-bottom);
}
html[data-touch="1"] #chat-input{font-size:16px;padding:8px 6px;}
html[data-touch="1"] .ask-in{font-size:16px;padding:10px 8px;}

/* Przyciski dotykowe: pasek górny, czat, pasek przenoszenia. */
.tbtn{
  min-width:44px;height:44px;
  background:linear-gradient(#4f4842,#332f2b);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--ink); font-family:var(--font); font-size:16px;
  cursor:pointer; padding:0 8px; flex:0 0 auto;
}
.tbtn.wide{flex:1;font-size:13px;}
.tbtn.on{background:#5c5347; color:var(--gold); border-color:var(--gold);}

#hud-top{
  align-items:center; gap:6px; flex:0 0 auto;
  background:var(--panel-lo);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  padding:3px 6px; min-height:44px;
}
#hud-name{color:var(--gold); font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.hud-gap{flex:1;}

/* Paski życia i many wjeżdżają tu na telefonie (`#bars-home` → `#hud-bars`).
   Zdejmujemy z sekcji ramkę panelu: to nie jest już panel, tylko pasek stanu. */
#hud-bars{flex:0 0 auto;}
#hud-bars .panel{border:none;background:none;}
#hud-bars .panel-b{padding:0;}
#hud-bars .bar{height:20px;}
#hud-bars .bar-txt{line-height:18px;font-size:12px;}

#touch-actions{
  align-items:center; justify-content:space-between; gap:4px;
  flex:0 0 auto; padding:3px 2px;
}
.abtn{
  flex:1; height:50px;
  background:linear-gradient(#4f4842,#332f2b);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--ink); font-family:var(--font); font-size:21px;
  cursor:pointer; padding:0;
}
/* Tryb jednorazowy zapalony — gracz musi widzieć, że następne dotknięcie
   znaczy co innego niż zwykle. */
.abtn.on{background:#6a5f4e; color:var(--gold); border-color:var(--gold);}
.abtn-sep{width:8px;flex:0 0 auto;}

#drawer-tabs{
  gap:3px; flex:0 0 auto; padding-top:3px;
}
.dtab{
  flex:1; height:44px;
  background:linear-gradient(#4f4842,#332f2b);
  border:2px solid;
  border-color:var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
  color:var(--ink); font-family:var(--font); font-size:12px; cursor:pointer;
}
.dtab.on{background:#5c5347; color:var(--gold); border-color:var(--gold);}

#carry-bar{
  align-items:center; gap:5px; flex:0 0 auto;
  background:#3a3226; border:2px solid var(--gold);
  padding:4px 5px;
}
#carry-what{flex:0 0 auto; color:var(--gold); font-size:12px; max-width:38%;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}

/* Krzyżak i pierścień długiego przytrzymania — obie nakładki leżą na kadrze. */
#dpad{
  position:absolute; left:6px; bottom:6px;
  width:126px; height:126px; border-radius:50%;
  background:radial-gradient(circle, rgba(90,84,76,.42), rgba(20,19,18,.42));
  border:2px solid rgba(216,178,90,.45);
  z-index:8; touch-action:none;
}
#dpad-knob{
  position:absolute; left:50%; top:50%;
  width:46px; height:46px; margin:-23px 0 0 -23px; border-radius:50%;
  background:rgba(216,178,90,.55); border:2px solid #0008;
  pointer-events:none;
}
#press-ring{
  position:absolute; width:54px; height:54px; margin:-27px 0 0 -27px;
  border-radius:50%; pointer-events:none; z-index:9;
  border:3px solid rgba(216,178,90,.85);
  /* Pierścień „domyka się" wraz z upływem progu: `--p` (0…1) ustawia skrypt. */
  background:conic-gradient(rgba(216,178,90,.35) calc(var(--p,0) * 360deg), transparent 0);
}

/* ============================================================
   TELEFON — układ pionowy i poziomy
   ============================================================ */

html[data-ui^="phone"] body{overflow:hidden;}
html[data-ui^="phone"] #app{
  display:flex; flex-direction:column; gap:3px;
  padding-top:calc(3px + env(safe-area-inset-top));
  padding-bottom:calc(3px + env(safe-area-inset-bottom));
}
/* Zakładki szuflady są jedynym elementem dotykowym wyłącznie telefonowym:
   na tablecie panel boczny zostaje na swoim miejscu, więc nie ma czego chować. */
html[data-ui^="phone"] #drawer-tabs{display:flex;}
/* Blok, nie flex: sekcja pasków to jedyne dziecko i ma zająć całą szerokość.
   Jako element flex zwijała się do zawartości, czyli do dwóch pikseli. */
html[data-ui^="phone"] #hud-bars{display:block;}

/* Kadr przestaje być rozmiarem kanwy, a staje się przydzielonym prostokątem:
   `resize` mierzy go i dopiero z pomiaru liczy skalę (`stretchScale`).
   Kanwy są w środku wyśrodkowane i **nie** wpływają na jego rozmiar —
   inaczej pomiar karmiłby sam siebie. */
html[data-ui^="phone"] #viewport{
  /* `1 1 0`, a nie `1 1 auto`: przy podstawie `auto` rozmiar liczyłby się
     z zawartości, czyli z kanwy — a kanwa dostaje rozmiar z pomiaru tego
     właśnie elementu. Pomiar karmiłby wtedy sam siebie i skala pełzłaby
     przy każdej zmianie rozmiaru okna. */
  flex:1 1 0; min-height:0; align-self:stretch;
  overflow:hidden; border-width:2px;
}
/* Obie kanwy wyśrodkowane bezwzględnie i tym samym przekształceniem. Mają
   identyczne rozmiary (ustawia je `Renderer.setScale`), więc warstwa napisów
   trafia dokładnie na świat. Bezwzględne, bo inaczej wróciłyby do rozmiaru
   `#viewport` i pomiar znów byłby błędnym kołem. */
html[data-ui^="phone"] #game,
html[data-ui^="phone"] #overlay{
  position:absolute; inset:auto; left:50%; top:50%; transform:translate(-50%,-50%);
}
html[data-ui^="phone"] .game-col{flex:1 1 0; min-height:0; min-width:0; gap:3px;}

/* Konsola na telefonie jest niska z rozmysłu: log jest do zerkania, a nie do
   czytania, i każdy jego wiersz zabiera miejsce kadrowi. */
/* Kadr ma **stałe proporcje** 15 × 11 kafelków, więc rozciąganie go na całą
   wolną wysokość dawało czarne pasy nad i pod światem, a log tracił miejsce,
   którego i tak nie widać. `aspect-ratio` oddaje kadrowi dokładnie tyle
   wysokości, ile wynika z szerokości — resztę bierze log.
   Sufit `58dvh` jest dla telefonów niskich i szerokich: tam proporcja
   kazałaby kadrowi zjeść cały ekran razem z paskiem akcji. */
html[data-ui="phone-portrait"] #viewport{
  flex:0 0 auto; aspect-ratio:480 / 352; width:100%; max-height:58dvh;
}
html[data-ui="phone-portrait"] #console-wrap{flex:1 1 0; min-height:64px;}
html[data-ui="phone-portrait"] #console{font-size:12px;}
/* Szesnaście slotów ([TD-227]) na szerokość telefonu się nie mieści, więc
   pasek zawija się na dwa rzędy — po jednym na rząd klawiszy. `nowrap`
   ścisnąłby slot do kilku pikseli i palec nie trafiłby w żaden. */
html[data-ui="phone-portrait"] #hotbar{gap:3px; flex-wrap:wrap; justify-content:space-between;}
html[data-ui="phone-portrait"] .hot{width:auto; flex:1 0 10%; height:40px;}

/* W poziomie kadr jest szeroki, a wysokości brakuje: log wchodzi na kadr jako
   półprzezroczysta nakładka, a nie własny pas. Nie przechwytuje dotknięć —
   pod nim dalej jest mapa. */
html[data-ui="phone-landscape"] #app{flex-direction:row; align-items:stretch;}
html[data-ui="phone-landscape"] #hud-top{
  flex-direction:column; min-height:0; width:52px; padding:4px 3px;
}
html[data-ui="phone-landscape"] #hud-name{display:none;}
html[data-ui="phone-landscape"] .game-col{flex:1 1 auto; min-width:0;}
html[data-ui="phone-landscape"] #console-wrap{
  /* Log jako nakładka na dole kadru, a nie własny pas: w poziomie brakuje
     wysokości, a przepuszcza dotknięcia, więc pod nim dalej jest mapa.
     Kończy się nad paskiem skrótów, żeby go nie przykrywać. */
  position:absolute; left:0; right:0; bottom:46px; height:76px;
  border:none; background:linear-gradient(rgba(20,19,18,0), rgba(20,19,18,.82) 40%);
  pointer-events:none; z-index:7;
}
/* Paski życia i many na górnej krawędzi kadru — w pasie własnym nachodziłyby
   na nakładkę logu, a w walce to jedyna rzecz, na którą gracz patrzy. */
html[data-ui="phone-landscape"] #hud-bars{
  position:absolute; left:0; right:0; top:0; z-index:7;
  padding:2px 4px;
  background:linear-gradient(rgba(20,19,18,.85), rgba(20,19,18,0));
}
html[data-ui="phone-landscape"] #hud-bars .bar{height:16px; margin-bottom:2px;}
html[data-ui="phone-landscape"] #hud-bars .bar-txt{line-height:14px; font-size:10.5px;}
html[data-ui="phone-landscape"] #hud-bars .xp-bar,
html[data-ui="phone-landscape"] #hud-bars #cond-row{display:none;}
html[data-ui="phone-landscape"] #chat-row{pointer-events:auto;}
html[data-ui="phone-landscape"] #console{font-size:11.5px;}
html[data-ui="phone-landscape"] .game-col{position:relative;}
html[data-ui="phone-landscape"] #touch-actions{
  flex-direction:column; width:56px; padding:2px;
}
html[data-ui="phone-landscape"] .abtn{height:auto; flex:1; width:100%;}
html[data-ui="phone-landscape"] .abtn-sep{width:auto;height:6px;}
html[data-ui="phone-landscape"] #hotbar{flex-wrap:wrap;}
html[data-ui="phone-landscape"] .hot{width:auto;flex:1 0 10%;height:34px;}
html[data-ui="phone-landscape"] #drawer-tabs{
  flex-direction:column; width:60px; padding:0 0 0 3px;
}
html[data-ui="phone-landscape"] .dtab{height:auto;flex:1;font-size:11px;}

/* ---------- szuflada ---------- */
/*
   Panel boczny na telefonie nie mieści się obok kadru: 212 px z 390 px to 54%
   szerokości, a kanwa i tak nie miałaby gdzie się schować, bo strona nie
   przewija się (`overflow:hidden`). Zjeżdża więc pod dolną krawędź i wraca
   dotknięciem zakładki — z DOŁU, bo tam sięga kciuk, i **nie zasłaniając
   kadru**, bo gracz musi widzieć, na co patrzy, gdy przekłada rzeczy.
*/
html[data-ui^="phone"] #sidebar{
  position:fixed; left:0; right:0; bottom:0;
  width:auto; flex:none; max-height:58dvh;
  padding:5px 5px calc(56px + env(safe-area-inset-bottom));
  background:var(--panel-lo);
  border-top:3px solid var(--bevel-hi);
  box-shadow:0 -8px 24px #000a;
  z-index:60;
  transform:translateY(102%);
  transition:transform .18s ease-out;
}
html[data-ui^="phone"] #app[data-drawer] #sidebar{transform:translateY(0);}
/* Zakładka wybiera, który panel widać. Panel bez `data-tab` (żaden dziś taki
   nie jest) zostałby ukryty — to jest zamierzone, bo znaczyłoby, że ktoś dołożył
   panel i zapomniał powiedzieć, do której zakładki należy. */
html[data-ui^="phone"] #sidebar .panel{display:none;}
html[data-ui^="phone"] #app[data-drawer="plecak"] #sidebar .panel[data-tab="plecak"],
html[data-ui^="phone"] #app[data-drawer="postac"] #sidebar .panel[data-tab="postac"],
html[data-ui^="phone"] #app[data-drawer="bitwa"]  #sidebar .panel[data-tab="bitwa"],
html[data-ui^="phone"] #app[data-drawer="mapa"]   #sidebar .panel[data-tab="mapa"]{display:block;}
html[data-ui^="phone"] #sidebar .panel.grow{display:none;}
html[data-ui^="phone"] #app[data-drawer="plecak"] #sidebar .panel.grow[data-tab="plecak"]{
  display:flex;
}
/* Szuflada stoi nad paskami akcji i zakładek, więc te muszą być nad nią. */
html[data-ui^="phone"] #drawer-tabs{position:relative; z-index:61;}
html[data-ui^="phone"] #touch-actions{position:relative; z-index:61;}

/* Sloty w szufladzie: 44 px zamiast 34 px z wariantu wąskiego okna. */
html[data-ui^="phone"] #equipment{grid-template-columns:repeat(3,44px);}
html[data-ui^="phone"] .eq-slot,html[data-ui^="phone"] .slot{width:44px;height:44px;}
html[data-ui^="phone"] .item-grid{grid-template-columns:repeat(4,44px);}
html[data-ui^="phone"] #minimap{width:100%;height:auto;max-width:220px;}

/* Okna pływające na telefonie zajmują szerokość ekranu i nie wychodzą poza
   niego — `createWindow` stawia je na stałych 280 px od lewej i 60 px od góry,
   co przy 390 px oznaczało okno wystające prawą krawędzią. */
html[data-ui^="phone"] .win:not(.docked){
  left:4px !important; right:4px !important; width:auto !important;
  max-height:74dvh;
}
html[data-ui="phone-landscape"] .win:not(.docked){max-height:88dvh;}

/* Pojemniki są częścią szuflady „Plecak" — i tylko jej. Bez tych dwóch reguł
   zadokowane okna wisiałyby w szufladzie pod każdą zakładką, bo `#cont-dock`
   nie jest `.panel` i reguła chowająca panele go nie dotyczy ([TD-231]). */
html[data-ui^="phone"] #cont-dock{display:none;}
html[data-ui^="phone"] #app[data-drawer="plecak"] #cont-dock{display:flex;}
html[data-ui^="phone"] .win-h{padding:8px 8px;}
