/* ============================================================
   Outdoor Escape Game – Chat-Player im Messenger-Look
   ============================================================ */

/* Alle Farben, die Schrift und die Maße stehen in einer eigenen Datei —
   nicht der Ordnung wegen, sondern weil das BACKEND sie ebenfalls laden
   muss: Der Design-Reiter zeigt die Vorgabewerte in seinen Feldern an und
   darf sie nicht ein zweites Mal führen. Als eigene Datei liest er sie
   über ein <link> — das geht auch dann, wenn das Backend als Datei geöffnet
   ist (dort darf eine Seite keine Nachbardatei per fetch lesen).
   @import steht ganz oben, weil CSS das so verlangt. */
@import url("variablen.css");

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

html, body {
  height: 100%;
  font-family: var(--font-family);
  background: var(--page-bg);
}

/* Handy-Rahmen: auf dem Desktop zentriert, auf Mobilgeräten Vollbild */
.phone {
  max-width: 460px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  background: var(--chat-bg);
  box-shadow: 0 0 24px var(--shadow-phone);
  position: relative;
}

/* ---------- Login ---------- */
.login {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Bild über dem Verlauf (URS-015). Ohne eigenes Bild bleibt `none` und
     der Verlauf steht wie bisher. Mit Bild deckt es den Verlauf ab — das
     ist gewollt; die drei Verlaufsfarben wirken dann nur noch dort, wo das
     Bild durchsichtig ist. */
  background-image:
    var(--login-bg-image),
    linear-gradient(160deg, var(--login-bg-from) 0%, var(--login-bg-via) 60%, var(--login-bg-to) 100%);
  background-size: cover, auto;
  background-repeat: no-repeat, no-repeat;
  background-position: center center, 0 0;
  padding: 24px;
}
.login-box {
  background: var(--login-card-bg);
  border-radius: var(--login-card-radius);
  padding: 32px 26px;
  width: 100%;
  max-width: 330px;
  text-align: center;
  box-shadow: 0 12px 40px var(--shadow-login);
}
.login-logo { font-size: 44px; margin-bottom: 10px; }
.login-box h1 { font-size: 22px; color: var(--login-title); margin-bottom: 8px; }
.login-box p { font-size: 14px; color: var(--login-sub); margin-bottom: 20px; line-height: 1.4; }
.login-box input {
  width: 100%;
  border: var(--login-field-border-width) solid var(--field-border);
  border-radius: var(--login-input-radius);
  padding: 12px 14px;
  font-size: 16px;
  text-align: center;
  letter-spacing: 1px;
  outline: none;
  margin-bottom: 12px;
}
.login-box input:focus { border-color: var(--field-border-focus); }
.login-box button {
  width: 100%;
  background: var(--login-btn-bg);
  color: var(--login-btn-text);
  border: none;
  border-radius: var(--login-btn-radius);
  padding: 13px;
  font-size: 16px;
  font-weight: var(--login-btn-weight);
  cursor: pointer;
}
.login-box button:disabled { background: var(--login-btn-disabled-bg); }
.login-error { color: var(--error); font-size: 13px; margin-top: 12px; min-height: 18px; }

/* ---------- Ersetzbare Symbole (URS-015) ----------
   Jedes dieser Zeichen lässt sich im Design-Reiter durch ein eigenes Bild
   ersetzen. Der Trick steckt in `content: var(--icon-x, "🎒")`: Ist die
   Variable nicht gesetzt, greift der Rückfall und das Emoji erscheint; ist
   sie auf `url(…)` gesetzt, erscheint das Bild. Kein Zusatzschalter, kein
   Rest — und beide Zustände sind gleich groß (gemessen 18.09.2026: 28×25
   px mit Emoji wie mit einem 200-px-Bild).

   DESHALB stehen die Emojis hier im Stylesheet und nicht mehr im HTML bzw.
   im `textContent`: Solange ein Zeichen als Text im Element steht, bekommt
   man es per CSS nicht wieder weg, und ein eigenes Bild stünde daneben
   statt an seiner Stelle. Das ist der kleine Preis, den URS-015 mit
   „ohne Änderung an der Knopf-Erzeugung" nicht vorhergesehen hatte.

   `max-width`/`max-height` decken ein zu groß hochgeladenes Bild auf
   Zeilenhöhe; auf ein Emoji wirken sie nicht.

   Die Galerie ist die eine Ausnahme ohne Emoji im Rückfall: Ihr Zeichen
   steht in `js/texte.js` (das Backend zeigt es auch), und die Engine
   reicht es beim Start als `--icon-gallery-default` herein. Es hier ein
   zweites Mal zu schreiben wäre genau der Fehler, den texte.js verhindert. */
.ico::before {
  display: inline-block;
  max-width: 1.25em;
  max-height: 1.25em;
  vertical-align: middle;
}
.ico-backpack::before { content: var(--icon-backpack, "🎒"); }
.ico-gallery::before  { content: var(--icon-gallery, var(--icon-gallery-default)); }
.ico-clip::before     { content: var(--icon-clip, "📎"); }
.ico-play::before     { content: var(--icon-play, "▶"); }
.ico-pause::before    { content: var(--icon-pause, "⏸"); }
.ico-continue::before { content: var(--icon-continue, "▶"); }

/* ---------- Rucksack ---------- */
/* Die Hülle um Rucksack und Galerie (URS-028). Auf dem Handy erzeugt sie
   bewusst KEINE eigene Box: `display: contents` lässt sie verschwinden,
   die beiden Panels hängen dann wie vorher direkt an `.phone` und behalten
   ihre absolute Lage als Overlay. Erst ab Desktop-Breite wird sie unten in
   den @media-Blöcken zur Seitenspalte. */
.sidebar { display: contents; }

.badge {
  position: absolute;
  top: 0; right: 0;
  background: var(--badge-bg);
  color: var(--badge-text);
  font-size: 10px;
  font-weight: var(--badge-weight);
  border-radius: var(--badge-radius);
  min-width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
}
#btn-backpack { position: relative; }
.backpack {
  display: none;
  position: absolute;
  top: 62px;
  right: 10px;
  z-index: 5;
  background: var(--panel-bg);
  border-radius: var(--panel-radius);
  box-shadow: 0 8px 28px var(--shadow-panel);
  padding: 14px 16px;
  width: 250px;
  max-height: 55%;
  overflow-y: auto;
}
.backpack-title { font-weight: var(--panel-title-weight); margin-bottom: 8px; color: var(--panel-title); }
.backpack ul { list-style: none; }
.backpack li {
  padding: 8px 0;
  border-bottom: var(--panel-divider-width) solid var(--panel-divider);
  font-size: 13.5px;
  color: var(--panel-item-text);
}
.backpack li:last-child { border-bottom: none; }
.backpack li span { color: var(--panel-item-sub); font-size: 12.5px; }
.backpack li.clickable { cursor: pointer; }
.backpack li.clickable:hover { background: var(--panel-row-hover); }
.backpack li.clickable strong { color: var(--item-name); }

/* Item-Kombination: Auswahl im Rucksack + Kombinieren-Button */
.backpack li { position: relative; padding-right: 30px; }
.backpack li.selected {
  background: var(--panel-row-selected);
  border-radius: var(--panel-row-radius);
  padding-left: 8px;
  margin-left: -8px;
}
.backpack li.selected:hover { background: var(--panel-row-selected-hover); }
.bp-hint {
  font-size: 12px;
  color: var(--bp-hint-text);
  margin-bottom: 6px;
  line-height: 1.35;
}
/* Leerer Rucksack (URS-028). Auf dem Handy war der nie zu sehen – der
   🎒-Knopf erscheint erst mit dem ersten Item. In der Seitenspalte steht
   der Rucksack dagegen von Anfang an offen, und eine Karte mit nichts als
   einer Überschrift sieht kaputt aus. */
.bp-empty {
  color: var(--bp-empty-text);
  font-size: 13px;
  border-bottom: none;
  padding-right: 0;
}
.bp-clip {
  position: absolute;
  top: 6px; right: 0;
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
  padding: 2px 4px;
}
.bp-clip:hover { transform: scale(1.15); }
.bp-combine {
  display: block;
  width: 100%;
  margin-top: 10px;
  background: var(--combine-bg);
  border: none;
  color: var(--combine-text);
  font-size: 13.5px;
  font-weight: var(--combine-weight);
  padding: 10px;
  border-radius: var(--combine-radius);
  cursor: pointer;
}
.bp-combine:hover { background: var(--combine-bg-hover); }

/* Galerie-Panel */
.gallery-panel { width: 290px; }
.gallery-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.gal-item img {
  width: 100%;
  height: 90px;
  object-fit: cover;
  border-radius: var(--gal-item-radius);
  cursor: pointer;
  display: block;
}
.gal-caption {
  font-size: 11.5px;
  color: var(--gal-caption-text);
  margin-top: 3px;
  line-height: 1.3;
}
.gal-empty {
  grid-column: 1 / -1;
  font-size: 13px;
  color: var(--gal-empty-text);
  padding: 6px 2px;
  line-height: 1.4;
}

/* Platzhalter für noch nicht hochgeladene Medien */
.media-missing {
  background: var(--placeholder-bg);
  border: var(--placeholder-border-width) dashed var(--placeholder-border);
  border-radius: var(--placeholder-radius);
  padding: 22px 14px;
  font-size: 13px;
  color: var(--placeholder-text);
  text-align: center;
  min-width: 220px;
}

/* ---------- Kopfzeile ---------- */
.chat-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--header-bg);
  color: var(--header-text);
  flex-shrink: 0;
  z-index: 2;
}
.avatar {
  width: 40px; height: 40px;
  border-radius: var(--avatar-radius);
  background: var(--header-avatar-bg);
  display: flex; align-items: center; justify-content: center;
  font-weight: var(--avatar-weight); font-size: 18px;
  border: var(--avatar-border-width) solid var(--header-avatar-border);
  /* URS-018: Ein Profilbild soll die runde Form annehmen, nicht über sie
     hinausstehen. Ohne Bild ändert das nichts. */
  overflow: hidden;
}
/* URS-018: Jos Profilbild. `border-radius: inherit` statt einer eigenen
   Zahl – dadurch trägt das Bild weiterhin --avatar-radius mit, auch wenn
   das Team die Form im Design-Reiter ändert (URS-015). `cover` schneidet
   zu, statt zu verzerren: Ein hochkant fotografiertes Bild wäre sonst
   gestaucht. */
.avatar-bild {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}
.header-info { flex: 1; min-width: 0; }
.header-name { font-weight: var(--header-name-weight); font-size: 16px; }
.header-status { font-size: 12.5px; opacity: .85; }
.header-btn {
  background: none; border: none; color: var(--header-btn-text);
  font-size: 22px; cursor: pointer; padding: 4px 8px;
  border-radius: var(--header-btn-radius);
}
.header-btn:hover { background: var(--header-btn-hover); }

/* ---------- Chatverlauf ---------- */
.chat {
  flex: 1;
  overflow-y: auto;
  padding: 14px 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* Drei Ebenen: oben das Hintergrundbild des Spiels (URS-015), darunter
     das feine Punktmuster aus zwei Verläufen. Ohne eigenes Bild steht dort
     `none` — eine gültige Ebene, die nichts zeichnet. Die Angaben zu Größe,
     Wiederholung und Lage brauchen deshalb je Ebene einen Wert; sonst
     würde das Foto in 28-px-Kacheln wiederholt. */
  background-image:
    var(--chat-bg-image),
    radial-gradient(circle at 25% 25%, var(--chat-pattern) 1px, transparent 1px),
    radial-gradient(circle at 75% 75%, var(--chat-pattern) 1px, transparent 1px);
  background-size: cover, 28px 28px, 28px 28px;
  background-repeat: no-repeat, repeat, repeat;
  background-position: center center, 0 0, 0 0;
}

.msg {
  max-width: 78%;
  padding: 7px 9px 8px;
  border-radius: var(--msg-radius);
  position: relative;
  font-size: 14.5px;
  line-height: 1.35;
  color: var(--msg-text);
  box-shadow: 0 1px 1px var(--shadow-bubble);
  word-wrap: break-word;
  animation: pop .18s ease-out;
}
@keyframes pop {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.msg.bot { align-self: flex-start; background: var(--bubble-bot); border-top-left-radius: 0; }
.msg.me  { align-self: flex-end;   background: var(--bubble-me);  border-top-right-radius: 0; }

/* Absender über der Blase (URS-022): Schreibt ein anderer Charakter über Jos
   Account, steht sein Name darüber – dasselbe Muster wie in Gruppenchats.
   Das Bild ist optional; ohne Bild trägt der Name allein den Wechsel. */
.msg .absender {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 3px;
  font-size: 12.5px;
  font-weight: var(--sender-name-weight);
  color: var(--sender-name);
}
.msg .absender-bild {
  width: 20px;
  height: 20px;
  border-radius: var(--avatar-radius);
  object-fit: cover;
  flex: none;
}
/* Etwas mehr Luft oben, damit der Name nicht am Blasenrand klebt */
.msg.bot.fremder-absender { padding-top: 6px; }

.msg .time {
  display: inline-block;
  font-size: 11px;
  color: var(--msg-time);
  margin-left: 8px;
  float: right;
  margin-top: 6px;
}
.msg.me .time::after { content: " ✓✓"; color: var(--tick-read); }

/* Medien-Nachrichten */
.msg.media { padding: 4px; }
.msg.media img, .msg.media video {
  display: block;
  width: 100%;
  max-width: 320px;
  border-radius: var(--media-radius);
  cursor: pointer;
}
.msg .caption { padding: 5px 5px 2px; }
.msg.media .time { padding-right: 5px; }

/* Sprachnachricht */
.voice {
  display: flex; align-items: center; gap: 10px;
  min-width: 210px; padding: 4px 6px;
}
.voice button {
  width: 38px; height: 38px;
  border-radius: var(--voice-btn-radius);
  border: none;
  background: var(--voice-btn-bg);
  color: var(--voice-btn-text); font-size: 16px;
  cursor: pointer;
  flex-shrink: 0;
}
.voice .wave {
  flex: 1; display: flex; align-items: center; gap: 2px; height: 26px;
}
.voice .wave span {
  width: 3px; border-radius: var(--voice-wave-radius);
  background: var(--voice-wave);
}
.voice.playing .wave span { background: var(--voice-wave-active); }
.voice .dur { font-size: 12px; color: var(--voice-dur); }

/* Dokument (PDF) */
.doc {
  display: flex; align-items: center; gap: 10px;
  background: var(--doc-bg); border-radius: var(--doc-radius);
  padding: 10px; min-width: 220px;
  text-decoration: none; color: var(--doc-text);
}
.doc .doc-icon { font-size: 28px; }
.doc .doc-name { font-weight: var(--doc-name-weight); font-size: 13.5px; }
.doc .doc-meta { font-size: 12px; color: var(--doc-meta-text); }

/* System-Hinweis (z.B. Spielende) */
.sysmsg {
  align-self: center;
  background: var(--sysmsg-bg);
  color: var(--sysmsg-text);
  font-size: 12.5px;
  padding: 5px 12px;
  border-radius: var(--sysmsg-radius);
  margin: 8px 0;
  box-shadow: 0 1px 1px var(--shadow-sysmsg);
}

/* Tipp-Indikator */
.typing {
  align-self: flex-start;
  background: var(--typing-bg);
  border-radius: var(--typing-radius); border-top-left-radius: 0;
  padding: 12px 14px;
  display: flex; gap: 4px;
  box-shadow: 0 1px 1px var(--shadow-bubble);
}
.typing span {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--typing-dot);
  animation: blink 1.2s infinite;
}
.typing span:nth-child(2) { animation-delay: .2s; }
.typing span:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 60%, 100% { opacity: .3; } 30% { opacity: 1; } }

/* ---------- Antwortauswahl ---------- */
.choices {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 12px;
  background: transparent;
}
.choices:not(:empty) { padding: 8px 12px; }
.choice-btn {
  flex: 1 1 40%;
  background: var(--choice-bg);
  border: var(--choice-border-width) solid var(--choice-border);
  color: var(--choice-text);
  font-weight: var(--choice-weight);
  font-size: 14px;
  padding: 10px 14px;
  border-radius: var(--choice-radius);
  cursor: pointer;
  transition: background .15s;
}
.choice-btn:hover { background: var(--choice-bg-hover); }

/* Hilfs-Buttons (Tipp/Lösung): dezenter als die Story-Buttons */
.choice-btn.help-btn {
  flex: 0 1 auto;
  border-color: var(--help-border);
  color: var(--help-text);
  background: var(--help-bg);
  font-weight: var(--help-weight);
  font-size: 13px;
  padding: 8px 14px;
  border-width: var(--help-border-width);
  border-radius: var(--help-radius);
}
.choice-btn.help-btn:hover { background: var(--help-bg-hover); }

/* URS-078 (20.09.2026): Die Lösung darf sich vom Tipp absetzen. Die Klasse
   kommt aus der Engine und hängt daran, ob der Hilfs-Button ein Ziel hat.
   Alle Werte zeigen in variablen.css von Haus aus auf die Tipp-Werte —
   ohne eine Einstellung im Design-Reiter ändert sich also NICHTS. */
.choice-btn.help-btn.solution-btn {
  border-color: var(--solution-border);
  color: var(--solution-text);
  background: var(--solution-bg);
  font-weight: var(--solution-weight);
  border-width: var(--solution-border-width);
  border-radius: var(--solution-radius);
}
.choice-btn.help-btn.solution-btn:hover { background: var(--solution-bg-hover); }

/* Geheime-Bibliothek-Button: eigener Look (dunkles Buchbraun) */
.choice-btn.library-btn {
  flex: 0 1 auto;
  border-color: var(--library-border);
  color: var(--library-text);
  background: var(--library-bg);
  font-weight: var(--library-weight);
  font-size: 13px;
  padding: 8px 14px;
  border-width: var(--library-border-width);
  border-radius: var(--library-radius);
}
.choice-btn.library-btn:hover { background: var(--library-bg-hover); }

/* Auswahl-Hub: Zähler-Zeile + Options-Buttons (Petrol), besuchte gedimmt */
.hub-status {
  flex: 1 1 100%;
  text-align: center;
  font-size: 12.5px;
  color: var(--hub-status-text);
  padding: 2px 0;
}
.choice-btn.hub-btn {
  border-color: var(--hub-border);
  color: var(--hub-text);
  background: var(--hub-bg);
  border-width: var(--hub-border-width);
  border-radius: var(--hub-radius);
  font-weight: var(--hub-weight);
}
.choice-btn.hub-btn:hover { background: var(--hub-bg-hover); }
.choice-btn.hub-btn.visited {
  border-color: var(--hub-visited-border);
  color: var(--hub-visited-text);
  background: var(--hub-visited-bg);
  font-weight: var(--hub-visited-weight);
}
.choice-btn.hub-continue {
  flex: 1 1 100%;
  background: var(--continue-bg);
  border-color: var(--continue-border);
  color: var(--continue-text);
  border-width: var(--continue-border-width);
  border-radius: var(--continue-radius);
  font-weight: var(--continue-weight);
}
.choice-btn.hub-continue:hover { background: var(--continue-bg-hover); }

/* ---------- Eingabezeile ---------- */
.input-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--inputbar-bg);
  flex-shrink: 0;
}
.input-bar input {
  flex: 1;
  border: none;
  outline: none;
  background: var(--input-bg);
  border-radius: var(--input-radius);
  padding: 11px 16px;
  font-size: 15px;
}
.input-bar input:disabled { background: var(--input-disabled-bg); color: var(--input-disabled-text); }
.input-bar button {
  width: 44px; height: 44px;
  border-radius: var(--send-radius);
  border: none;
  background: var(--send-bg);
  color: var(--send-text);
  font-size: 18px;
  cursor: pointer;
  flex-shrink: 0;
}
.input-bar button:disabled { background: var(--send-disabled-bg); cursor: default; }

/* ---------- Bildbereich-Rätsel: Vollbild-Ansicht (URS-038) ----------
   Liegt wie der Login über dem ganzen Handy-Rahmen: auf dem Handy also
   echtes Vollbild, auf dem Desktop formatfüllend im Rahmen. Das Bild
   wird per CSS-Transform gezoomt und geschoben; die Trefferprüfung
   rechnet immer mit Anteilen des Bildes, nicht mit Pixeln – deshalb
   spielt die Zoomstufe für die Lösung keine Rolle. */
.hotspot-view {
  position: absolute;
  inset: 0;
  z-index: 12;
  display: none;
  flex-direction: column;
  background: var(--hs-bg);
}
.hotspot-view.open { display: flex; }

.hs-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--hs-bar-bg);
  flex-shrink: 0;
}
.hs-hint {
  flex: 1;
  color: var(--hs-hint-text);
  font-size: 13px;
  line-height: 1.3;
  text-align: center;
}
.hs-bar button {
  width: 38px; height: 38px;
  flex-shrink: 0;
  border: none;
  border-radius: var(--hs-btn-radius);
  background: var(--hs-btn-bg);
  color: var(--hs-btn-text);
  font-size: 17px;
  cursor: pointer;
}
.hs-bar button:hover { background: var(--hs-btn-bg-hover); }
.hs-bar button:disabled { opacity: .35; cursor: default; }

/* Die Bühne fängt alle Zeiger-Ereignisse ab: Ziehen = schieben,
   zwei Finger = zoomen, kurzes Tippen = antworten.
   touch-action: none schaltet die Browser-eigene Gesten-Auswertung ab –
   ohne das scrollt der Browser die Seite, statt das Bild zu schieben. */
.hs-stage {
  flex: 1;
  position: relative;   /* Bezugsrahmen für den Tipp-Kringel .hs-ping */
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  cursor: crosshair;
  user-select: none;
}
.hs-stage img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transform-origin: center center;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;   /* die Bühne wertet die Zeiger aus, nicht das Bild */
}

/* Kurze Rückmeldung an der angetippten Stelle: Ohne sie ist nicht zu
   erkennen, ob der Tipp überhaupt angekommen ist – die Reaktion kommt
   erst eine Anfrage später im Chat. */
.hs-ping {
  position: absolute;
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border: 2px solid var(--hs-ping);
  border-radius: var(--ping-radius);
  pointer-events: none;
  animation: hs-ping .45s ease-out forwards;
}
@keyframes hs-ping {
  from { transform: scale(.4); opacity: 1; }
  to   { transform: scale(1.4); opacity: 0; }
}

/* ============================================================
   Tablet und Desktop (URS-028) — 18.09.2026
   ============================================================
   Bis hierher galt EINE Ansicht für jede Bildschirmbreite: ein 460 px
   schmaler Handy-Rahmen, auf dem Desktop mittig, links und rechts daneben
   leere Fläche.

   ALLES, was hier unten steht, gilt NUR ab den genannten Breiten. Oberhalb
   dieser Datei ist keine Zeile angefasst worden — auf dem Handy sieht das
   Spiel deshalb aus wie vorher. Belegt mit
   `node tools/css-vergleich.js <alt.css> <neu.css> --ohne-media`.

   DER GEDANKE DAHINTER — beim zweiten Anlauf korrigiert:
   Der erste Versuch begrenzte den RAHMEN (erst 680, dann 1000 px). Damit
   blieb auf einem 1920er Bildschirm links und rechts eine handbreite leere
   Fläche stehen. Begrenzt gehört aber nicht der Rahmen, sondern die
   LESEBREITE DES TEXTES: Der Hintergrund darf den Bildschirm füllen, die
   Chatblasen bleiben trotzdem lesbar. Genau das macht `--chat-max` weiter
   oben zusammen mit der Formel in ①.

   Der Gewinn ist nicht nur optisch: Eine feste Rahmenbreite ist eine Zahl,
   die man für jede neue Gerätegröße neu raten muss. Eine Lesebreite gilt
   überall — sie hängt an der Schrift, nicht am Bildschirm.

   Zwei Stufen, mehr braucht es nicht:

   ① Ab 768 px fällt der Handy-Rahmen weg. Die Seite füllt den Bildschirm,
      der Text bleibt in einer zentrierten Spalte von höchstens `--chat-max`.
      Dazwischen gibt es KEINE weitere Stufe — die Formel wächst stufenlos
      mit, vom kleinen Tablet bis zum breiten Monitor.

   ② Ab 1000 px kommt die Seitenspalte dazu. Diese eine Zahl ist nötig, weil
      Rucksack und Galerie darunter schlicht nicht mehr danebenpassen. Das
      ist der einzige echte Unterschied zwischen Tablet und Desktop.

   Der Kern der Entscheidung ① des Teams ist nicht die Breite, sondern das
   Ende des Zudeckens: Rucksack und Galerie lagen als Overlay ÜBER dem Chat.
   Wer ein Item ansah, verdeckte damit genau die Frage, zu der es gehört.
   ============================================================ */

/* ---------- ① Ab Tablet: kein Rahmen mehr, nur noch eine Lesebreite ---------- */
@media (min-width: 768px) {

  .phone { max-width: none; }

  /* Die Formel, die alles trägt: Der seitliche Rand ist die Hälfte dessen,
     was über die Lesebreite hinausgeht. Bleibt nichts übrig — auf einem
     schmalen Tablet oder in der Spalte neben dem Rucksack — greift `max()`
     und es bleibt beim bisherigen Rand. Der Chat-Hintergrund samt Punktmuster
     füllt dabei die ganze Fläche; die Blasen sitzen in der Mitte.

     `.choices:not(:empty)` muss ausdrücklich mitstehen: Diese Regel ist
     spezifischer als `.choices` und würde die Formel sonst überstimmen,
     egal wie weit unten sie steht. */
  .chat,
  .choices,
  .choices:not(:empty) { padding-inline: max(12px, (100% - var(--chat-max)) / 2); }
  .input-bar           { padding-inline: max(10px, (100% - var(--chat-max)) / 2); }

  /* 78 % der Lesebreite wären rund 550 px Textbreite — zu viel, um bequem
     zu lesen. 65 % ergeben etwa 450 px und damit ungefähr dieselbe
     Zeilenlänge wie auf dem Handy. Bilder dürfen dagegen größer werden. */
  .msg { max-width: 65%; }
  .msg.media img,
  .msg.media video { max-width: 420px; }
}

/* ---------- ② Ab Desktop: Seitenspalte ---------- */
@media (min-width: 1000px) {

  /* Der Merker, den `layoutBreit()` in js/engine.js liest. Die 1000 px
     stehen nur hier — nicht ein zweites Mal im JavaScript. */
  :root { --layout: breit; }

  /* Aus der Spalte wird ein Raster. Die Kopfzeile geht über beide Spalten,
     Chat / Antwortauswahl / Eingabezeile bleiben zusammen links, die
     Seitenspalte läuft rechts über alle drei Zeilen durch.
     `.login` und `.hotspot-view` sind absolut gesetzt und stehen deshalb
     weiterhin über ALLEM, Seitenspalte eingeschlossen — genau richtig:
     Der Anmeldebildschirm soll nichts durchscheinen lassen, und das
     Bildbereich-Rätsel ist Vollbild. */
  .phone {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--sidebar-width);
    grid-template-rows: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      "kopf    kopf"
      "chat    spalte"
      "wahl    spalte"
      "eingabe spalte";
  }
  .chat-header { grid-area: kopf; }
  .choices     { grid-area: wahl; }
  .input-bar   { grid-area: eingabe; }

  /* `min-height: 0` ist hier nicht Kosmetik: Ohne sie wächst eine
     1fr-Zeile mit ihrem Inhalt mit, statt ihn scrollen zu lassen — der
     Chat schöbe dann die Eingabezeile aus dem Bild. */
  .chat { grid-area: chat; min-height: 0; }

  /* Aus `display: contents` wird eine echte Spalte. */
  .sidebar {
    grid-area: spalte;
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
    overflow-y: auto;
    padding: 12px;
    background: var(--sidebar-bg);
    border-left: 1px solid var(--sidebar-border);
  }

  /* Aus dem schwebenden Overlay wird eine Karte in der Spalte.
     `!important` steht hier, weil js/engine.js die Panels über
     `style.display` ein- und ausblendet — ein Inline-Wert, den eine
     gewöhnliche Regel nicht überstimmt. Die Alternative wäre gewesen, die
     Engine auf Klassen umzubauen; das hätte an fünf Stellen eingegriffen,
     um dasselbe zu erreichen. Die beiden Umschalt-Knöpfe in der Kopfzeile
     verschwinden dafür (siehe unten) – sonst schalteten sie etwas um, das
     ohnehin dauerhaft zu sehen ist. */
  .sidebar .backpack {
    display: block !important;
    position: static;
    top: auto;
    right: auto;
    width: auto;
    max-height: none;
    box-shadow: 0 1px 2px var(--shadow-bubble);
  }
  .sidebar .gallery-panel { width: auto; }

  /* Die Galerie hat jetzt Platz – in der Spalte sind die Bilder das, was
     man wirklich ansehen will, nicht nur ein Beleg dafür, dass es sie gibt. */
  .gal-item img { height: 110px; }

  /* 🎒 und 🖼 fallen weg, ⟳ und ⏻ bleiben. */
  #btn-gallery,
  #btn-backpack { display: none !important; }
}
