/* ==========================================================================
   Herní obrazovka, konzole nad polem a hrací pole

   Zásada: hrací pole je hrdina stránky. Všechno ovládání je stlačené
   do jediného tenkého pruhu nad ním, aby poli zbylo co nejvíc místa.
   ========================================================================== */

/* ---------------------------------------------------------------- konzole */
/* Zalomení platí na každé šířce, ne až na telefonu. Konzole nese čtyři až
   šest prvků, jejichž šířka závisí na motivu, na --ui i na tom, jestli je
   před startem vidět pole pro nastavení, přetečení se tím pádem nedá
   spolehlivě odhadnout dopředu. Když se všechno vejde, zalomení nic nedělá;
   když ne, spadne ovládání na druhý řádek místo ven z rámu. */
.console {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(8px * var(--ui));
  row-gap: calc(7px * var(--ui));
  width: 100%;
  max-width: max(var(--board-w), calc(320px * var(--ui)));
  padding: calc(7px * var(--ui)) calc(8px * var(--ui))
           calc(7px * var(--ui)) calc(7px * var(--ui));
  background-color: var(--surface);
  border: var(--hairline) solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
}

/* Tažené číslo je nejaktivnější prvek herní obrazovky: jílový přesvit,
   jílový obrys (--clay, výplňová varianta akcentu) a jílová číslice.

   Rámeček drží rozměr, ať v něm stojí cokoli. Popisek nad číslem se totiž
   za partii mění („tah“, „7. tah“, „12. číslo · žolík“) a s ním rostla
   i dlaždice: údaje vedle ní uskakovaly po každém čísle a na telefonu se
   celá konzole zalomila o řádek níž i s hracím polem pod sebou. Proto pevná
   šířka (ne spodní mez, tu by delší popisek přerostl), popisek useknutý,
   když se nevejde, a číslo přišpendlené k pravé hraně (space-between), aby
   neskákalo podle toho, jak dlouhý je zrovna popisek vlevo od něj.

   Dvě stě pixelů je nejdelší popisek ve všech třech jazycích i s rezervou
   na dvojciferné pořadí. Na telefonu pravidlo neplatí, tam si dlaždice bere
   místo, které zbylo po počítadlech (viz zlom 700 px v responsive.css). */
.console-draw {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex: none;
  gap: calc(8px * var(--ui));
  padding: calc(4px * var(--ui)) calc(12px * var(--ui));
  width: calc(200px * var(--ui));
  border-radius: var(--r-sm);
  background-color: var(--accent-soft);
  border: var(--hairline) solid var(--clay);
  transition: background-color var(--t-fast), border-color var(--t-fast);
}

/* Popisek se do rámečku vejde vždycky: co přeteče, se ustřihne. Radši
   useknutý konec než rozhozená konzole. */
.console-draw .console-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.console-draw.is-empty {
  background-color: var(--surface-2);
  border-color: var(--border);
}

.console-label {
  font-family: var(--label-font);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Šířka na dvě číslice: jednociferné číslo, pomlčka i hvězdička zabírají
   v rámečku stejné místo jako 54, takže se pravá hrana čísla nehýbe.
   Míra je v pixelech, ne v `ch`: `ch` se počítá z písma, které je zrovna
   nasazené, a při dostavení číslicového písma (font-display: swap) by se
   rezerva o pár pixelů změnila a konzole by s ní cukla. */
.console-draw-value {
  flex: none;
  min-width: calc(39px * var(--ui));
  text-align: right;
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: 1.875rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  letter-spacing: -0.02em;
}

/* Prázdný stav nesmí vzít --text-faint, ten je jílový a nenatažené číslo
   by vypadalo aktivně. Cloud-dark napřímo, v obou režimech čitelný. */
.console-draw.is-empty .console-draw-value {
  color: #87867f;                /* --swatch--cloud-dark */
}

.draw-pop {
  animation: drawPop 340ms cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes drawPop {
  0% {
    transform: scale(0.6);
    opacity: 0;
  }
  60% {
    transform: scale(1.1);
    opacity: 1;
  }
  100% {
    transform: scale(1);
  }
}

/* Roste do zbylého místa a smršťovat se smí, ale ne donekonečna: s původním
   `min-width: 0` se při plné konzoli stlačila na pár pixelů a z „Body“
   i „Políčka“ zbyly výseče písmen. Dokud se vejde tenhle základ, drží konzole
   jeden řádek; když ani on nezbyde, zalomí se ovládání pod něj.

   Hodnota je v pixelech, ne `min-content`: dva údaje se do 112px vždycky
   vejdou a přísnější mez lámala konzoli i tam, kde nemusela. Tabulka má
   konzoli jen 320px a `min-content` na ní o pár pixelů přehodil Vymazat na
   druhý řádek, o který pak pole přeteklo přes okno (hlídá to e2e test
   jazyk.spec.mjs).

   A schválně se nenásobí --ui. Není to rozměr návrhu, ale poslední mez pro
   případ nouze, a ta nouze nastává právě na velkém displeji, kde --ui zvedá
   všechno ostatní, ale šířku konzole drží hrací pole. */
.console-stats {
  display: flex;
  align-items: stretch;
  gap: 0;
  flex: 1;
  min-width: 112px;
}

/* Na herních stránkách do zbylého místa neroste. Růst znamená, že šířka
   počítadel závisí na tom, kolik místa zrovna zbylo po ostatních, a tomu
   vedle nich mění text hlavní tlačítko po každém tahu: odznaky mezi nimi
   uskakovaly o desítky pixelů a trefit se do nich mezi tahy bylo o štěstí.
   S šířkou podle obsahu (a rezervou na nejdelší hodnotu níž) stojí počítadla
   pořád stejně a zbylé místo si bere řádek ovládání, kde na konci visí
   tlačítko. Prázdná tabulka to nepotřebuje a doplatila by na to: konzoli má
   užší a širší počítadla by ji na malém okně zalomila o řádek. */
[data-mode] .console-stats {
  flex: 0 1 auto;
}

/* Tři a víc údajů (denní výzva s rekordem dne, těžká s odpočtem) se do
   112px nevejdou nikdy: popisky jsou nowrap a se stlačením se „POLÍČKA“
   a „REKORD“ slily do jednoho slova. Tady je spodní mezí skutečný obsah;
   když se nevejde, spadne ovládání na druhý řádek (.console má wrap),
   což je pořád čitelnější než text přes text. */
.console-stats:has(> .stat:nth-child(3)) {
  min-width: min-content;
}

.stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: calc(2px * var(--ui)) calc(14px * var(--ui));
  border-left: var(--hairline) solid var(--border);
  min-width: 0;
}

.stat:first-child {
  border-left: 0;
}

.stat-label {
  font-family: var(--label-font);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}

.stat-value {
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: 1.1875rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Místo na nejdelší hodnotu, kterou počítadlo za partii ukáže: čtyři číslice
   skóre (nejvyšší možné je 1500, viz SCORE_MAX v shared/rules.js) a pět míst
   na počet políček („25/25“). Bez rezervy se údaj po každém tahu o kousek
   rozšířil (z „0“ na „128“ je to přes dvacet pixelů) a všechno napravo od
   něj se posunulo.

   Míra je v pixelech, ne v `ch`, ačkoli by `ch` na tabulkové číslice sedělo
   přesněji: počítá se ale z písma, které je zrovna nasazené, takže by se
   při dostavení číslicového písma (font-display: swap) o pár pixelů změnila
   a konzole by při načítání stránky cukla. Pixely platí od prvního snímku.

   Platí to jen na herních stránkách. Prázdná tabulka má konzoli užší
   (nemá hrací pole, ze kterého by se šířka brala) a rezerva by ji na malém
   okně zalomila o řádek, což je horší než pohyb počítadla, které se tam
   navíc mění jen při psaní do buňky. */
[data-mode] .stat-value {
  min-width: calc(50px * var(--ui));
}

[data-mode] .console-stats > .stat:nth-child(2) .stat-value {
  min-width: calc(62px * var(--ui));
}

/* Odpočet drží šířku na tvar 00:00, i když zrovna ukazuje pomlčku. Číslice
   jsou sice tabulkové, jenže mezi čísly se místo času sází „–“, a bez pevné
   šířky by se dlaždice při každém položení zúžila a počítadla vedle ní by
   uskakovala (na úzkém displeji znatelně). Pixely místo `ch` ze stejného
   důvodu jako u ostatních počítadel výš. */
.stat--timer .stat-value {
  display: inline-block;
  min-width: calc(56px * var(--ui));
  text-align: center;
  transition: color var(--t-fast);
}

.stat--timer.t-good .stat-value {
  color: var(--good);
}

.stat--timer.t-warn .stat-value {
  color: var(--warn);
}

.stat--timer.t-bad .stat-value {
  color: var(--bad);
  animation: tick 1s steps(2) infinite;
}

@keyframes tick {
  50% {
    opacity: 0.45;
  }
}

/* Ovládání se zalomí ze stejného důvodu jako celá konzole: na úzkém telefonu
   se pole pro nastavení, vypínač náhledu, žolíci a hlavní tlačítko do jednoho
   řádku nevejdou. */
.console-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(6px * var(--ui));
  flex: none;
}

/* Hlavní tlačítko mění za partii text („Start“, „Generovat“, „Polož číslo“,
   „Použij žolíka“) a s ním šířku. Dokud si zbylé místo brala počítadla,
   posouvala každá taková změna celou skupinu odznaků nalevo od tlačítka.
   Řádek ovládání si teď zbylé místo bere sám a tlačítko v něm visí na pravé
   hraně: odznaky drží svoje místo a tlačítko roste doleva do prázdna.
   Stránky bez tažení (prázdná tabulka) nemají co skákat, tam zůstává celý
   blok u pravé hrany jako dřív. */
.console-actions:has(> .btn-roll) {
  flex: 1 1 auto;
  min-width: 0;
}

.console-actions > .btn-roll {
  margin-left: auto;
  /* Text se v tlačítku nezalamuje. Zalomený se do něj vejde i tam, kde je
     na něj málo místa, jenže tím tlačítko povyroste na dva řádky, s ním
     konzole a hrací pole sjede dolů. Bez zalomení se místo toho posune celé
     tlačítko na vlastní řádek, což je změna, která se dá uhlídat rezervou
     šířky (viz zlom 701 px v responsive.css). */
  white-space: nowrap;
}

.console-actions:not(:has(> .btn-roll)) {
  margin-left: auto;
}

/* Výběr čísel: řádek zabírá celou šířku konzole a hlavní tlačítko stojí
   kompaktní u pravého okraje, stejně jako na herních stránkách. */
.console-actions--wide {
  flex: 1;
}

.console-actions--wide > .btn-roll {
  margin-left: auto;
}

/* indikátor uschovaných žolíků */
.joker-chip {
  display: inline-flex;
  align-items: center;
  gap: calc(6px * var(--ui));
  padding: calc(8px * var(--ui)) calc(11px * var(--ui));
  border-radius: var(--r-btn);
  border: var(--hairline) solid var(--border);
  background-color: var(--surface-2);
  color: var(--text-faint);
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  cursor: not-allowed;
  transition: background-color var(--t-fast), border-color var(--t-fast),
    color var(--t-fast);
}

.joker-chip .icon {
  width: calc(17px * var(--ui));
  height: calc(17px * var(--ui));
}

.joker-chip.has-jokers {
  background-color: var(--joker-soft);
  border-color: var(--joker);
  color: var(--joker);
  cursor: pointer;
}

/* Klikací stav (žolík připravený k použití) potřebuje odezvu na najetí,
   jinak se od mrtvého čipu bez žolíků nedá rozeznat rukou. Výplň se
   překlopí do plné barvy žolíku, inkoust nese --inverse-ink, stejná
   logika jako u ostatních barevných výplní. */
.joker-chip.has-jokers:hover {
  background-color: var(--joker);
  border-color: var(--joker);
  color: var(--inverse-ink);
}

.joker-chip.is-armed {
  animation: armed 1.5s ease-in-out infinite;
}

@keyframes armed {
  0%,
  100% {
    box-shadow: 0 0 0 0 var(--joker-soft);
  }
  55% {
    box-shadow: 0 0 0 6px transparent;
  }
}

/* Místo pro oba vypínače je rezervované dopředu. Staví je js/preview.js
   a js/combos.js, oba odložené, takže do konzole přibudou až po prvním
   vykreslení. Bez rezervy se do prázdných značek naráz vešly dva čipy,
   konzole se o ně rozšířila, zalomila se o řádek a hrací pole pod ní
   uskočilo o padesát pixelů dolů, asi půl vteřiny po načtení stránky.
   Míra je rozměr hotového čipu (37 × 35 px při --ui 1), takže se po
   dostavení nezmění nic. Zůstává i tam, kde se náhled nesmí zapnout
   (zadavatel ho ve skupině může vypnout) a čip je proto schovaný. */
[data-preview-switch],
[data-combos-switch] {
  min-width: calc(37px * var(--ui));
  min-height: calc(35px * var(--ui));
}

/* Vypínač náhledu bodů a čip s bodovací tabulkou (js/combos.js). Tvarem
   sedí na .joker-chip vedle sebe. Náhled navíc nese stav, takže se místo
   .has-jokers řídí podle aria-pressed, stav ovládacího prvku patří do
   atributu, ne do třídy navíc; čip tabulky žádný stav nemá. */
.preview-chip,
.combos-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: calc(8px * var(--ui)) calc(9px * var(--ui));
  border-radius: var(--r-btn);
  border: var(--hairline) solid var(--border);
  background-color: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--label-font);
  font-size: 0.8125rem;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast), border-color var(--t-fast),
    color var(--t-fast);
}

.preview-chip .icon,
.combos-chip .icon {
  width: calc(17px * var(--ui));
  height: calc(17px * var(--ui));
}

.preview-chip:hover,
.combos-chip:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

.preview-chip[aria-pressed="true"] {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

/* Stisknutý stav stojí v kaskádě za obecným hoverem a sebral by mu odezvu;
   zapnutý vypínač musí na najetí reagovat taky, jinak vypadá mrtvě. */
.preview-chip[aria-pressed="true"]:hover {
  border-color: var(--accent-hover);
  color: var(--accent-hover);
}

.btn-roll {
  white-space: nowrap;
}

/* Hlavní akce stránky (Start / Generovat / Táhnout) je jílová. Je to jediné
   tlačítko, které jíl dostane, kdyby ho nesla i tlačítka v liště a dialozích,
   přestal by být akcentem a stal by se druhou základní barvou. Inkoust je
   --clay-ink (slate-dark v obou režimech): ivory by na #d97757 mělo kontrast
   jen 3,0 : 1. */
.btn-roll:not(.is-restart) {
  background-color: var(--clay);
  border-color: var(--clay);
  color: var(--clay-ink);
  font-weight: 600;
}

.btn-roll:not(.is-restart):hover:not(:disabled) {
  background-color: var(--clay-hover);
  border-color: var(--clay-hover);
}

.btn-roll.is-restart {
  background-color: var(--good);
  border-color: var(--good);
  color: var(--inverse-ink);
}

/* Bez vlastního hoveru by zelené tlačítko při najetí převzalo výchozí
   --btn-bg-hover z .btn:hover a překliklo na černou/bílou. Zjasnění je
   stejný postup jako u .btn--danger. */
.btn-roll.is-restart:hover:not(:disabled) {
  background-color: var(--good);
  border-color: var(--good);
  filter: brightness(1.08);
}

/* pole pro zadání času v těžké obtížnosti */
.field {
  display: flex;
  align-items: center;
  gap: calc(7px * var(--ui));
  padding-left: calc(10px * var(--ui));
}

.field label {
  font-family: var(--label-font);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}

.field input {
  width: calc(62px * var(--ui));
  padding: calc(7px * var(--ui)) calc(8px * var(--ui));
  background-color: var(--surface-inset);
  border: var(--hairline) solid var(--border-strong);
  border-radius: var(--r-sm);
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: 0.9375rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- hrací pole */
.board-wrap {
  width: var(--board-w);
  max-width: 100%;
  margin-inline: auto;
}

.board {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  border: var(--hairline) solid var(--border-strong);
  border-radius: var(--r-md);
  overflow: hidden;
  background-color: var(--surface);
  box-shadow: var(--shadow-md);
}

.board th,
.board td {
  border-right: var(--hairline) solid var(--grid-line);
  border-bottom: var(--hairline) solid var(--grid-line);
  text-align: center;
  vertical-align: middle;
  padding: 0;
  overflow: hidden;
  position: relative;
}

.board tr > *:last-child {
  border-right: 0;
}

.board tr:last-child > * {
  border-bottom: 0;
}

.board col.col-score {
  width: calc(var(--score-cell) / var(--board-w) * 100%);
}

.board col.col-play {
  width: calc(var(--cell) / var(--board-w) * 100%);
}

.board thead th {
  height: var(--score-cell);
}

.board tbody tr {
  height: var(--cell);
}

/* Rohové buňky nesou body za úhlopříčky. Malá šikmá ryska v rohu ukazuje,
   kterým směrem úhlopříčka vede. */
/* Ryska se měří polem, ne --ui: pole roste i tam, kde --ui zůstává na jedné
   (nízké široké okno), a značka musí držet stejný poměr k rohu buňky. */
.board thead th.corner::before {
  content: "";
  position: absolute;
  top: calc(var(--cell) * 0.04);
  width: calc(var(--cell) * 0.102);
  height: 0;
  border-top: max(1.5px, calc(var(--cell) * 0.012)) solid currentColor;
  opacity: 0.4;
}

.board thead th.corner:first-child::before {
  left: calc(var(--cell) * 0.04);
  transform: rotate(45deg);
  transform-origin: left top;
}

.board thead th.corner:last-child::before {
  right: calc(var(--cell) * 0.04);
  transform: rotate(-45deg);
  transform-origin: right top;
}

/* bodové buňky v záhlaví a na okraji řádků */
.board th {
  background-color: var(--score-bg);
  color: var(--score-ink);
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: calc(var(--cell) * 0.2);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  cursor: default;
  transition: background-color var(--t-fast), color var(--t-fast);
}

.board th.is-scoring {
  background-color: var(--score-hot-bg);
  color: var(--score-hot-ink);
}

/* Poslední sloupec je jen pokračování rámu, ne hrací plocha. Nese barvu
   bodových buněk, --surface-2 by z něj udělala nápadný pás. */
.board tbody th:last-child {
  background-color: var(--score-bg);
}

/* hrací buňky, velká čísla v serifu */
.board td {
  background-color: var(--cell-empty);
  color: var(--cell-ink);
  font-family: var(--font-display);
  font-weight: var(--board-num-weight);
  font-size: calc(var(--cell) * 0.48);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  transition: background-color var(--t-fast), box-shadow var(--t-fast);
}

.board td.filled {
  background-color: var(--cell-fill);
  cursor: default;
}

.board td.from-joker {
  color: var(--joker);
  background-color: var(--joker-soft);
}

.board td.just-placed {
  animation: cellIn 300ms cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes cellIn {
  from {
    transform: scale(0.55);
    opacity: 0;
  }
}

/* Když čeká číslo k umístění, volné buňky se dají kliknout a pod kurzorem
   ukážou předběžný náhled toho čísla. */
.board.is-placing td:not(.filled) {
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--accent-ring);
}

.board.is-placing td:not(.filled)::after {
  content: attr(data-ghost);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--accent);
  opacity: 0;
  transition: opacity var(--t-fast);
  pointer-events: none;
}

/* Hover jen tam, kde je skutečný kurzor. Dotykový prohlížeč jinak nechá
   :hover viset na políčku pod posledním ťuknutím (třeba po tlačítku losování)
   a políčko svítí, i když na něj nikdo nesahá. */
@media (hover: hover) {
  .board.is-placing td:not(.filled):hover {
    background-color: var(--accent-soft);
  }

  .board.is-placing td:not(.filled):hover::after {
    opacity: 0.45;
  }
}

.board.is-placing td:not(.filled):focus-visible {
  background-color: var(--accent-soft);
}

.board.is-placing td:not(.filled):focus-visible::after {
  opacity: 0.45;
}

/* Náhled bodů, kolik by čekající číslo na tomhle políčku přineslo.
   Sedí v rohu, aby se nepral s duchem čísla uprostřed: ten se ukáže jen pod
   kurzorem, tohle svítí na všech volných políčkách naráz. To je celý smysl,
   pole se dá přelétnout očima místo počítání dvanácti linií v hlavě.

   Píše ho js/preview.js do data-delta, takže vypnutý náhled je prostě pole
   bez atributu a nepotřebuje vlastní třídu na tabulce. */
.board.is-placing td:not(.filled)[data-delta]::before {
  content: attr(data-delta);
  position: absolute;
  top: calc(var(--cell) * 0.07);
  right: calc(var(--cell) * 0.09);
  font-family: var(--font-num);
  font-weight: var(--num-weight);
  font-size: calc(var(--cell) * 0.2);
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  pointer-events: none;
}

/* Nejvyšší okamžitý zisk. Schválně jen barvou, je to pomůcka pro oko,
   ne doporučený tah: zabrané políčko má cenu, kterou tohle číslo nevidí. */
.board.is-placing td:not(.filled).is-best::before {
  color: var(--accent);
}

/* ručně vyplňovaná tabulka */
/* Prázdná buňka nemá řádkový box, takže `vertical-align: middle` nemá co
   vystředit a psací kurzor se kreslí od horní hrany obsahu. Polohu kurzoru
   v takové buňce určuje půlproložení řádku (line-height minus výška písma,
   půl nahoru, půl dolů), a to je při `line-height: 1` nula. Roztažením
   řádkování na výšku buňky se z půlproložení stane polovina volného místa,
   takže kurzor i zapsaná číslice sednou na osu buňky.

   Hodnota je o vlásečnici nižší než buňka, aby se řádkový box vešel do
   obsahové výšky i s dolním rámečkem a řádek tabulky nenarostl. */
.board td[contenteditable="true"] {
  cursor: text;
  line-height: calc(var(--cell) - var(--hairline));
}

.board td[contenteditable="true"]:focus {
  outline: 0;
  background-color: var(--accent-soft);
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* ---------------------------------------------------- návod pro první hru */
/* Bublina js/tutorial.js. Polohu (left/top) i posun šipky (--tut-ax/--tut-ay)
   počítá JavaScript a stranu šipky píše do data-arrow; tady je jen vzhled.
   Žádný překryv přes stránku, hráč hraje dál a bublina se hracím buňkám
   vyhýbá. Ztišení animace řeší společné pravidlo prefers-reduced-motion
   v responsive.css. */
.tut-bubble {
  position: absolute;
  z-index: 45;             /* nad lištou souhlasu (40), pod dialogy (50) */
  max-width: min(calc(280px * var(--ui)), calc(100vw - 16px));
  padding: calc(10px * var(--ui)) calc(12px * var(--ui));
  background-color: var(--surface);
  border: var(--hairline) solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  animation: tutIn 200ms cubic-bezier(0.16, 1, 0.3, 1);
}

.tut-bubble[hidden] {
  display: none;
}

@keyframes tutIn {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
}

.tut-text {
  margin: 0 0 calc(8px * var(--ui));
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--text);
}

.tut-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(6px * var(--ui));
}

.tut-actions .btn {
  padding: calc(5px * var(--ui)) calc(11px * var(--ui));
  font-size: 0.75rem;
}

/* Šipka: čtverec otočený o 45°, ze kterého kouká jen špička. Vidět smí být
   jen dvě hrany směrem ven, zbylé dvě by kreslily čáru přes tělo bubliny. */
.tut-bubble::before {
  content: "";
  position: absolute;
  width: 10px;
  height: 10px;
  background-color: var(--surface);
  transform: rotate(45deg);
}

.tut-bubble[data-arrow="up"]::before {
  top: -6px;
  left: calc(var(--tut-ax, 24px) - 5px);
  border-top: var(--hairline) solid var(--border-strong);
  border-left: var(--hairline) solid var(--border-strong);
}

.tut-bubble[data-arrow="down"]::before {
  bottom: -6px;
  left: calc(var(--tut-ax, 24px) - 5px);
  border-right: var(--hairline) solid var(--border-strong);
  border-bottom: var(--hairline) solid var(--border-strong);
}

.tut-bubble[data-arrow="left"]::before {
  left: -6px;
  top: calc(var(--tut-ay, 14px) - 5px);
  border-left: var(--hairline) solid var(--border-strong);
  border-bottom: var(--hairline) solid var(--border-strong);
}

.tut-bubble[data-arrow="right"]::before {
  right: -6px;
  top: calc(var(--tut-ay, 14px) - 5px);
  border-top: var(--hairline) solid var(--border-strong);
  border-right: var(--hairline) solid var(--border-strong);
}

/* Bublina přilepená k hraně okna. Nastává tam, kde se kolem cíle žádná
   poloha nevejde a ani místo pod polem není vidět, tedy skoro vždycky na
   telefonu. Šipka nemá kam mířit, tak žádná není. Stranu vybírá JS podle
   toho, kde leží cíl, viz dock() v js/tutorial.js. */
.tut-bubble.is-docked {
  position: fixed;
  left: calc(8px * var(--ui));
  right: calc(8px * var(--ui));
  max-width: none;
}

.tut-bubble.is-docked[data-dock="bottom"] {
  bottom: calc(8px * var(--ui) + env(safe-area-inset-bottom, 0px));
}

.tut-bubble.is-docked[data-dock="top"] {
  top: calc(8px * var(--ui) + env(safe-area-inset-top, 0px));
}

.tut-bubble[data-arrow="none"]::before {
  content: none;
}

/* Cíl, ke kterému bublina mluví. Bodové buňky vypadají všechny stejně,
   takže samotná šipka je slabá stopa. Stín je vnitřní: hrací pole má
   buňky natěsno u sebe a vnější by sousedka překreslila. */
.tut-spot {
  animation: tutSpot 1.6s ease-in-out infinite;
}

@keyframes tutSpot {
  0%,
  100% {
    box-shadow: inset 0 0 0 0 var(--accent);
  }
  50% {
    box-shadow: inset 0 0 0 2px var(--accent);
  }
}

/* Linie, kterými prochází právě položené číslo. Spolu s přepočtem bodů na
   okraji (js/tutorial.js) ukazují to, co jinak nikdo nevidí: jedno číslo se
   počítá do dvou až čtyř linií naráz. Zhasínají až s bublinou, která je
   vysvětluje, nebo dalším tahem, ne po odměřeném čase. */
.board td.tut-line {
  background-color: var(--accent-soft);
}

.board th.tut-line-score {
  box-shadow: inset 0 0 0 2px var(--accent);
}
