/* ---------------------------------------------------------------- tokens */
:root {
  --bg: #f6f6f4;
  --fg: #111114;
  --muted: #6b6b76;
  --line: #e2e2dd;

  --face-bg: #ffffff;
  --face-fg: #111114;
  --face-line: #dcdcd6;

  --back-bg: #17171b;
  --back-line: #17171b;

  --wrong-bg: #9b9ba3;
  --wrong-fg: #ffffff;

  --ok: #1fb573;
  --no: #ef4444;

  --shadow: 0 1px 2px rgba(17, 17, 20, .06), 0 8px 24px -12px rgba(17, 17, 20, .25);
  --radius: 16px;
  --tap: color-mix(in srgb, var(--fg) 8%, transparent);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e0e11;
    --fg: #f2f2f5;
    --muted: #9a9aa6;
    --line: #26262e;

    --face-bg: #2b2b34;
    --face-fg: #ffffff;
    --face-line: #3d3d49;

    --back-bg: #08080a;
    --back-line: #1c1c22;

    --wrong-bg: #55555f;
    --wrong-fg: #d8d8e0;

    --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 30px -14px rgba(0, 0, 0, .8);
  }
}

/* ------------------------------------------------------------------ base */
* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  overflow-x: hidden;
}

button {
  font: inherit;
  color: inherit;
  touch-action: manipulation;
  cursor: pointer;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Bis js/main.js uebersetzt hat, bleibt die App unsichtbar (das Attribut setzt
   applyTranslations). Nur so sieht eine franzoesische Oberflaeche nicht ein
   Einzelbild lang die englische Grundlage aus index.html. Ohne JS gaebe es
   ohnehin kein Spielfeld - das Warten kostet also nichts. */
.app {
  visibility: hidden;
}

html[data-i18n-ready] .app {
  visibility: visible;
}

.app {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr;
  min-height: 100svh;
  padding: max(10px, env(safe-area-inset-top)) 16px max(16px, env(safe-area-inset-bottom));
  max-width: 560px;
  margin-inline: auto;
}

/* ------------------------------------------------------------------- hud */
.hud {
  display: grid;
  /* Nicht symmetrisch (1fr auto 1fr): Dann waere die linke Spalte so breit wie
     die Knopfleiste rechts, und bei 320 px passte die Zeile nicht mehr - der
     Beenden-Knopf laege ausserhalb des Bildschirms. So nimmt jede Seite nur,
     was sie braucht, und die Uhr bekommt den Rest. */
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .25s ease, transform .25s ease;
  pointer-events: none;
}

.hud[data-on="1"] {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.hud__side { display: flex; align-items: center; gap: 6px; }
.hud__side--end { justify-content: flex-end; }

.pill {
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .01em;
  color: var(--muted);
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}

.hud__center { position: relative; display: grid; justify-items: center; gap: 6px; min-width: 0; }

.clock {
  font-size: 22px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

.clock--low { color: var(--no); }

.clock__bar {
  /* Schrumpft mit, wenn die Zeile eng wird. */
  width: min(104px, 100%);
  height: 3px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}

.clock__bar > i {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: inherit;
  background: var(--fg);
  transform-origin: left center;
}

.clock--low ~ .clock__bar > i { background: var(--no); }

/* Gewonnene Zeit kurz einblenden – sonst merkt man den Rundenbonus gar nicht. */
.bonus {
  position: absolute;
  left: 100%;
  top: 0;
  margin-left: 10px;
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ok);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
}

.bonus[data-on] { animation: bonus .9s ease-out; }
/* Ein von Fehlern geschmaelerter Bonus ist kein Gewinn - also auch nicht gruen. */
.bonus[data-cut] { color: var(--muted); }

@keyframes bonus {
  0%   { opacity: 0; transform: translateY(5px); }
  20%  { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-9px); }
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  font-size: 17px;
  transition: background .15s ease, color .15s ease, transform .1s ease;
}

@media (max-width: 360px) {
  .icon-btn { width: 32px; height: 32px; }
  .hud__side { gap: 2px; }
  .pill { padding: 4px 8px; }
}

.icon-btn:hover { background: var(--tap); color: var(--fg); }
.icon-btn:active { transform: scale(.92); }
.icon-btn svg { width: 20px; height: 20px; }
.icon-btn[aria-pressed="true"] .icon-mute { display: none; }
.icon-btn[aria-pressed="false"] .icon-wave { display: none; }
.icon-btn[aria-pressed="false"] { color: color-mix(in srgb, var(--muted) 70%, transparent); }

.flash {
  width: 11px; height: 11px;
  margin-right: 2px;
  border-radius: 50%;
  background: var(--ok);
  opacity: 0;
  transition: opacity .45s ease;
}

.flash[data-on="ok"] { background: var(--ok); opacity: 1; transition: none; }
.flash[data-on="no"] { background: var(--no); opacity: 1; transition: none; }

/* ----------------------------------------------------------------- stage */
.stage {
  display: grid;
  grid-template-rows: 1fr auto;
  align-content: center;
  justify-items: center;
  gap: clamp(20px, 5vh, 40px);
  padding-block: clamp(12px, 4vh, 32px);
}

.board-wrap {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 18px;
}

.board {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), 1fr);
  gap: clamp(8px, 2.4vw, 14px);
  width: min(88vw, 400px);
  transition: opacity .2s ease;
}

.board[data-locked="1"] { pointer-events: none; }

/* ----------------------------------------------------------------- tiles */
.tile {
  position: relative;
  aspect-ratio: 5 / 4;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--face-line);
  border-radius: var(--radius);
  background: var(--face-bg);
  color: var(--face-fg);
  font-size: clamp(22px, 7.5vw, 34px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0;
  overflow: hidden;
  transition:
    background-color .22s cubic-bezier(.2, .7, .3, 1),
    border-color .22s ease,
    color .12s ease,
    transform .12s cubic-bezier(.2, .7, .3, 1);
}

.tile > span {
  transition: opacity .16s ease, transform .22s cubic-bezier(.2, .7, .3, 1);
}

/* verdeckt */
.tile[data-state="back"] {
  background: var(--back-bg);
  border-color: var(--back-line);
  color: transparent;
}

.tile[data-state="back"] > span { opacity: 0; transform: scale(.6); }

/* aufgedeckt / Vorschau */
.tile[data-state="face"] > span { opacity: 1; transform: none; }

/* leeres Feld in der Vorschau */
.tile[data-state="face"][data-empty="1"] > span { opacity: 0; }

/* falsch getippt */
.tile[data-state="wrong"] {
  background: var(--wrong-bg);
  border-color: var(--wrong-bg);
  color: var(--wrong-fg);
  animation: shake .32s cubic-bezier(.36, .07, .19, .97);
}

.tile[data-state="wrong"] > span { opacity: 1; transform: none; }

.tile:active { transform: scale(.955); }

.tile[data-state="back"]:active { background: #24242c; }

.tile.is-pop { animation: pop .3s cubic-bezier(.2, .8, .3, 1.2); }

.tile.is-clear { animation: clear .45s ease both; }

@keyframes pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.07); }
  100% { transform: scale(1); }
}

@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-6px); }
  40%, 60% { transform: translateX(6px); }
}

@keyframes clear {
  0%   { transform: scale(1); opacity: 1; }
  30%  { transform: scale(1.05); }
  100% { transform: scale(.9); opacity: .25; }
}

/* ------------------------------------------------------------ fortschritt */
.dots {
  display: flex;
  gap: 7px;
  min-height: 8px;
  opacity: 0;
  transition: opacity .2s ease;
}

.dots[data-on="1"] { opacity: 1; }

.dots > i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--line);
  transition: background-color .2s ease, transform .2s cubic-bezier(.2, .8, .3, 1.4);
}

.dots > i[data-done] { background: var(--ok); }
.dots > i[data-next] { background: var(--fg); transform: scale(1.35); }

/* ---------------------------------------------------------------- button */
.action {
  min-width: 190px;
  padding: 14px 28px;
  border: 0;
  border-radius: 999px;
  background: var(--fg);
  color: var(--bg);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .01em;
  box-shadow: var(--shadow);
  transition: transform .12s cubic-bezier(.2, .7, .3, 1), opacity .2s ease;
}

/* Unsichtbar, aber im Layout: Verschwaende der Knopf seinen Platz, wuerde das
   Spielfeld beim Verdecken neu zentriert - genau im Moment, in dem der Spieler
   sich die Positionen gemerkt hat. */
.action[data-idle] { visibility: hidden; }

.action:active { transform: scale(.96); }
.action[disabled] { opacity: .45; pointer-events: none; }
.action--lg { width: 100%; padding: 16px 28px; font-size: 18px; }

/* ----------------------------------------------------------------- sheet */
.sheet {
  position: fixed;
  inset: 0;
  /* Spalte plus `margin: auto` an der Karte (statt `place-items: center`), und
     zwar aus zwei Gruenden:

     1. Passt die Karte nicht auf den Bildschirm, muss die Lade scrollen. Auf
        einem 320x568-Display stand der "Spiel starten"-Knopf sonst bei 626 px
        und war schlicht nicht erreichbar. Ein zentrierter Grid-Inhalt, der
        ueberlaeuft, laesst sich NICHT herunterscrollen - `margin: auto` in
        einer Flex-Spalte schon.
     2. Eine zentrierte Grid-Spur ist so breit wie der groesste Inhalt, und das
        `width: min(100%, 420px)` der Karte rechnete seine 100 % gegen genau
        diese Breite. Die Wunschbreite eines Eingabefeldes (~20 Zeichen) schob
        die Endkarte damit auf 320 px ueber den rechten Rand. */
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 10;
  transition: opacity .25s ease;
}

.sheet[hidden] { display: none; }
.sheet.is-out { opacity: 0; pointer-events: none; }

.card {
  width: min(100%, 420px);
  margin: auto; /* zentriert und trotzdem scrollbar - siehe .sheet */
  padding: 28px 24px 24px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--face-bg);
  box-shadow: var(--shadow);
  text-align: center;
  animation: rise .28s cubic-bezier(.2, .8, .3, 1) both;
}

.card--slim { padding-bottom: 28px; }
.card[hidden] { display: none; }

@keyframes rise {
  from { opacity: 0; transform: translateY(14px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.card h1 {
  margin: 0 0 12px;
  font-size: clamp(25px, 7.4vw, 33px);
  letter-spacing: -.02em;
  overflow-wrap: break-word;
  text-wrap: balance;
}

.card h2 {
  margin: 0 0 14px;
  font-size: clamp(22px, 6.5vw, 27px);
  letter-spacing: -.01em;
}

.eyebrow {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}

.lead { margin: 0 0 18px; color: var(--muted); }

.rules {
  margin: 0 0 24px;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
  text-align: left;
  font-size: 15px;
  color: var(--muted);
}

.rules li {
  padding-left: 22px;
  position: relative;
}

.rules li::before {
  content: "";
  position: absolute;
  left: 4px; top: .62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--fg);
}

.rules b { color: var(--fg); font-weight: 650; }

.stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 18px;
}

.stat {
  display: grid;
  gap: 2px;
  padding: 12px 6px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}

.stat b { font-size: 24px; font-weight: 750; font-variant-numeric: tabular-nums; }
.stat span { font-size: 12px; color: var(--muted); }

/* Einstellungen auf den Karten: erreichbar, ohne die Karte zu einem Menue zu machen. */
.chips {
  display: flex;
  /* Umbrechen, nicht quetschen: Drei Chips passen auf 390 px nebeneinander,
     auf 320 px nicht mehr - und ein laengeres Wort ("Clasificación") reisst
     die Reihe auch auf breiteren Geraeten auf. */
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 650;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .1s ease;
}

.chip:hover { background: var(--tap); color: var(--fg); }
.chip:active { transform: scale(.96); }
.chip svg { width: 18px; height: 18px; }
.chip[aria-pressed="true"] { color: var(--fg); border-color: var(--fg); }
.chip[aria-pressed="true"] .icon-mute { display: none; }
.chip[aria-pressed="false"] .icon-wave { display: none; }

/* Der Sprachwaehler ist ein echtes <select> in Chip-Form. Das System malt die
   Liste selbst - auf dem Handy als Rad, auf dem Desktop als Menue -, also gibt
   es hier kein nachgebautes Aufklappmenue, keine Tastaturbedienung zum
   Nachruesten und nichts, was bei einer fuenften Sprache neu geschrieben werden
   muesste. Das <label> traegt den Rahmen, das <select> sitzt nur darin. */
.chip--lang {
  padding-inline-end: 10px;
  cursor: pointer;
}

.chip--lang:focus-within { color: var(--fg); border-color: var(--fg); }

.chip__select {
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-weight: 650;
  /* Der Pfeil gehoert zum Chip, nicht zum Systemfeld: `appearance: none` nimmt
     ihn weg, hier kommt er als Hintergrundbild zurueck - in `currentColor`, also
     auch im Dunkelmodus richtig. */
  padding-inline-end: 16px;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 6px center, right 2px center;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.chip__select:focus-visible { outline: 2px solid var(--fg); outline-offset: 4px; }

/* Die Liste selbst malt das System - dort schlaegt `transparent` als
   Hintergrund auf manchen Plattformen auf weissem Grund weisse Schrift. */
.chip__select option { color: initial; background: initial; }

/* Auf den schmalsten verbreiteten Geraeten wird die Chipreihe knapp: drei Chips,
   und Franzoesisch wie Spanisch laufen deutlich laenger als Deutsch. Gekuerzt
   wird nur waagerecht - senkrecht ist das die Grosse des Daumenziels. */
@media (max-width: 360px) {
  .chip { padding-inline: 10px; gap: 6px; }
  .chips { gap: 6px; }
}

.best {
  margin: 16px 0 0;
  min-height: 1.2em;
  font-size: 14px;
  color: var(--muted);
}

.best b { color: var(--fg); font-weight: 650; }

/* ---------------------------------------------------------- bestenliste */
/* Die Endkarte darf durch das Eintragen nicht zur Formularseite werden: eine
   Zeile Rang, eine Zeile Eingabe, eine Zeile Status - und erst darunter wieder
   der grosse Knopf, der in 99 % der Faelle der naechste Griff ist. */
.rank-line {
  margin: 0 0 10px;
  font-size: 14px;
  color: var(--muted);
}

.rank-line[hidden] { display: none; }
.rank-line b { color: var(--fg); font-weight: 650; }

.entry {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.entry[hidden] { display: none; }

.entry__name {
  /* Basis 6em statt `auto`: Die Wunschbreite eines Eingabefeldes (~20 Zeichen)
     soll nicht mitreden, wie breit die Karte sein will. */
  flex: 1 1 6em;
  min-width: 0;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  color: var(--fg);
  font: inherit;
  font-size: 15px;
}

.entry__name::placeholder { color: var(--muted); }

.entry__submit {
  flex: none;
  padding: 11px 18px;
  border: 1px solid var(--fg);
  border-radius: 999px;
  background: var(--fg);
  color: var(--bg);
  font-size: 15px;
  font-weight: 650;
  transition: transform .1s ease, opacity .2s ease;
}

.entry__submit:active { transform: scale(.96); }
.entry__submit[disabled] { opacity: .45; pointer-events: none; }

.entry__status {
  margin: 0 0 16px;
  min-height: 1.3em;
  font-size: 13px;
  color: var(--muted);
}

.entry__status[data-tone="ok"] { color: var(--ok); }
.entry__status[data-tone="err"] { color: var(--no); }

/* Die Bestenliste ist eine eigene Karte in derselben Lade: Sie oeffnet sich
   ueber der Start- oder Endkarte und kehrt beim Schliessen dorthin zurueck. */
.card--scores {
  display: flex;
  flex-direction: column;
  /* Die Liste scrollt in sich; die Karte selbst bleibt im Bild. */
  max-height: min(78svh, 620px);
  flex: none;
}

.tabs {
  display: flex;
  gap: 6px;
  padding: 4px;
  margin-bottom: 12px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 6%, transparent);
}

.tab {
  flex: 1;
  min-width: 0;
  padding: 8px 6px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background .15s ease, color .15s ease;
}

.tab[hidden] { display: none; }
.tab[aria-selected="true"] {
  background: var(--face-bg);
  color: var(--fg);
  box-shadow: var(--shadow);
}

/* Die Reiterzeile ist die engste Zeile der App: zwei Reiter nebeneinander,
   beide ohne Umbruch, in vier verschieden langen Sprachen. Auf 320 px stand
   "Auf dem Gerät" darueber hinaus und wurde abgeschnitten - was von selbst
   nirgends auffaellt, weil ein abgeschnittener Reiter immer noch wie ein
   Reiter aussieht. Gekuerzt wird nur waagerecht; senkrecht ist das das Ziel
   fuer den Daumen. Muss HINTER `.tab` stehen: dessen `padding`-Kurzform
   ueberschriebe ein vorher notiertes `padding-inline` wieder. */
@media (max-width: 360px) {
  .tab { padding-inline: 2px; font-size: 13px; }
}

/* Die Liste ist der einzige Teil, der schrumpfen darf - so bleibt die Karte
   gleich hoch, egal ob drei oder fuenfzig Zeilen drinstehen. */
.score-list {
  flex: 1;
  min-height: 84px;
  overflow-y: auto;
  margin-bottom: 16px;
  text-align: left;
  -webkit-overflow-scrolling: touch;
}

.score-row {
  display: grid;
  grid-template-columns: 2.1em minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 12px;
  font-size: 15px;
}

.score-row + .score-row { margin-top: 2px; }
.score-row:nth-child(odd) { background: color-mix(in srgb, var(--fg) 4%, transparent); }

/* Die eigene Zeile. Nicht nur Farbe: Ein Rahmen bleibt auch dann erkennbar,
   wenn die Liste weit gescrollt ist oder jemand Farben schlecht unterscheidet. */
.score-row.me {
  outline: 2px solid var(--ok);
  outline-offset: -2px;
  background: color-mix(in srgb, var(--ok) 12%, transparent);
}

.score-rank {
  color: var(--muted);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.score-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.score-val {
  color: var(--muted);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.score-val b { color: var(--fg); font-weight: 700; font-size: 15px; }

.score-note {
  padding: 24px 10px;
  color: var(--muted);
  font-size: 14px;
  text-align: center;
}

/* --------------------------------------------------------------- a11y/motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .06s !important;
  }
}

:focus-visible {
  outline: 3px solid var(--ok);
  outline-offset: 3px;
}
