/* ══════════════════════════════════════════════════════════════════════════
   sq-sprache.css — IF1 (2026-09-15): die neue Formsprache als ZUSAETZLICHE
   Schicht ueber der Lobby.

   🚨 DIE REGEL DIESER DATEI: hier steht NUR, was hinter dem Schalter
   `body.sq-sprache` haengt. Keine einzige Regel in game-v3.css wurde geaendert
   oder geloescht — wer den Schalter ausschaltet, sieht exakt den Bildschirm von
   heute. Marcel, 15.09.: „wir ersetzen nicht, wir bauen um."

   Jede Regel hier beginnt mit `body.sq-sprache #screen-lobby` (oder
   `body.sq-sprache` fuer die Farbwerte). Das ist Absicht und keine Umstaend-
   lichkeit: der Vorfahre IST der Schalter, und der Bildschirmbezug haelt die
   Runde bei der Lobby.

   Die Rollenteilung, aus mockups/bildschirme-neue-sprache.html uebersetzt:
       GOLD  = Struktur und Besitz  (das Gehaeuse, der Rahmen, was DA ist)
       CYAN  = Energie und das Anklickbare (was ANTWORTET)
   Nie beide fuer dasselbe. Deshalb ruht der Knopf golden und wird unter dem
   Finger cyan — nicht heller gold.
   ══════════════════════════════════════════════════════════════════════════ */

body.sq-sprache {
    --sq-gold:     #f0b429;
    --sq-goldRGB:  240, 180, 41;
    --sq-cyan:     #2dd4bf;
    --sq-cyanRGB:  45, 212, 191;
    --sq-cyanHell: #7fe6d6;
}

/* ── 1. Der Menueknopf ──────────────────────────────────────────────────────
   Die Eckabschnitte gibt es seit Fix I1 bereits (clip-path-Chamfer) — neu sind
   der GOLDENE Balken links (heute grau), der Gefahrenstreifen oben rechts und
   die Indexnummer.

   Der Gefahrenstreifen ist ein HINTERGRUNDBILD, kein zusaetzliches Element:
   `.menu-btn::after` ist von der Tick-Kerbe belegt und `::before` traegt gleich
   die Indexnummer. Ein drittes Pseudo-Element gibt es nicht, ein neues DOM-
   Element waere ein Markup-Umbau gewesen — verboten in dieser Runde. */
body.sq-sprache #screen-lobby .menu-btn {
    --mb-chamfer: 20px;
    --mb-edge: rgba(var(--sq-goldRGB), 0.78);
    background-color: rgba(4, 8, 16, 0.80);
    background-image: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.70) 0 3px, transparent 3px 7px);
    background-repeat: no-repeat;
    background-position: right 30px top 0;
    background-size: 34px 8px;
    color: var(--sq-gold);
    padding-left: 34px;            /* Platz fuer die Indexnummer, symmetrisch … */
    padding-right: 34px;           /* … damit die Beschriftung mittig bleibt      */
    transition: background-color 0.15s ease, border-color 0.15s ease,
                color 0.15s ease, box-shadow 0.15s ease;
}
body.sq-sprache #screen-lobby .menu-btn .menu-arrow {
    color: rgba(var(--sq-goldRGB), 0.75);
}
body.sq-sprache #screen-lobby .menu-btn .menu-btn-sub {
    color: rgba(var(--sq-goldRGB), 0.42);
}

/* Die Indexnummer (001, 002 …) — OHNE eine einzige Aenderung am Markup.
   Ein CSS-Zaehler je Menue-Ebene zaehlt die Knoepfe; `decimal-leading-zero`
   liefert zwei Stellen, die fuehrende "0" im content macht drei daraus
   (9 -> "0"+"09" = 009, 10 -> "0"+"10" = 010).
   Zurueck- und Beenden-Knoepfe zaehlen NICHT mit: sie sind kein Menuepunkt,
   sondern ein Ausgang. Verborgene Knoepfe (`display:none`) erhoehen den
   Zaehler nach CSS-Spezifikation ohnehin nicht — genau richtig, denn im
   Browser ist „Mit Steam anmelden" unsichtbar. */
body.sq-sprache #screen-lobby .menu-level { counter-reset: sq-idx; }
body.sq-sprache #screen-lobby .menu-btn:not(.back-btn):not(.menu-btn-quit) {
    counter-increment: sq-idx;
}
body.sq-sprache #screen-lobby .menu-btn:not(.back-btn):not(.menu-btn-quit)::before {
    content: "0" counter(sq-idx, decimal-leading-zero);
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-cyanRGB), 0.62);
    pointer-events: none;
}

/* ── 2. Die Farbrolle: unter dem Finger wird der Knopf CYAN ─────────────────
   Das ist der eigentliche Kern der Sprache (Prompt, Abschnitt 3, Punkt 2) —
   nicht die Eckabschnitte. Gold sagt „der Knopf ist da", Cyan sagt „er
   antwortet". Dieselbe Rolle, die Cyan im Spiel schon hat (Ladering,
   Kommandoknopf im Zustand „bereit"). */
body.sq-sprache #screen-lobby .menu-btn:hover,
body.sq-sprache #screen-lobby .menu-btn:focus-visible {
    --mb-edge: var(--sq-cyan);
    border-left-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
    background-color: rgba(var(--sq-cyanRGB), 0.14);
    background-image: repeating-linear-gradient(115deg,
        rgba(var(--sq-cyanRGB), 0.80) 0 3px, transparent 3px 7px);
    box-shadow: 0 0 18px -4px rgba(var(--sq-cyanRGB), 0.55);
    text-shadow: 0 0 10px rgba(var(--sq-cyanRGB), 0.35);
}
body.sq-sprache #screen-lobby .menu-btn:hover .menu-arrow,
body.sq-sprache #screen-lobby .menu-btn:focus-visible .menu-arrow {
    color: var(--sq-cyanHell);
    text-shadow: 0 0 8px rgba(var(--sq-cyanRGB), 0.6);
}
body.sq-sprache #screen-lobby .menu-btn:hover .menu-btn-sub,
body.sq-sprache #screen-lobby .menu-btn:focus-visible .menu-btn-sub {
    color: rgba(var(--sq-cyanRGB), 0.75);
}
body.sq-sprache #screen-lobby .menu-btn:hover::before,
body.sq-sprache #screen-lobby .menu-btn:focus-visible::before {
    color: var(--sq-cyanHell);
}

/* Zurueck-Knopf: bleibt zurueckgenommen, folgt aber derselben Regel — unter
   dem Finger cyan, nicht gold. Heute wird er beim Ueberfahren gold, und das
   waere in der neuen Sprache die falsche Aussage (Gold = Besitz, nicht
   Antwort). Kein Streifen, keine Nummer: ein Ausgang ist kein Menuepunkt. */
body.sq-sprache #screen-lobby .menu-btn.back-btn {
    --mb-edge: rgba(var(--sq-goldRGB), 0.30);
    background-image: none;
    padding-left: 20px;
    padding-right: 20px;
    color: #6a7090;
}
body.sq-sprache #screen-lobby .menu-btn.back-btn:hover {
    --mb-edge: var(--sq-cyan);
    color: var(--sq-cyanHell);
    background-color: rgba(var(--sq-cyanRGB), 0.10);
    background-image: none;
    text-shadow: 0 0 10px rgba(var(--sq-cyanRGB), 0.3);
}
/* Beenden bleibt rot — Gefahr ist eine eigene Rolle und wird nicht eingefaerbt. */
body.sq-sprache #screen-lobby .menu-btn.menu-btn-quit {
    background-image: none;
    padding-left: 20px;
    padding-right: 20px;
}

/* ── 3. Der Titel ──────────────────────────────────────────────────────────
   Zwei Toene, eine Zeile. Die Aufteilung in zwei Haelften kann CSS allein
   nicht: sie braucht zwei Elemente. Die setzt sq-sprache.js zur LAUFZEIT und
   nur bei eingeschaltetem Schalter — im Markup (`views/play-v3.ejs`) steht
   davon nichts, und mit ausgeschaltetem Schalter steht die Ueberschrift
   unveraendert da. */
body.sq-sprache #screen-lobby .lobby-title {
    color: var(--sq-gold);
    /* EINE Zeile. Die Ueberschrift steht in `#lobby-main`, und das ist per
       layout-config.js auf 400 px festgenagelt (`overflow-x:hidden`) — sie MUSS
       also hineinpassen, statt dagegen anzuschreiben. Bei 24 px brach sie um.
       Klein und gesperrt ist zugleich naeher an der Vorlage: dort steht unter
       dem grossen Schriftzug eine schmale Zeile „Trading Card Game · v0.7.370",
       und genau diese Rolle hat der Kickstarter-Zusatz hier. */
    font-size: 13px;
    letter-spacing: 0.24em;
    white-space: nowrap;
    line-height: 1.2;
    margin-top: 2px;
}
body.sq-sprache #screen-lobby .lobby-title br { display: none; }
body.sq-sprache #screen-lobby .lobby-title .sq-titel-a { color: #ffffff; }
body.sq-sprache #screen-lobby .lobby-title .sq-titel-b { color: var(--sq-gold); }
body.sq-sprache #screen-lobby .lobby-title .sq-titel-trenn {
    color: rgba(var(--sq-goldRGB), 0.55);
    padding: 0 0.45em;
}

/* Die Beschriftungen ueber den Eingabefeldern gehoeren zum Gehaeuse — gold. */
body.sq-sprache #screen-lobby .menu-label { color: rgba(var(--sq-goldRGB), 0.70); }
body.sq-sprache #screen-lobby .menu-input:focus {
    border-color: var(--sq-cyan);
    box-shadow: 0 0 12px -4px rgba(var(--sq-cyanRGB), 0.6);
}

/* ── 4. Die Leitbahnen ─────────────────────────────────────────────────────
   Die Flaeche selbst. Sie faengt NICHTS ab (`pointer-events:none`) und liegt
   UNTER der Bedienung: `.lobby-main` hat z-index 2, `#lobby-ship-container`
   hat 0 — die Bahnen sitzen dazwischen. Das Element entsteht nur, wenn der
   Schalter an ist (sq-sprache.js), deshalb gibt es im Aus-Zustand weder
   Canvas noch Bildschleife. */
body.sq-sprache #screen-lobby #sq-bahnen {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    z-index: 1;
    pointer-events: none;
}

/* ── 5. Der Pre-Enlist-Kasten ───────────────────────────────────────────────
   II1 (2026-09-16). 🚨 UMBAU, KEIN NEUBAU: die drei Elemente im Kasten sind
   woertlich dieselben DOM-Knoten, die die Lobby schon hat —
   `#lobby-promo-banner` (seit 17.07.), `#lobby-discord-btn` (seit 17.07.) und
   `#lobby-steam-btn` (seit BE1, 20.08.). sq-sprache.js haengt sie beim
   Einschalten in `#sq-preenlist` um und beim Ausschalten zurueck; keiner von
   ihnen wird erzeugt, ersetzt oder in seiner Verlinkung angefasst.

   Was hier steht, ist ausschliesslich ihre KLEIDUNG. Aussenmasse des Kastens
   selbst stehen in layout-config.js (IG1: die Formsprache aendert keine
   gefuehrten Aussenmasse) — hier kein width/height mit !important, kein
   min-/max-width, kein min-/max-height. */

body.sq-sprache #screen-lobby #sq-preenlist {
    /* Sichtbar nur im Hauptmenue — dieselbe Bedingung, unter der die drei
       Elemente heute schon erscheinen (game-v3.css, `:has(#menu-main.active)`).
       Sie wird hier WIEDERHOLT und nicht geerbt: der Kasten ist ein eigenes
       Element und faellt sonst in den Untermenues nicht mit weg. */
    display: none;
    position: relative;
    box-sizing: border-box;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-cyanRGB), 0.45);   /* Vorlage: der Community-
        Kasten ist der einzige mit cyanem statt goldenem Rahmen */
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    overflow: hidden;
    z-index: 3;                 /* ueber den Leitbahnen (1), wie .lobby-main (2) */
}
body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist {
    display: flex;
    flex-direction: column;
}
/* Der goldene Balken links und der Gefahrenstreifen oben rechts — dieselben
   zwei Pseudo-Elemente wie an jedem Rahmen der Vorlage (.fui::before/::after). */
body.sq-sprache #screen-lobby #sq-preenlist::before {
    content: ''; position: absolute; left: -1px; top: 14px;
    width: 3px; height: 34px; background: var(--sq-cyan);
}
body.sq-sprache #screen-lobby #sq-preenlist::after {
    content: ''; position: absolute; right: 8px; top: -1px;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-cyanRGB), 0.85) 0 4px, transparent 4px 9px);
}

/* Kopfzeile mit Indexnummer. 🚨 Die Nummer ist HART und kein CSS-Zaehler:
   der Zaehler aus Abschnitt 1 laeuft ueber `.menu-level` und zaehlt Menue-
   knoepfe; dieser Kasten steht ausserhalb jeder Menue-Ebene. */
body.sq-sprache #screen-lobby #sq-preenlist .sq-kasten-kopf,
body.sq-sprache #screen-lobby #sq-status .sq-kasten-kopf,
body.sq-sprache #screen-lobby #sq-roadmap .sq-kasten-kopf {
    flex: none;
    padding: 8px 14px 7px;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--sq-cyanHell);
    border-bottom: 1px solid rgba(var(--sq-cyanRGB), 0.28);
    display: flex;
    justify-content: space-between;
    align-items: center;
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-kasten-idx,
body.sq-sprache #screen-lobby #sq-status .sq-kasten-idx {
    font-size: 9px;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-cyanRGB), 0.62);
}

/* Rumpf: links die Figur, rechts der Text — wie im Kickstarter-Banner. */
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-rumpf {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    align-items: stretch;
}

/* Die BB. Sie steht mit der Unterkante auf der Kastenkante auf und darf oben
   herausragen — genau dafuer wurde sie in IE1 freigestellt (545x1066, der
   Schnitt sitzt im BILD, nicht im CSS). Der cyane Hof unter ihr ist die
   Lichtquelle, kein Rahmen. */
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-bild {
    flex: none;
    width: 132px;
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-hof {
    position: absolute; left: 50%; top: 52%;
    width: 170px; height: 170px;
    transform: translate(-50%, -50%);
    pointer-events: none;
    background: radial-gradient(circle,
        rgba(var(--sq-cyanRGB), 0.26) 0%,
        rgba(var(--sq-cyanRGB), 0.09) 44%, transparent 70%);
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-bild img {
    position: relative;
    z-index: 1;
    display: block;
    height: 252px;              /* EINE Zahl steuert die Groesse (IE1) */
    width: auto;
    filter: drop-shadow(0 0 20px rgba(var(--sq-cyanRGB), 0.40))
            drop-shadow(0 5px 10px rgba(2, 4, 10, 0.80));
}

body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-text {
    flex: 1 1 auto;
    min-width: 0;
    padding: 10px 14px 12px 2px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-titel {
    font-size: 13px;
    letter-spacing: 0.06em;
    line-height: 1.4;
    color: var(--sq-cyanHell);
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-titel b {
    color: var(--sq-gold);
    font-weight: 700;
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-punkte {
    margin-top: 9px;
    font-size: 10.5px;
    line-height: 1.7;           /* LO1: 1.85 -> 1.7, Platz fuer die vierte Knopfzeile */
    color: #aab4c2;
}
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-punkte div::before {
    content: '\25B8\00a0';                      /* ▸ — Zeichen, kein Text */
    color: rgba(var(--sq-goldRGB), 0.75);
}

/* ── Die drei vorhandenen Elemente, umgekleidet ─────────────────────────────
   Ab hier wird NICHTS erzeugt: jede Regel kleidet einen Knoten, den es seit
   Monaten gibt. Sie stehen im Kasten nebeneinander statt einzeln auf der
   Buehne — deshalb `position:static`. Das darf CSS hier, weil sq-sprache.js
   die von der Layout-Engine geschriebenen Inline-Stile vorher RAEUMT (und
   beim Ausschalten `applyLayout('lobby')` sie wieder setzt); ein
   `!important` waere der stille Weg an der Engine vorbei, den IG1 verbietet. */
/* LO1: seit dem Livestream-Knopf stehen VIER Knoepfe untereinander. Der Kasten
   ist gefuehrt (400x300, narrow 360x280) und bleibt es — Platz schafft die
   Kleidung: Abstand 12 -> 10, Luecke 6 -> 5, Knopf-Innenabstand 6 -> 5 und die
   Punkteliste etwas enger. Gemessen (scripts/lo1-nachweis.js, Fall 15): ohne das
   lief die Textspalte in narrow ueber (Luft oben -6, unten -3), bei 16:9 blieben
   oben 4 px. */
body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-knoepfe {
    margin-top: 10px;
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
    align-items: center;
}

/* Gemeinsame Knopfform der Vorlage (.knopf.klein) fuer alle drei. */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-promo-banner,
body.sq-sprache #screen-lobby #sq-preenlist .lobby-discord-btn,
body.sq-sprache #screen-lobby #sq-preenlist .lobby-steam-btn,
body.sq-sprache #screen-lobby #sq-preenlist .lobby-twitch-btn {
    position: static;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    box-sizing: border-box;
    padding: 5px 11px;
    border-radius: 0;
    border-width: 1px;
    border-style: solid;
    font-family: 'Orbitron', sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
    opacity: 1;
    transform: none;
    clip-path: polygon(0 8px, 8px 0, calc(100% - 12px) 0, 100% 12px,
                       100% 100%, 12px 100%, 0 calc(100% - 12px));
    transition: background 0.15s ease, border-color 0.15s ease,
                color 0.15s ease, box-shadow 0.15s ease;
}

/* Pre-Enlist: der EINZIGE Knopf, der von sich aus leuchtet (.knopf.bereit).
   Sein Bild tritt im Kasten zurueck — es wird NICHT entfernt, nur verborgen,
   und kommt beim Ausschalten unveraendert wieder. */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-promo-banner {
    border-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
    background: rgba(var(--sq-cyanRGB), 0.12);
    animation: sqBereitPuls 2.4s ease-in-out infinite;
}
body.sq-sprache #screen-lobby #sq-preenlist .lobby-promo-banner img { display: none; }
/* Der Pfeil als Zeichen im Stylesheet — nicht als Textknoten (s. sq-sprache.js). */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-promo-banner .sq-pe-knopf-text::after {
    content: '\00a0\25B8';
    color: rgba(var(--sq-cyanRGB), 0.85);
}
body.sq-sprache #screen-lobby #sq-preenlist .lobby-promo-banner:hover {
    background: rgba(var(--sq-cyanRGB), 0.22);
    color: #ffffff;
    filter: none;
}
@keyframes sqBereitPuls {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--sq-cyanRGB), 0.34); }
    50%      { box-shadow: 0 0 20px -2px rgba(var(--sq-cyanRGB), 0.60); }
}

/* Discord und Steam behalten ihre Hausfarbe — sie sind fremde Marken, und die
   Formsprache faerbt keine fremde Marke um. Nur die FORM wird angeglichen. */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-discord-btn {
    border-color: rgba(88, 101, 242, 0.75);
    color: #9aa6ff;
    background: rgba(88, 101, 242, 0.10);
}
body.sq-sprache #screen-lobby #sq-preenlist .lobby-steam-btn {
    border-color: rgba(155, 176, 196, 0.75);
    color: #cdd8e4;
    background: rgba(155, 176, 196, 0.10);
}
/* LO1: der Livestream-Knopf — dieselbe Regel wie Discord und Steam: eine fremde
   Marke behaelt ihre Hausfarbe (Twitch-Violett), nur die FORM wird angeglichen.
   Er steht unter dem Steam-Knopf (vierter in der Reihe, bricht um). Die Regel
   `display:inline-flex` oben macht ihn hier sichtbar; ausserhalb des Kastens
   bleibt er verborgen (game-v3.css). */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-twitch-btn {
    border-color: rgba(145, 70, 255, 0.75);
    color: #c4a6ff;
    background: rgba(145, 70, 255, 0.10);
    cursor: pointer;
}
body.sq-sprache #screen-lobby #sq-preenlist .lobby-twitch-btn:hover {
    background: rgba(145, 70, 255, 0.22);
    color: #ffffff;
}
/* Die Wortmarken-Symbole bleiben, nur kleiner. */
body.sq-sprache #screen-lobby #sq-preenlist .lobby-discord-icon,
body.sq-sprache #screen-lobby #sq-preenlist .lobby-steam-icon,
body.sq-sprache #screen-lobby #sq-preenlist .lobby-twitch-icon {
    width: 13px; height: 13px; flex-shrink: 0;
}

/* LO1: narrow (1/1 .. 6/5) — der Kasten ist dort 20 px niedriger (280), die vier
   Knopfzeilen brauchen dieselbe Hoehe. Die Punkteliste und die Innenabstaende der
   Textspalte werden enger; Schriftgroessen bleiben. */
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-text { padding: 6px 12px 7px 2px; }
    body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-punkte { margin-top: 6px; line-height: 1.5; }
    body.sq-sprache #screen-lobby #sq-preenlist .sq-pe-knoepfe { margin-top: 8px; }
}

/* Hochformat: `lobby.portrait` fuehrt nur `lobby-main` (CX1) — ein Kasten ohne
   Ankerwert stuende dort unpositioniert herum. Dieselbe Entscheidung, die
   game-v3.css fuer die drei Einzelelemente schon getroffen hat. */
@media (max-aspect-ratio: 1/1) {
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist { display: none; }
}


/* ── 6. Der Status-Kasten ───────────────────────────────────────────────────
   IJ1 (2026-09-16). Drei Zeilen, rechts der Wert. Er teilt sich Kopfzeile und
   Indexnummer mit dem Pre-Enlist-Kasten (Selektoren oben erweitert, nicht
   verdoppelt) und traegt den GOLDENEN Rahmen der Vorlage — cyan ist dort dem
   Community-Kasten vorbehalten.

   Die Farbregel, woertlich aus dem Prompt: ZAHLEN in Gold (Bestand, was da ist),
   "Bereit" in Cyan (Zustand, was antwortet). Nie beides fuer dasselbe. */

body.sq-sprache #screen-lobby #sq-status {
    display: none;
    position: relative;
    box-sizing: border-box;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-goldRGB), 0.34);
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    overflow: hidden;
    z-index: 3;
}
body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status {
    display: flex;
    flex-direction: column;
}
body.sq-sprache #screen-lobby #sq-status::before {
    content: ''; position: absolute; left: -1px; top: 14px;
    width: 3px; height: 34px; background: var(--sq-gold);
}
body.sq-sprache #screen-lobby #sq-status::after {
    content: ''; position: absolute; right: 8px; top: -1px;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
}
/* Geraetebeschriftung — im Stylesheet, weil ein Literal in textContent fuer den
   i18n-Waechter ein Anzeigetext waere (II1 hat so den Pfeil gefunden). */
body.sq-sprache #screen-lobby #sq-status .sq-kasten-idx::after { content: 'NET'; }

body.sq-sprache #screen-lobby #sq-status .sq-status-rumpf {
    flex: 1 1 auto;
    min-height: 0;
    padding: 4px 14px 6px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
body.sq-sprache #screen-lobby #sq-status .sq-status-zeile {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px 0;
    font-size: 11.5px;
    border-bottom: 1px solid rgba(139, 147, 168, 0.14);
}
body.sq-sprache #screen-lobby #sq-status .sq-status-zeile:last-child { border-bottom: none; }
body.sq-sprache #screen-lobby #sq-status .sq-status-name { color: #8b93a8; }
body.sq-sprache #screen-lobby #sq-status .sq-status-wert {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
/* GOLD = Bestand. */
body.sq-sprache #screen-lobby #sq-status .sq-status-zahl {
    color: var(--sq-gold);
    font-weight: 700;
    font-variant-numeric: tabular-nums;   /* die Zeile springt nicht bei 9 -> 10 */
}
body.sq-sprache #screen-lobby #sq-status .sq-status-dim { color: #8b93a8; }
/* Das Trennzeichen als Zeichen im Stylesheet, nicht als Textknoten.
   LS1: "X Spieler / X Games / X Spiele gegen Bot" — der Abstand kommt aus dem gap
   der Wertspalte. */
body.sq-sprache #screen-lobby #sq-status .sq-status-trenner::before { content: '/'; color: #8b93a8; }

/* Der Punkt neben "Online" — grau, solange niemand da ist; er leuchtet erst,
   wenn die Zahl es rechtfertigt. Eine Anzeige, die immer gruen ist, sagt nichts. */
body.sq-sprache #screen-lobby #sq-status .sq-status-punkt {
    display: inline-block;
    width: 7px; height: 7px;
    background: rgba(139, 147, 168, 0.45);
}
body.sq-sprache #screen-lobby #sq-status .sq-status-punkt.sq-status-punkt-an {
    background: var(--sq-cyan);
    box-shadow: 0 0 7px rgba(var(--sq-cyanRGB), 0.75);
}

/* CYAN = Zustand. Der einzige cyane Wert im Kasten. */
body.sq-sprache #screen-lobby #sq-status .sq-status-bereit { color: var(--sq-cyan); }
body.sq-sprache #screen-lobby #sq-status .sq-status-weg    { color: #d06060; }

/* Hochformat: wie beim Pre-Enlist-Kasten kein gefuehrter Ankerwert (lobby.portrait
   fuehrt nur lobby-main, Fund CX1) — also ausblenden statt unpositioniert stehen. */
@media (max-aspect-ratio: 1/1) {
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status { display: none; }
}


/* ── 7. Die Komposition: die Gruppe steht mittig ────────────────────────────
   IM1 (2026-09-16). Marcel: „einfach nur weiter nach links, damit Buttons und
   die beiden Kaesten mittig sind." Die Vorlage macht daraus ein zweispaltiges
   Gitter, das als GANZES mittig auf der Buehne steht
   (mockups/bildschirme-neue-sprache.html, Zeile 171: `max-width:1240px;
   margin:6px auto 0`).

   🚨 GERECHNET, NICHT GESCHOBEN. Die Gruppe steht heute so (gemessen,
   scripts/im1-messung.js) — W ist die BUEHNENbreite, nicht die Bildschirm-
   breite (sie klemmt bei 1280 und waechst bis 1920, s. layout-engine.js):

       Menuespalte  links = W/2 - 200      (Anker center, Pivot center, 400 breit)
       beide Kaesten rechts = W - 8        (Anker mid-right, Pivot mid-right)

   Gruppenmitte = 3W/4 - 104, Buehnenmitte = W/2. Der Versatz ist die Differenz:

       Versatz = W/2 - (3W/4 - 104) = 104px - W/4

   Ein fester Pixelwert taete es NICHT: bei 1280 waeren das -216, bei 1706
   (21:9) aber -323. Gemessen ueber 1280 .. 1720 Buehnen-px, Randdifferenz
   ueberall 0 (scripts/im1-versuch.js).

   🚨 WARUM `margin-left` UND NICHT `transform`. Beide ueberleben die Engine —
   `applyToElement()` schreibt position/left/top/width/height und leert
   right/bottom/min-width/min-height, sonst nichts (layout-anchors.js:123-135).
   Aber ein Prozentwert in `transform: translateX()` bezieht sich auf die
   EIGENE Breite des Elements, in `margin-left` dagegen auf die Breite des
   umgebenden Rahmens — und der ist hier gemessen `#screen-lobby`
   (position:relative) und exakt so breit wie die Buehne. Nur so laesst sich
   „W/4" ueberhaupt hinschreiben. `right` ist von der Engine geleert, also
   auto: der negative Rand verschiebt den Kasten und aendert seine Breite
   nicht (gemessen: 832 bzw. 1046 Buehnen-px vorher wie nachher).

   Kein `!important`, kein min-/max-width, keine Aenderung an layout-config.js —
   die gefuehrten Aussenmasse bleiben, wo sie hingehoeren (IG1, Weg A).

   ⚠ DIE BEDINGUNG IST DIESELBE WIE DIE DER KAESTEN. In den Untermenues sind
   beide Kaesten `display:none`; dort BESTEHT die Gruppe nur aus der
   Menuespalte, und die steht schon mittig. Wuerde der Versatz dort
   weitergelten, stuende die Spalte allein links der Mitte. Deshalb haengt er
   an `:has(#menu-main.active)` — an derselben Bedingung, unter der die Kaesten
   sichtbar sind, nicht an einer zweiten. Der Uebergang gleitet, damit der
   Wechsel eine Bewegung ist und kein Sprung.

   ⚠ Der Titelblock wandert mit, ohne eigene Regel: Logo, Untertitel und der
   Sprachumschalter stehen IN `#lobby-main` (views/play-v3.ejs, `.lobby-header`
   und `.lang-switch-wrap`). Eine halb verschobene Spalte ist hier strukturell
   nicht moeglich. */

body.sq-sprache #screen-lobby:has(#menu-main.active) #lobby-main,
body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status,
body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist {
    transition: margin-left 0.22s ease;
}

/* `narrow` (Seitenverhaeltnis 1.0 .. 1.2): die Menuespalte ist dort 360 breit,
   der Versatz also 104px -> (180+8)/2 = 94px. Die Buehne ist in diesem Band
   immer 1280 breit, aber die Rechnung bleibt dieselbe Form.
   🚨 Unter 1/1 steht KEINE Regel: dort sind beide Kaesten ausgeblendet (s.
   Abschnitt 5 und 6), die Gruppe ist wieder nur die Spalte, und die steht
   mittig. Ein Versatz haette sie ohne Grund nach links gezogen.
   Die Reihenfolge der beiden Bloecke ist Absicht: bei genau 1.2 treffen beide
   zu, der spaetere gewinnt — und 1.2 gehoert der Engine nach zu `default`
   (layout-engine.js, computeGeometry: `else if (ratio < 1.2) narrow`). */
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-main.active) #lobby-main,
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status,
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist {
        margin-left: calc(94px - 25%);
    }
}
@media (min-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-main.active) #lobby-main,
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status,
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist {
        margin-left: calc(104px - 25%);
    }
}

/* ── LP1 (2026-09-23): Menue und Roadmap ruecken an den rechten Kasten ──────
   Seit LO1 ist die Gruppe dreispaltig; IM1s Versatz haelt aber nur die Mitte
   der ZWEI alten Spalten. Ab einer Buehne ueber 1280 (Seitenverhaeltnis ueber
   16:9, z. B. ein Browserfenster mit Leisten) klafft deshalb zwischen Menue und
   Status-Kasten eine Luecke, die mit W waechst (W/2 - 608: 0 bei 1280 ueber
   der 32er-Fuge, 245 bei 21:9).

   🚨 DIE REGEL: die Lage der linken Gruppen ergibt sich aus der LINKEN KANTE
   DES RECHTEN KASTENS — nicht aus einer festen Zahl. Der Kasten selbst bleibt,
   wo er ist (Regel darueber unveraendert).
       Kastenkante  = W - 8 - 400 + (104px - 25%)   Anker mid-right -8, Breite
                                                     400 (layout-config.js),
                                                     IM1-Versatz
       Spalte links = Kastenkante - 32 - 400         32er-Fuge wie ueberall
       margin-left  = Spalte links - (W/2 - 200)     die Engine setzt die Spalte
                                                     mittig (Anker center)
   Bei W = 1280 ergibt das genau IM1s -216 — dort aendert sich nichts. Die
   Roadmap folgt der Spalte (Abschnitt 19). `%` ist die Buehnenbreite
   (`#screen-lobby`, gemessen IM1), die Variablen werden erst am Element
   aufgeloest.

   Weg A: `margin-left` ist kein gefuehrtes Mass (die Engine schreibt es
   nicht, s. IM1) — kein Eintrag in layout-config.js, kein !important. Nur im
   default-Band: narrow hat eine feste Buehne (1280), Hochformat und AUS-
   Zustand sind von diesen Selektoren nicht erfasst. */
@media (min-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby {
        --sq-kasten-kante: calc(100% - 408px + 104px - 25%);
        --sq-spalte-links: calc(var(--sq-kasten-kante) - 32px - 400px);
    }
    body.sq-sprache #screen-lobby:has(#menu-main.active) #lobby-main {
        margin-left: calc(var(--sq-spalte-links) - (50% - 200px));
    }
}


/* ── 8. Der Abdunkler hinter dem Titelblock ─────────────────────────────────
   IM1. Die Kulisse (`public/bg-space.jpg`) hat ihre Sonne oben links. Solange
   die Menuespalte mittig stand, war das kein Problem — nach der Verschiebung
   aus Abschnitt 7 steht der Schriftzug genau davor. Marcel: „wichtig ist, dass
   wir zur besseren Lesbarkeit dann vermutlich auch die Sonne wieder an der
   Logo-Stelle abdunkeln muessen."

   ⚠ NICHT DAS GANZE BILD. Die Kulisse ist bewusst hell; die Vorlage nimmt mit
   `#buehne::before` nur oben und unten einen Hauch. Was hier steht, ist der
   Schleier der Vorlage selbst (mockups/bildschirme-neue-sprache.html, Zeile
   174-177: „ein weicher dunkler Schleier, weil die Sonne der Kulisse genau
   dort steht und sonst blendet") — ein Verlauf, der zum Rand hin auf 0 geht
   und deshalb keine sichtbare Kante hat.

   Er haengt am Titelblock und nicht an der Buehne: so wandert er mit, wenn die
   Spalte sich verschiebt, und steht auch im Hochformat richtig. `::before` ist
   an `.lobby-header` frei (geprueft: game-v3.css kennt dort kein Pseudo-
   Element), `position:absolute` haelt ihn aus dem Flex-Fluss — sonst waere er
   ein fuenftes Flex-Kind und wuerde das Logo nach unten schieben. `z-index:-1`
   legt ihn hinter Logo und Schrift, aber innerhalb von `#lobby-main`
   (z-index:2) — er kann also nicht hinter die Kulisse fallen. */
body.sq-sprache #screen-lobby .lobby-header { position: relative; }
body.sq-sprache #screen-lobby .lobby-header::before {
    content: '';
    position: absolute;
    left: 50%; top: 50%;
    /* IW1 (2026-09-17): 130%/170% -> 220%/240%, Mitte 48% -> 56%.
       Marcel: „das Abdunkeln muss da ein bisschen groesser gemacht werden,
       damit das Wort ,Kickstarter' auch besser lesbar ist."
       GEMESSEN, warum: die Kickstarter-Zeile sitzt am UNTEREN Rand des
       Titelblocks (Mitte bei 94,5 % seiner Hoehe), der Schleier war aber auf
       dessen MITTE zentriert. An den Enden der Zeile lag der normierte
       Ellipsenradius bei 0,94 — jenseits des letzten Farbstopps (78 %), also
       Deckkraft 0. Genau dort steht die Kulisse am hellsten (Sonnenstrahl
       links, Planetenkante rechts): Kontrast 1,26:1 (scripts/iw1-messung.js).
       Die Ellipse ist deshalb breiter (sie muss die ganze Zeile fassen, nicht
       nur das Logo) und ihre Mitte tiefer (zwischen Logo und Zeile).
       ⚠ NICHT staerker in der Mitte — 0,90 statt 0,88 ist die einzige
       Aenderung am Kern. Was fehlte, war Reichweite, nicht Schwaerze.
       ⚠ Der letzte Stopp bleibt bei Deckkraft 0: eine Kante entsteht nur
       dort, wo ein Verlauf auf einen Wert > 0 endet. */
    width: 150%; height: 260%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: -1;
    background: radial-gradient(ellipse 50% 50% at 50% 55%,
        rgba(2, 4, 10, 0.90) 0%,
        rgba(2, 4, 10, 0.85) 55%,
        rgba(2, 4, 10, 0.45) 68%,
        rgba(2, 4, 10, 0) 77%);
}


/* ── 9. Das Atmen ──────────────────────────────────────────────────────────
   IM1. Marcel: „das Atmen, also die Idle-Animation der Buttons, fehlt noch."

   🚨 ZWEI VERSCHIEDENE BEWEGUNGEN, UND SIE DUERFEN SICH NICHT INS GEHEGE
   KOMMEN:
       Atmen     — sehr langsames Heben und Senken  -> ALLE vier Menuekaesten
       Pulsieren — der Rand leuchtet auf            -> GENAU EINER
   Das Pulsieren bleibt dem Pre-Enlist-Knopf (`sqBereitPuls`, Abschnitt 5).
   Wenn alles pulsiert, bedeutet Pulsieren nichts mehr — dieselbe Grenze, die
   FV1 fuer die Benachrichtigungsklaenge gezogen hat. Das Atmen hier traegt
   deshalb KEIN Leuchten: nur Bewegung.

   ⚠ NUR DIE BEWEGUNG, KEINE GROESSENAENDERUNG. Die Vorlage hat im selben
   Keyframe noch `scale(1.008)` und einen Schein; beides ist hier bewusst
   weggelassen. Ein wachsender Kasten schiebt seine Nachbarn und stoert beim
   Lesen, und der Schein waere das zweite Pulsieren.

   🚨 WARUM DIE `translate`-EIGENSCHAFT UND NICHT `transform`. `.menu-btn:active`
   setzt `transform: scale(0.98)` (game-v3.css). Eine laufende Animation auf
   `transform` haette diese Rueckmeldung beim Druecken ueberstimmt. `translate`
   ist eine eigene Eigenschaft und wird VOR `transform` angewandt — beide
   wirken nebeneinander, das Druecken bleibt sichtbar.

   🚨 WARUM DIE LISTE BEIDE ANIMATIONEN NENNT. `.menu-level.active .menu-btn`
   traegt bereits `animation: menu-fade-in 0.3s ease-out both` (game-v3.css) —
   den Auftritt beim Bildschirmwechsel. Eine Regel mit hoeherer Spezifitaet
   ERSETZT diese Liste, sie ergaenzt sie nicht; ohne die Nennung waere der
   Auftritt bei eingeschaltetem Schalter still verschwunden.
   Und `animation-delay` bleibt hier ABSICHTLICH ungesetzt: die Staffelung des
   Auftritts (`:nth-child(N)`, 0.1s .. 0.55s) gilt damit weiter. Ein einzelner
   Verzoegerungswert wiederholt sich ueber die ganze Liste — er trifft also
   beide Animationen, und beim Atmen ist er folgenlos, weil dessen PHASE in den
   Keyframes steckt und nicht in einer Verzoegerung.

   🚨 JEDER KASTEN MIT EIGENER PHASE UND EIGENEM TAKT. Vier Keyframe-Saetze,
   um je eine Vierteldrehung versetzt, dazu vier verschiedene Dauern — die
   Reihe ist damit zu KEINEM Zeitpunkt im Gleichschritt, auch nicht im
   Augenblick des Ladens. (Vier gleiche Keyframes mit nur verschiedener Dauer
   waeren beim Start alle bei 0 gewesen.) Dieselbe Asymmetrie wie bei den
   Leitbahnen in Abschnitt 4. */

@keyframes sqAtmenA {   /* Phase 0   */
    0%, 100% { translate: 0 0; }
    25%      { translate: 0 -0.75px; }
    50%      { translate: 0 -1.5px; }
    75%      { translate: 0 -0.75px; }
}
@keyframes sqAtmenB {   /* Phase 1/4 */
    0%, 100% { translate: 0 -0.75px; }
    25%      { translate: 0 -1.5px; }
    50%      { translate: 0 -0.75px; }
    75%      { translate: 0 0; }
}
@keyframes sqAtmenC {   /* Phase 2/4 */
    0%, 100% { translate: 0 -1.5px; }
    25%      { translate: 0 -0.75px; }
    50%      { translate: 0 0; }
    75%      { translate: 0 -0.75px; }
}
@keyframes sqAtmenD {   /* Phase 3/4 */
    0%, 100% { translate: 0 -0.75px; }
    25%      { translate: 0 0; }
    50%      { translate: 0 -0.75px; }
    75%      { translate: 0 -1.5px; }
}

body.sq-sprache #screen-lobby #menu-main .menu-btn:not(.back-btn):not(.menu-btn-quit) {
    animation-name: sqAtmenA, menu-fade-in;
    animation-duration: 5.2s, 0.3s;
    animation-timing-function: ease-in-out, ease-out;
    animation-iteration-count: infinite, 1;
    animation-fill-mode: none, both;
    will-change: translate;
}
/* Eigener Takt und eigene Phase je Kasten — die Dauern der Vorlage.
   `:nth-child` zaehlt hier genau die vier Menueknoepfe: der Sprachumschalter
   und der (im Browser verborgene) Beenden-Knopf stehen dahinter.

   🚨 DIE `:not()`-KETTE MUSS HIER WIEDERHOLT WERDEN. Ohne sie ist die
   allgemeine Regel darueber SPEZIFISCHER als diese vier: jedes `:not()` gibt
   seinem Argument den vollen Klassenpunkt weiter, die Grundregel kommt damit
   auf (2,4,1) und ein blosses `:nth-child(N)` nur auf (2,3,1). Gemessen beim
   ersten Lauf (scripts/im1-nachweis.js, Fall 6): alle vier Knoepfe liefen auf
   `sqAtmenA` mit 5.2s — und die Probe war trotzdem GRUEN, weil die vier
   Auftritts-Verzoegerungen aus game-v3.css (0.1s .. 0.55s) vier knapp
   verschiedene Werte erzeugten. Vier verschiedene Zahlen sind eben noch kein
   Beleg fuer vier Phasen; 0.45s Spreizung auf 5.2s Takt sind 9 Prozent und
   damit praktisch Gleichschritt. */
body.sq-sprache #screen-lobby #menu-main
    .menu-btn:not(.back-btn):not(.menu-btn-quit):nth-child(1) {
    animation-name: sqAtmenA, menu-fade-in; animation-duration: 5.0s, 0.3s;
}
body.sq-sprache #screen-lobby #menu-main
    .menu-btn:not(.back-btn):not(.menu-btn-quit):nth-child(2) {
    animation-name: sqAtmenB, menu-fade-in; animation-duration: 6.1s, 0.3s;
}
body.sq-sprache #screen-lobby #menu-main
    .menu-btn:not(.back-btn):not(.menu-btn-quit):nth-child(3) {
    animation-name: sqAtmenC, menu-fade-in; animation-duration: 5.6s, 0.3s;
}
body.sq-sprache #screen-lobby #menu-main
    .menu-btn:not(.back-btn):not(.menu-btn-quit):nth-child(4) {
    animation-name: sqAtmenD, menu-fade-in; animation-duration: 6.6s, 0.3s;
}

/* ⚠ Sie hoert auf, wenn der Zeiger darueber steht — sonst wackelt genau das,
   was man gerade anfassen will. `paused` haelt den Kasten dort an, wo er
   steht; es springt nichts. */
body.sq-sprache #screen-lobby #menu-main .menu-btn:hover {
    animation-play-state: paused;
}

/* Wer Bewegung abbestellt hat, bekommt keine. Dieselbe Entscheidung, die
   game-v3.css fuer das Bot-Angebot trifft (`prefers-reduced-motion: reduce`).

   🚨 UND DAS IST ZUGLEICH DER WEG FUER BROWSERPROBEN. Playwright haelt ein
   dauernd bewegtes Element fuer „not stable" und bricht `locator.hover()` /
   `.click()` nach 30 s ab — gemessen, nicht vermutet (erster Lauf von
   scripts/im1-nachweis.js, Fall 10). Den BEDIENER trifft das nicht (Fall 8:
   56 Treffer, 0 Fehlgriffe an der Ruhelage), eine kuenftige Probe schon.
   Wer hier klicken will, nimmt entweder `page.mouse.move()`/`{force:true}`
   oder schaltet die Bewegung ab:
       browser.newContext({ reducedMotion: 'reduce' })
   ⛔ BERICHTIGT in JI1 (2026-09-18): der Satz „verify-ui ist heute nicht
   betroffen — es faehrt mit ausgeschaltetem Schalter" gilt NICHT MEHR. Die
   Formsprache ist seit JI1 die VORGABE; jeder Browserlauf trifft diese
   Animation jetzt, sofern er nicht ausdruecklich `?sprache=0` setzt.
   `verify-ui` ist weiterhin heil, aber aus einem anderen Grund: es startet
   seit IN1 mit `reducedMotion: 'reduce'`. **Jedes NEUE Messskript muss das
   ebenfalls tun** — sonst laeuft sein erster Klick in den Deckel. */
@media (prefers-reduced-motion: reduce) {
    body.sq-sprache #screen-lobby #menu-main .menu-btn:not(.back-btn):not(.menu-btn-quit) {
        animation-name: menu-fade-in;
        animation-duration: 0.3s;
        animation-timing-function: ease-out;
        animation-iteration-count: 1;
        animation-fill-mode: both;
        translate: none;
    }
}


/* ── 10. Freies Spiel (#menu-play) ─────────────────────────────────────────
   IN1 (2026-09-16). Der erste Bildschirm der Formsprache, der nicht nur aus
   Knoepfen besteht: ein Namensfeld, eine Fraktionsreihe mit Bildern, ein
   `<select>`, eine Anwesenheitszeile.

   🚨 NICHTS WIRD GELOESCHT, NICHTS NEU GEBAUT, UND KEIN KNOTEN WANDERT.
   Dieser ganze Abschnitt ist reines CSS — die Anordnung entsteht ueber `order`
   in der Flex-Spalte, die `.menu-level` ohnehin ist (game-v3.css: `display:none;
   flex-direction:column`). Damit sind es nach dem Umschalten nicht nur
   „dieselben Knoten" — es hat sich am Baum ueberhaupt nichts geruehrt, und
   `#guestName`, `#botDifficulty`, `#sq-set-row` und die Wappen koennen gar
   nicht verlorengehen.

   ⚠ WARUM NICHT DIE ZWEISPALTIGE ANORDNUNG DER VORLAGE: `#lobby-main` ist per
   layout-config.js auf 400 Buehnen-px festgenagelt und schneidet waagerecht ab
   (`overflow-x:hidden`). Weg A verbietet, daran zu ruehren. Die beiden Kaesten
   der Vorlage stehen deshalb in den 400 px nebeneinander — was `.play-actions-
   grid` mit `1fr 1fr` ohnehin schon tut (gemessen 196 + 196 Buehnen-px). Sie
   werden hoeher statt breiter, die Komposition bleibt.

   ⚠ UND DESHALB STEHT DIE ANWESENHEITSZEILE UEBER DEN KAESTEN, NICHT DARIN.
   Die Vorlage zeigt „Suchen gerade 3 …" im Suchkasten; das waere ein
   Verschachteln, also ein Knotenumzug. Ueber beiden Kaesten gelesen ist die
   Zeile ausserdem nicht falsch: sie nennt online, Suchende UND die Fassung, und
   die Fassung gilt fuer beide Kaesten. (Ihr Text kommt unveraendert aus
   sqPresenceText(), FF1 — kein neues Feld, keine zweite Wahrheit.)

   🚨 DIE FASSUNGSWAHL WIRD NICHT ANGEFASST — UND ZWAR AUS EINEM GEMESSENEN
   GRUND: `#sq-set-row` steht gar nicht auf diesem Bildschirm, sondern eine
   Ebene davor in `#menu-play-choice` (views/play-v3.ejs:514). Genau dort klickt
   `verify-ui.js` `[data-testid="fassung-<id>"]` (Zeile 910). Sie „optisch in
   den Suchkasten zu holen" hiesse, den Knoten zu verschieben — und damit die
   Pruefung blind zu machen, die diese Woche jeden Tag getragen hat. Die Wahl
   bleibt, wo sie ist; ihr ERGEBNIS steht ohnehin in der Anwesenheitszeile.  */

/* Anordnung. Alles Negative steht vor dem ZURUECK-Knopf (Vorgabe `order:0`). */
body.sq-sprache #screen-lobby #menu-play > #guestBox,
body.sq-sprache #screen-lobby #menu-play > #userDisplay { order: -9; }
/* 🚨 IQ1 (17.09.2026): die Fraktionsreihe steht jetzt DIREKT UNTER DEM NAMENSFELD
   (Marcel: „Waehle deine Fraktion muss nach oben, unter die Namens-Eingabe"). Das
   ist eine reine UMNUMMERIERUNG dieser Leiter — dieselbe Bauform wie IN1, es
   bewegt sich weiterhin kein einziger Knoten. `> label.menu-label` trifft genau
   die Ueberschrift der Reihe; die Beschriftung des Namensfeldes liegt eine Ebene
   tiefer in #guestBox und bleibt unberuehrt. */
body.sq-sprache #screen-lobby #menu-play > label.menu-label,
body.sq-sprache #screen-lobby #menu-play > .faction-row { order: -8; }
body.sq-sprache #screen-lobby #menu-play > .play-actions-grid { order: -7; }
body.sq-sprache #screen-lobby #menu-play > #warte-bot-btn { order: -6; }
body.sq-sprache #screen-lobby #menu-play > .menu-btn:not(.back-btn) { order: -5; }
/* Der Inhaltskasten des privaten Raums (IQ1) steht im Baum unmittelbar hinter
   seiner Kopfzeile und traegt denselben `order`-Wert — gleiche Werte behalten
   die Baumreihenfolge, also bleibt er an ihr kleben. */
body.sq-sprache #screen-lobby #menu-play > #sq-raum { order: -5; }
body.sq-sprache #screen-lobby #menu-play > #queueStatus,
body.sq-sprache #screen-lobby #menu-play > #privateRoomInfo { order: -4; }

/* ── Die beiden Kaesten ──────────────────────────────────────────────────
   Aus zwei getoenten Knoepfen werden zwei Rahmen der Vorlage: goldener Balken
   links, Gefahrenstreifen und Indexnummer in der Kopfzeile. Die Kopfzeile ist
   KEIN neuer Knoten — es ist `.play-action-sub`, die Unterzeile, die heute
   schon „ONLINE" bzw. „BOT" traegt. Sie wandert nur nach oben und bekommt eine
   Trennlinie. Damit kommt kein einziges neues Wort in den Bildschirm
   (Zusicherung 13 ist hier strukturell erfuellt, nicht bloss geprueft). */
body.sq-sprache #screen-lobby #menu-play .play-actions-grid { gap: 10px; }

body.sq-sprache #screen-lobby #menu-play .play-action-btn {
    position: relative;
    box-sizing: border-box;
    padding: 0 0 11px;
    gap: 0;
    justify-content: flex-start;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-goldRGB), 0.34);
    color: var(--sq-gold);
    clip-path: polygon(0 10px, 10px 0, calc(100% - 20px) 0, 100% 20px,
                       100% 100%, 20px 100%, 0 calc(100% - 20px));
    overflow: hidden;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease;
}
/* Der goldene Balken links — dasselbe Zeichen wie an den Kaesten der rechten
   Spalte (Abschnitt 5/6). */
body.sq-sprache #screen-lobby #menu-play .play-action-btn::before {
    content: ''; position: absolute; left: -1px; top: 12px;
    width: 3px; height: 26px; background: var(--sq-gold);
}
/* Der Gefahrenstreifen oben rechts. */
body.sq-sprache #screen-lobby #menu-play .play-action-btn::after {
    content: ''; position: absolute; right: 6px; top: -1px;
    width: 36px; height: 8px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
}

/* Die Kopfzeile: die vorhandene Unterzeile, nach oben gezogen. */
body.sq-sprache #screen-lobby #menu-play .play-action-btn .play-action-sub {
    align-self: stretch;
    padding: 7px 46px 6px 12px;     /* rechts Platz fuer Streifen und Nummer */
    margin-bottom: 10px;
    text-align: left;
    opacity: 1;
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--sq-cyanHell);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.24);
}

/* Die Indexnummern der Vorlage. Ziffern, kein Text — hier ist nichts zu
   uebersetzen. Sie sitzen an einem eigenen Knoten (der Kopfzeile), weil
   ::before und ::after des Kastens schon Balken und Streifen tragen. */
body.sq-sprache #screen-lobby #menu-play .play-action-sub::after {
    position: absolute;
    right: 46px;
    top: 7px;
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-cyanRGB), 0.62);
}
body.sq-sprache #screen-lobby #menu-play .play-action-primary   .play-action-sub::after { content: '001'; }
body.sq-sprache #screen-lobby #menu-play .play-action-secondary .play-action-sub::after { content: '002'; }

/* Der Rumpf beider Kaesten. Der Rumpf sitzt in der Mitte der Restflaeche:
   das Gitter zieht beide Zellen auf gleiche Hoehe, und der hoehere Kasten (der
   mit dem `<select>`) bestimmt sie. Ohne `margin:auto 0` haengt der Inhalt des
   anderen oben und darunter steht eine tote Flaeche. */
body.sq-sprache #screen-lobby #menu-play .play-action-primary {
    font-size: 12px;
    letter-spacing: 0.1em;
    padding-bottom: 14px;
}
body.sq-sprache #screen-lobby #menu-play .play-action-primary > *:not(.play-action-sub),
body.sq-sprache #screen-lobby #menu-play .play-action-secondary > .play-action-row {
    margin-top: auto;
    margin-bottom: auto;
}
body.sq-sprache #screen-lobby #menu-play .play-action-secondary { color: var(--sq-gold); }
body.sq-sprache #screen-lobby #menu-play .play-action-row {
    padding: 0 10px;
    gap: 8px;
    flex-direction: column;
    align-items: center;
}
/* „GEGEN BOT" ist ein Knopf und sah wie eine Beschriftung aus — der Kasten
   darum ist ein `div` und kann die Klickbarkeit nicht anzeigen. Er bekommt
   deshalb die Knopfform der Vorlage. Der Knoten bleibt derselbe; er wird
   angezogen, nicht ersetzt. */
body.sq-sprache #screen-lobby #menu-play .play-action-row > button {
    color: var(--sq-gold);
    border: 1px solid rgba(var(--sq-goldRGB), 0.45) !important;
    background: rgba(var(--sq-goldRGB), 0.06) !important;
    padding: 6px 12px !important;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.14em;
    clip-path: polygon(0 6px, 6px 0, calc(100% - 8px) 0, 100% 8px,
                       100% 100%, 8px 100%, 0 calc(100% - 6px));
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

/* GOLD ruht, CYAN antwortet — dieselbe Regel wie am Menueknopf (Abschnitt 2).
   Der Suchkasten IST ein Knopf; der Botkasten ist ein `div`, dort antwortet
   sein Knopf. */
body.sq-sprache #screen-lobby #menu-play .play-action-primary:hover,
body.sq-sprache #screen-lobby #menu-play .play-action-primary:focus-visible {
    border-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
    box-shadow: 0 0 18px -4px rgba(var(--sq-cyanRGB), 0.55);
}
body.sq-sprache #screen-lobby #menu-play .play-action-row > button:hover {
    color: var(--sq-cyanHell);
    border-color: var(--sq-cyan) !important;
    background: rgba(var(--sq-cyanRGB), 0.12) !important;
    text-shadow: 0 0 10px rgba(var(--sq-cyanRGB), 0.35);
}

/* ── Der Schwierigkeitsgrad ──────────────────────────────────────────────
   🚨 DAS `<select>` BLEIBT — GEMESSEN, NICHT GEWAEHLT. Die Vorlage zeigt drei
   Knoepfe; drei Knoepfe daneben zu stellen und den `<select>` zu verbergen ist
   der Weg, den der Prompt als zweite Moeglichkeit nennt. Er traegt nicht:
   `verify-ui.js:953` ruft `page.selectOption('#botDifficulty', …)`, und
   Playwrights Actionability verlangt ein SICHTBARES Element. Gemessen
   (scripts/in1-selectprobe.js):

       sichtbar, nur umgekleidet   -> geht durch, Wert "hard"
       display:none                -> BRICHT AB nach 6 s
       visibility:hidden           -> BRICHT AB nach 6 s
       opacity:0 (Kasten bleibt)   -> geht durch  ← technisch, aber eine Falle:
                                      ein unsichtbares, anklickbares Bedienteil
                                      ueber den Knoepfen

   Also wird es UMGEKLEIDET, nicht ausgetauscht. `appearance:none` nimmt ihm den
   Systemanstrich, alles Uebrige ist Farbe und Form. Jeder Leser
   (`joinBotGame()`, verify-ui, der Botlauf selbst) sieht denselben Knoten mit
   denselben Werten. */
body.sq-sprache #screen-lobby #menu-play #botDifficulty.play-select {
    appearance: none;
    -webkit-appearance: none;
    background: rgba(2, 6, 14, 0.92) !important;   /* !important nur, weil die
        Bestandsregel .play-select selbst mit !important schreibt — hier wird
        eine vorhandene Farbregel ueberstimmt, KEIN Aussenmass (Weg A gilt) */
    border: 1px solid rgba(var(--sq-goldRGB), 0.45) !important;
    border-radius: 0 !important;
    color: var(--sq-gold) !important;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px !important;
    letter-spacing: 0.1em;
    padding: 5px 9px !important;
    min-width: 84px !important;
    clip-path: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px),
                       calc(100% - 6px) 100%, 0 100%);
    transition: border-color 0.15s ease, color 0.15s ease;
}
body.sq-sprache #screen-lobby #menu-play #botDifficulty.play-select:hover,
body.sq-sprache #screen-lobby #menu-play #botDifficulty.play-select:focus {
    border-color: var(--sq-cyan) !important;
    color: var(--sq-cyanHell) !important;
}
body.sq-sprache #screen-lobby #menu-play #botDifficulty.play-select option {
    background: #040a14 !important;
    color: var(--sq-gold) !important;
    font-size: 11px !important;
}

/* ── Kasten 003: der private Raum ────────────────────────────────────────
   Er ist ein `.menu-btn` und traegt darum seit IM1 schon Balken, Streifen und
   eine Indexnummer — nur zaehlt der CSS-Zaehler je Menue-Ebene, und auf dieser
   Ebene ist er der erste, bekommt also „001". In der Vorlage ist er der dritte.
   Die Nummer wird hier gesetzt, nicht gezaehlt. */
body.sq-sprache #screen-lobby #menu-play .menu-btn:not(.back-btn)::before {
    content: '003';
}

/* ── Das Namensfeld ──────────────────────────────────────────────────────
   Es steht UEBER den beiden Kaesten, nicht in „Gegner suchen": der Name gilt
   fuer beide Wege — auch das Botspiel traegt ihn — und in einem der Kaesten
   stuende er wie eine Bedingung nur dieses Kastens.
   Das Feld selbst wird nur angezogen; es bleibt `#guestName`, nimmt Eingaben
   an wie heute, und `page.fill('#guestName', …)` (verify-ui:945) findet es. */
body.sq-sprache #screen-lobby #menu-play .menu-input {
    background: rgba(2, 6, 14, 0.92);
    border: 1px solid rgba(var(--sq-goldRGB), 0.34);
    border-radius: 0;
    color: #e8eaf0;
    clip-path: polygon(0 8px, 8px 0, 100% 0, 100% calc(100% - 8px),
                       calc(100% - 8px) 100%, 0 100%);
}

/* ── Die Fraktionsreihe ──────────────────────────────────────────────────
   🚨 NUR RAHMEN UND SCHRIFT. Die Wappen sind echte Bilder
   (/images/faction-logo-vs.webp, -ued.webp, dazu der gezeichnete Wuerfel fuer
   „Zufall") — Marcel: „die richtigen Symbole usw. muessen genutzt werden."
   Die Vorlage zeigt an dieser Stelle blossen Text; das Bild ist die Vorlage,
   nicht die Wahrheit. Hier steht deshalb KEINE Regel, die `.faction-emblem`
   verbirgt, verkleinert oder ersetzt. */
body.sq-sprache #screen-lobby #menu-play .faction-btn {
    border-radius: 0;
    clip-path: polygon(0 10px, 10px 0, calc(100% - 14px) 0, 100% 14px,
                       100% 100%, 14px 100%, 0 calc(100% - 14px));
}

/* ── Such- und Raumstand ─────────────────────────────────────────────────
   Erscheinen erst waehrend der Suche bzw. im Raum; sie bekommen denselben
   Rahmen, damit der Bildschirm nicht auf halbem Weg die Sprache wechselt. */
body.sq-sprache #screen-lobby #menu-play #queueStatus,
body.sq-sprache #screen-lobby #menu-play #privateRoomInfo {
    box-sizing: border-box;
    padding: 10px 12px;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-cyanRGB), 0.34);
    clip-path: polygon(0 10px, 10px 0, calc(100% - 18px) 0, 100% 18px,
                       100% 100%, 18px 100%, 0 calc(100% - 18px));
}
body.sq-sprache #screen-lobby #menu-play .room-code { color: var(--sq-gold); }

/* Die Anwesenheitszeile als Kopfzeile ueber den Kaesten. */
body.sq-sprache #screen-lobby #menu-play #sq-presence-lobby {
    font-family: 'Share Tech Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    color: #8b93a8;
}

/* ── 11. Freies Spiel bekommt Breite ───────────────────────────────────────
   IO1 (2026-09-16). IN1 hat gebaut, was in 400 Buehnen-px moeglich war —
   Rahmen, Kopfzeilen, Indexnummern. Das RASTER der Vorlage
   (mockups/bildschirme-neue-sprache.html, „Freies Spiel": zwei Kaesten
   nebeneinander, darunter einer ueber die ganze Breite) braucht mehr.

   🚨 DIE GESCHAERFTE WEG-A-REGEL (CLAUDE.md, Berichtigung zu IG1):
   Die Formsprache DARF ein gefuehrtes Mass aendern — aber nur ueber
   Eigenschaften, die `applyToElement()` LEERT (`min-width`, `min-height`),
   niemals ueber `!important`, und niemals in `layout-config.js`. Der Grund,
   aus dem Weg A ueberhaupt existiert, ist der SCHALTER: eine Regel hinter
   `body.sq-sprache` greift nur im Ein-Zustand, „aus = heute" bleibt
   unberuehrt, und die Engine wird nicht angefasst.
   Gemessen (scripts/io1-messung.js, vier Fenster):
       400 -> 840 (default) · 360 -> 840 (narrow) · Ruecknahme -> wieder 400/360
       Hauptmenue 400/400 · Schalter aus 400/400 · Hochformat 1280 unberuehrt

   🚨 WARUM DIE REGEL AUF `:has(#menu-play.active)` BESCHRAENKT IST — und das
   ist der Preis aus Abschnitt 2 des Prompts, gerechnet aus gemessenen Kanten:
   im HAUPTMENUE stehen rechts fuenf Elemente (`#sq-preenlist`, `#sq-status`
   und die drei Geschwister `#lobby-promo-banner`/`#lobby-discord-btn`/
   `#lobby-steam-btn` darin). Die Fuge zwischen Menuespalte und Kaesten ist
   32 px: mit unbeschraenkter Regel wuerden sie ab einer Spaltenbreite von
   **432** Buehnen-px ueberlappt (narrow: ab 452). Es ist also nicht so, dass
   die Beschraenkung sauberer waere — sie ist der einzige Weg, der ueberhaupt
   geht.
   Auf der Ebene „Freies Spiel" sind alle fuenf `display:none`
   (game-v3.css `:has(#menu-main.active)`, Abschnitt 5/6 hier) — gemessen
   **0 von 5 gerendert**, in allen vier Fenstern. Dort ist nichts, was
   ueberlappt werden koennte.
   ⚠ „display !== none" ist dafuer der falsche Blick: die drei Geschwister
   haengen im Ein-Zustand IN `#sq-preenlist`, und an ihnen selbst steht
   weiter `display:flex`. Gemessen wird `getClientRects().length` — der erste
   Lauf der Probe zaehlte sie als sichtbar, bei einer Huellbox von 0x0.

   🚨 DIE AUSGLEICHSZAHL IST GERECHNET, NICHT GESCHOBEN. Die Engine setzt
   `left = W/2 - 200` (Anker center, Pivot center, 400 breit) und leert
   `right`. Waechst nur die Breite, waechst der Kasten nach RECHTS und die
   Mitte wandert um 220 px. Mittig waere `left = (W - X)/2`, also
       margin-left = 200 - X/2 = -220     (default, Spalte 400)
       margin-left = 180 - X/2 = -240     (narrow,  Spalte 360)
   — beides von der Buehnenbreite W unabhaengig, weil sich W herauskuerzt.
   Gemessen steht die Spalte danach bei 220 .. 1060, Rand links 220, Rand
   rechts 220, Differenz 0 px (1280, 1920 und narrow gleich).
   ⚠ Der IM1-Versatz `calc(104px - 25%)` haengt an `:has(#menu-main.active)`
   und gilt hier gar nicht — die beiden Regeln koennen sich nicht treffen.

   ⚠ Hochformat bekommt KEINE Regel: dort fuehrt `lobby.portrait` nur
   `lobby-main` mit `stretch-both` (CX1), die Spalte ist ohnehin so breit wie
   die Buehne (gemessen 1280), und beide Kaesten sind ausgeblendet. */

@media (min-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-play.active) #lobby-main {
        min-width: 840px;
        margin-left: -220px;
    }
}
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-play.active) #lobby-main {
        min-width: 840px;
        margin-left: -240px;
    }
}
/* Der Uebergang gleitet wie in Abschnitt 7 — der Wechsel auf „Freies Spiel"
   ist eine Bewegung, kein Sprung. */
body.sq-sprache #screen-lobby:has(#menu-play.active) #lobby-main {
    transition: margin-left 0.22s ease, min-width 0.22s ease;
}

/* ── Die zwei Kappen, die den Raum sonst wieder wegnehmen ─────────────────
   Gemessene Bestandswerte, KEINE gefuehrten Masse (weder `.menu-container`
   noch `.menu-btn` stehen in layout-config.js — die Engine kennt sie nicht):
       .menu-container  width:100%; max-width:420px   (game-v3.css:3069)
       .menu-btn        width:100%; max-width:360px   (game-v3.css, Fix I1)
   Ohne diese beiden Zeilen waere die Spalte 840 breit und der Inhalt stuende
   weiter in 420 px. Beide gelten nur, solange „Freies Spiel" die aktive
   Ebene ist. */
body.sq-sprache #screen-lobby:has(#menu-play.active) .menu-container {
    max-width: 100%;
}
body.sq-sprache #screen-lobby #menu-play { width: 100%; }

/* FIX OD1 (2026-10-03): der private Raum hat eine eigene Ebene (#menu-privat-raum) mit
   demselben Rahmen wie das Freie Spiel — er bekommt dieselbe Breite, dieselbe Mitte und
   denselben weichenden Titelblock. Woertlich die Regeln von oben, nur fuer die zweite
   Ebene; die Rechnung (840, -220/-240) gilt unveraendert. */
@media (min-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-privat-raum.active) #lobby-main { min-width: 840px; margin-left: -220px; }
}
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby:has(#menu-privat-raum.active) #lobby-main { min-width: 840px; margin-left: -240px; }
}
body.sq-sprache #screen-lobby:has(#menu-privat-raum.active) #lobby-main { transition: margin-left 0.22s ease, min-width 0.22s ease; }
body.sq-sprache #screen-lobby:has(#menu-privat-raum.active) .menu-container { max-width: 100%; }
body.sq-sprache #screen-lobby:has(#menu-privat-raum.active) .lobby-header { display: none; }

/* 🚨 UND DER TITELBLOCK WEICHT — GEMESSEN, NICHT AUS GESCHMACK. Mit ihm endete
   der ZURUECK-Knopf bei **860** von 720 Buehnen-px (scripts/io1-blick.js, erster
   Lauf): das Raster baut hoeher als eine Knopfliste, und `#lobby-main` hat
   `overflow-y:auto` — der Knopf waere nicht weg, aber unter der Kante, und
   niemand scrollt in einem Menue.
   Die Vorlage zeigt auf diesem Bildschirm ohnehin KEIN Logo, sondern nur das
   Schild „Freies Spiel" (mockups/bildschirme-neue-sprache.html, `#s-frei`) —
   das Schild UEBERNIMMT hier die Aufgabe des Titelblocks.
   ⚠ Nur der Titelblock, NICHT der Sprachumschalter: `.lang-switch-wrap` ist ein
   eigenes Element neben `.lobby-header` (IM1) und bleibt bedienbar. Und nur auf
   dieser Ebene und nur im Ein-Zustand — im Hauptmenue steht der Titel wie heute. */
body.sq-sprache #screen-lobby:has(#menu-play.active) .lobby-header {
    display: none;
}

/* ── Das Raster ──────────────────────────────────────────────────────────
   Weiterhin ueber `order` in der Flex-Spalte, die `.menu-level` ohnehin ist
   (IN1) — kein Knoten wird geloescht, ersetzt oder verschoben. Neu sind
   VIER Knoten, und sie werden erzeugt, nicht umgehaengt: das Schild und die
   drei Erklaersaetze (sq-sprache.js, `spielBauen()`), jeder mit
   `data-i18n` und leer im Code.

       [ FREIES SPIEL ]                         order -12   (Schild)
       SPIELERNAME [ … ]                        order -10
       2 online · niemand sucht                 order  -9
       ┌ 001 ┐ ┌ 002 ┐                          order  -8
       ┌ 003 privater Raum ┐                    order  -5
       Such-/Raumstand                          order  -4
       ‹ WAEHLE DEINE FRAKTION › [VS][?][UED]   order  -3
       ┌ ZURUECK ┐                              order   0  (Vorgabe) */

body.sq-sprache #screen-lobby #menu-play > #sq-fs-titel { order: -12; }

/* Das Schild der Vorlage (mockups, `.schild`): angeschnittene Ecken, Gold,
   weit gesperrt. Ein ELEMENT mit i18n-Schluessel, kein `content:` — ein Wort
   im Stylesheet waere hartkodiertes Deutsch (IN1 hat es darum gelassen; der
   Schluessel `FREIES SPIEL` ist in beiden Woerterbuechern vorhanden). */
body.sq-sprache #screen-lobby #menu-play #sq-fs-titel {
    align-self: center;
    margin: 0 0 16px;
    padding: 9px 32px;
    background: rgba(2, 4, 10, 0.94);
    border: 1px solid rgba(var(--sq-goldRGB), 0.5);
    clip-path: polygon(14px 0, 100% 0, calc(100% - 14px) 100%, 0 100%);
    font-family: 'Orbitron', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--sq-gold);
}

/* Das Namensfeld: eine ZEILE ueber dem Raster, Beschriftung links, Feld
   daneben. `.menu-field` ist im Bestand 270 px breit und eine Spalte
   (game-v3.css) — in 840 px stuende die Beschriftung sonst als
   Einzelzeile ueber einem schmalen Kasten mitten im Nichts.
   🚨 WARUM HIER UND NICHT IN EINEM KASTEN: der Name gilt fuer BEIDE Wege —
   auch das Botspiel traegt ihn — und in Kasten 001 stuende er wie eine
   Bedingung nur dieses Kastens. Ueber dem Raster gilt er sichtbar fuer
   alles, was darunter steht. (Dieselbe Begruendung wie IN1, dieselbe
   Stelle; die Vorlage hat das Feld vergessen.) */
body.sq-sprache #screen-lobby #menu-play > #guestBox,
body.sq-sprache #screen-lobby #menu-play > #userDisplay {
    order: -10;
    width: 100%;
    max-width: 470px;
    flex-direction: row;
    align-items: center;
    gap: 14px;
}
body.sq-sprache #screen-lobby #menu-play > #guestBox > .menu-input { flex: 1 1 auto; }
body.sq-sprache #screen-lobby #menu-play > #guestBox > .menu-label { flex: 0 0 auto; }

body.sq-sprache #screen-lobby #menu-play > .play-actions-grid {
    order: -8;
    gap: 18px;
    margin-bottom: 16px;
}
/* Gemessen standen die beiden Kaesten 2 Buehnen-px versetzt (001 bei 172, 002
   bei 174 — scripts/io1-blick.js). In einem Gitter ist das kein Geschmack,
   sondern ein Rest: beide Zellen werden ausdruecklich gestreckt und bekommen
   keinen eigenen Rand. */
body.sq-sprache #screen-lobby #menu-play > .play-actions-grid > .play-action-btn {
    align-self: stretch;
    margin: 0;
}

/* 003 und ZURUECK ueber die ganze Breite — wie in der Vorlage. */
body.sq-sprache #screen-lobby #menu-play > .menu-btn { max-width: none; }

/* Die Fraktionsreihe und die Standkaesten bleiben schmal: drei Wappen ueber
   840 px auseinanderzuziehen macht sie nicht lesbarer, nur weiter weg. */
body.sq-sprache #screen-lobby #menu-play > label.menu-label,
body.sq-sprache #screen-lobby #menu-play > .faction-row {
    width: 100%;
    max-width: 520px;
}
/* Die Ueberschrift der Reihe steht ueber ihrer Mitte, nicht an ihrem linken
   Rand — die Vorlage setzt sie mittig („‹ Waehle deine Fraktion ›"). */
body.sq-sprache #screen-lobby #menu-play > label.menu-label { text-align: center; }
body.sq-sprache #screen-lobby #menu-play > #queueStatus,
body.sq-sprache #screen-lobby #menu-play > #privateRoomInfo {
    width: 100%;
    max-width: 560px;
}

/* ── Was in den Kaesten steht ────────────────────────────────────────────
   Jetzt ist Platz fuer den Erklaersatz der Vorlage. Die Kopfzeile bleibt
   `.play-action-sub` (IN1), die Indexnummern bleiben, wo sie sind. */
body.sq-sprache #screen-lobby #menu-play .play-action-btn {
    min-height: 186px;
    padding: 0 0 14px;
}
body.sq-sprache #screen-lobby #menu-play .play-action-btn .play-action-sub {
    order: -2;
    padding: 8px 52px 7px 14px;
}

/* Der Erklaersatz. 🚨 Er muss aus der Knopfschrift AUSSTEIGEN: der Kasten ist
   ein `<button>` in Orbitron mit 1 px Sperrung und Grossbuchstaben — ein Satz
   darin waere unlesbar. Werte aus der Vorlage (12,5 px, Zeilenhoehe 1,7,
   #aab4c2). */
body.sq-sprache #screen-lobby #menu-play .sq-fs-erk {
    display: block;
    font-family: 'Rajdhani', sans-serif;
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.7;
    letter-spacing: 0.01em;
    text-transform: none;
    text-align: left;
    color: #aab4c2;
}
body.sq-sprache #screen-lobby #menu-play .play-action-btn > .sq-fs-erk {
    order: -1;
    align-self: stretch;
    margin: 0 14px 12px;
}

/* Kasten 001: der ganze Kasten IST der Knopf (`joinQueue()`), die
   Beschriftung wird zur Leiste am Fuss — die Vorlage zeigt dort
   „SCHNELLSUCHE ▸" ueber die ganze Kastenbreite. */
body.sq-sprache #screen-lobby #menu-play .play-action-primary > span:not(.play-action-sub):not(.sq-fs-erk) {
    align-self: stretch;
    margin: auto 14px 0;
    padding: 10px 0;
    border: 1px solid rgba(var(--sq-goldRGB), 0.45);
    background: rgba(var(--sq-goldRGB), 0.07);
    clip-path: polygon(0 8px, 8px 0, calc(100% - 10px) 0, 100% 10px,
                       100% 100%, 10px 100%, 0 calc(100% - 8px));
    font-size: 11px;
    letter-spacing: 0.16em;
    transition: border-color 0.15s ease, background 0.15s ease;
}
body.sq-sprache #screen-lobby #menu-play .play-action-primary:hover > span:not(.play-action-sub):not(.sq-fs-erk) {
    border-color: var(--sq-cyan);
    background: rgba(var(--sq-cyanRGB), 0.12);
}

/* Kasten 002: Schwierigkeit oben, Startknopf unten — die Reihenfolge der
   Vorlage. 🚨 Der Knoten `#botDifficulty` BLEIBT und bleibt sichtbar; in IN1
   gemessen bricht `selectOption()` bei `display:none` und `visibility:hidden`
   ab (je 6 s), und drei Knoepfe NEBEN dem `<select>` waeren zwei Bedienteile
   fuer denselben Wert. Er wird also nur breiter umgekleidet — die Kachelreihe
   der Vorlage als eine Kachel, die wirklich schaltet. */
body.sq-sprache #screen-lobby #menu-play .play-action-secondary > .play-action-row {
    align-self: stretch;
    margin: auto 14px 0;
    padding: 0;
    gap: 10px;
    flex-direction: column;
}
body.sq-sprache #screen-lobby #menu-play .play-action-row > button {
    order: 2;
    align-self: stretch;
    padding: 10px 0 !important;
    font-size: 11px;
    letter-spacing: 0.16em;
}
body.sq-sprache #screen-lobby #menu-play #botDifficulty.play-select {
    order: 1;
    align-self: stretch;
    width: 100%;
    min-width: 0 !important;
    padding: 9px 26px !important;
    font-size: 11px !important;
    text-align: center;
    text-align-last: center;
    /* ⚠ `appearance:none` (IN1) nimmt dem Feld auch den Systempfeil. In der
       schmalen Spalte war es klein und stand neben dem Knopf; ueber die ganze
       Kastenbreite sieht es aus wie ein zweiter Knopf. Der Winkel sagt, dass
       man darin WAEHLT — als Bild, nicht als Text: ein `content:` mit einem
       Wort waere hartkodierte Sprache, und an einem `<select>` gibt es
       ohnehin kein Pseudo-Element. */
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23f0b429'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 10px center !important;
}

/* Kasten 003: der Erklaersatz sitzt als eigene Zeile im Knopf — `.menu-btn`
   ist eine umbrechende Flex-Zeile (Fix I1), `flex-basis:100%` macht daraus
   eine zweite Zeile, genau wie `.menu-btn-sub` im Hauptmenue. */
body.sq-sprache #screen-lobby #menu-play .menu-btn > .sq-fs-erk {
    flex: 0 0 100%;
    text-align: center;
    margin: 9px 0 0;
    padding: 0 24px;
    box-sizing: border-box;
}

/* 🚨 IQ1 (17.09.2026): die Anwesenheitszeile ist im EIN-Zustand ausgeblendet
   (Marcel, am Live-Stand 0.7.412: „Die Online-Anzeige hier kann raus").

   ⚠ NUR AUSGEBLENDET UND NUR HIER. Der Knoten bleibt im Baum und behaelt seinen
   Inhalt; `sqRenderPresence()` (FF1) schreibt weiter hinein. Ihn zu entfernen
   hiesse, den AUS-Zustand zu aendern — und `#sq-presence-queue`, dieselbe Zahl
   auf dem SUCHbildschirm, haengt am selben Renderer und am selben DB-Schalter
   (`presence_search_enabled`). Diese Regel trifft die Lobby-Zeile ueber ihre
   eigene Kennung, nicht ueber die gemeinsame Klasse `.sq-presence`. */
body.sq-sprache #screen-lobby #menu-play > #sq-presence-lobby {
    order: -9;
    display: none;
}


/* ══ 12. Der private Raum kommt in den Kasten ══════════════════════════════
   IQ1 (2026-09-17). Kasten 003 zeigt beide Wege nebeneinander, so wie die
   Vorlage sie zeigt — kein Modal, keine Reiter.

   🚨 ES SIND DIESELBEN KNOTEN. `sq-sprache.js` haengt sechs vorhandene
   Elemente aus `#private-room-modal` und `#menu-play` in einen neuen Rahmen
   und beim Ausschalten per `insertBefore(el, davor)` an die GENAUE alte
   Stelle zurueck — dieselbe Mechanik, die II1 fuer den Pre-Enlist-Kasten
   gebaut hat, jetzt fuer beide Kaesten aus EINER Implementierung. Kennungen,
   Handler und `data-testid` bleiben unveraendert; `joinPrivateRoom()` &
   Co. suchen ihre Knoten ohnehin bei jedem Aufruf per `getElementById`.

   🚨 WARUM EIN GESCHWISTER UND KEIN KIND. Kasten 003 IST ein `<button>`
   (`views/play-v3.ejs:600`). Ein `<input>` und zwei `<button>` DARIN waeren
   ungueltiges Markup und nicht bedienbar. Der Knopf bleibt deshalb die
   Kopfzeile, der Inhalt steht als Geschwister darunter — die beiden sehen
   zusammen wie ein Kasten aus, sind aber zwei Knoten.

   ⚠ UND DESHALB IST DER KNOPF IM EIN-ZUSTAND STUMMGESCHALTET (in der JS-Datei,
   ein Lauscher in der Einfangphase): sein `onclick` wuerde ein Modal oeffnen,
   dessen Bedienteile gerade im Kasten stehen — also einen leeren Rahmen. Der
   Lauscher wird beim Ausschalten wieder abgenommen, das Attribut bleibt
   unberuehrt, und die 29 Pruefskripte, die `button[onclick="openPrivate
   RoomModal()"]` klicken, laufen alle im AUS-Zustand.

   🚨 DIE REITER WERDEN UEBER IHREN KASTEN ADRESSIERT, NICHT UEBER DIE KLASSE.
   `.private-room-tabs` gibt es ZWEIMAL: hier und im Deckviewer
   (`play-v3.ejs:1132`, die VS/UED-Reiter). Eine Regel auf die nackte Klasse
   haette dem Deckviewer die Fraktionsreiter genommen. */

/* FIX OD1 (2026-10-03): nur solange es Kasten 003 gibt (#sq-raum, s. sq-sprache.js#raumBauen). Seit
   OD1 baut das Freie Spiel ihn nicht mehr (der Rahmen steht im Markup) — dann ist das Modal wieder
   der Weg, und ohne Reiter liesse es nur Beitreten zu (gemessen: #tab-create 0x0, nicht klickbar). */
body.sq-sprache:has(#sq-raum) #private-room-modal .private-room-tabs { display: none; }

/* Der Erklaersatz aus IO1 entfaellt hier: seine beiden Haelften stehen jetzt
   als Spaltenueberschriften im Kasten. Er bleibt im Baum (IO1s Nachfuehrung
   haengt an ihm) und kommt im Aus-Zustand unveraendert wieder. */
body.sq-sprache #screen-lobby #menu-play .menu-btn > #sq-fs-erk-raum { display: none; }

/* Die Kopfzeile schliesst nach unten nicht ab — darunter kommt der Rumpf. */
body.sq-sprache #screen-lobby #menu-play > .menu-btn:not(.back-btn):has(+ #sq-raum) {
    border-bottom-color: transparent;
    margin-bottom: 0;
}

body.sq-sprache #screen-lobby #menu-play > #sq-raum {
    display: flex;
    flex-wrap: wrap;
    gap: 14px 18px;
    box-sizing: border-box;
    /* 🚨 GEMESSEN, NICHT GERATEN (scripts/iq1-geo.js): `#menu-play` ist
       `display:flex; align-items:center; gap:10px`. Ohne `align-self` schrumpft
       der Rumpf auf seine Inhaltsbreite — gemessen 822 px gegen 1260 px
       Kopfzeile, am Maß unauffaellig, am Bild sofort falsch. Und die 10 px
       Luecke darueber ist die `gap` der Spalte, kein Aussenabstand: sie geht
       nur ueber einen negativen Aussenabstand derselben Groesse weg. */
    align-self: stretch;
    margin-top: -10px;
    padding: 14px 18px 16px;
    border: 1px solid rgba(var(--sq-goldRGB), 0.34);
    border-top: none;
    background: rgba(4, 8, 16, 0.80);
}
body.sq-sprache #screen-lobby #sq-raum .sq-raum-spalte {
    flex: 1 1 0;
    min-width: 180px;          /* Weg A: Masse nur ueber min-* */
    display: flex;
    flex-direction: column;
    gap: 9px;
}
/* Die Trennlinie zwischen „erstellen" und „beitreten" — die Vorlage zeigt
   zwei Haelften, nicht zwei Kaesten. */
body.sq-sprache #screen-lobby #sq-raum .sq-raum-spalte + .sq-raum-spalte {
    padding-left: 18px;
    border-left: 1px solid rgba(var(--sq-goldRGB), 0.18);
}
body.sq-sprache #screen-lobby #sq-raum .private-hint,
body.sq-sprache #screen-lobby #sq-raum .sq-raum-hinweis {
    margin: 0;
    font-size: 12px;
    line-height: 1.45;
    color: rgba(224, 232, 255, 0.72);
    text-align: left;
}
body.sq-sprache #screen-lobby #sq-raum .sq-room-set:empty { display: none; }
body.sq-sprache #screen-lobby #sq-raum .sq-room-set {
    margin: 0;
    font-size: 11px;
    color: rgba(var(--sq-cyanRGB), 0.85);
}
body.sq-sprache #screen-lobby #sq-raum .private-code-input {
    box-sizing: border-box;
    margin: 0;
    text-align: center;
    letter-spacing: 0.34em;
    font-family: 'Orbitron', monospace;
}
/* Die beiden Aktionsknoepfe bekommen die Kachel der Vorlage — dieselbe Form
   wie der Startknopf in Kasten 001/002, damit drei Kaesten dieselbe Sprache
   sprechen. `margin-top:auto` setzt sie auf eine Linie, auch wenn die Texte
   darueber verschieden lang sind. */
body.sq-sprache #screen-lobby #sq-raum .private-action-btn {
    box-sizing: border-box;
    margin: auto 0 0;
    padding: 10px 0;
    border: 1px solid rgba(var(--sq-goldRGB), 0.45);
    border-radius: 0;
    background: rgba(var(--sq-goldRGB), 0.07);
    color: var(--sq-gold);
    font-family: 'Orbitron', sans-serif;
    font-size: 11px;
    letter-spacing: 0.16em;
    clip-path: polygon(0 8px, 8px 0, calc(100% - 10px) 0, 100% 10px,
                       100% 100%, 10px 100%, 0 calc(100% - 8px));
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
body.sq-sprache #screen-lobby #sq-raum .private-action-btn:hover,
body.sq-sprache #screen-lobby #sq-raum .private-action-btn:focus-visible {
    border-color: var(--sq-cyan);
    background: rgba(var(--sq-cyanRGB), 0.12);
    color: var(--sq-cyan);
}
/* Der erstellte Code mit „Abbrechen" — volle Breite unter beiden Spalten. */
body.sq-sprache #screen-lobby #sq-raum > #privateRoomInfo {
    flex: 0 0 100%;
    margin: 0;
}
body.sq-sprache #screen-lobby #sq-raum > #privateRoomInfo.hidden { display: none; }


/* ══ 13. Die Suche (#queueStatus) ══════════════════════════════════════════
   IR1 (2026-09-17). Marcel, 17.09.: „Suche und Annahme koennen wir schon
   basteln."

   🚨 GEMESSEN VOR DEM BAU (scripts/ir1-lage.js, Lauf 0554):
   Der Suchbildschirm des FREIEN Spiels ist `#queueStatus` in `#menu-play` —
   vier Kinder: die Pulszeile („Suche laeuft..."), `#queueInfo`, das
   FF1-Lebenszeichen `#sq-presence-queue` und der Abbrechen-Link.
   ⚠ **Er traegt KEIN Canvas und keinen Ring** (gemessen: `canvas: 0`); das
   „laeuft"-Zeichen ist `.lobby-pulse`. Die Vorlage (mockups/bildschirme-neue-
   sprache.html, `#s-suche`) zeigt dort einen Ring — der gehoert zum
   ANMELDE-Weg (`#menu-backbone-searching`, `#bb-search-ring`) und steht in
   einem anderen Bildschirm (`#screen-backbone-hub`), den die Formsprache nie
   angefasst hat. Hier wird darum KEIN Ring hinzugebaut: ein zweites Bauteil
   waere genau das, was der Rundenauftrag verbietet. Die Pulszeile bleibt, wie
   sie ist, und wird nur umgekleidet.

   🚨 DAS LEBENSZEICHEN BLEIBT STEHEN. IQ1 hat die Anwesenheitszeile in der
   Lobby ausgeblendet (`#sq-presence-lobby`, Abschnitt 11) — hier ist sie der
   Sinn der Sache. Die beiden haengen am selben Renderer (`sqRenderPresence()`)
   und am selben DB-Schalter; getroffen wird jede ueber ihre EIGENE Kennung,
   nie ueber die gemeinsame Klasse `.sq-presence`.

   ⚠ Der Bot-Hinweis bei null Mitsuchenden (`presence_bot_hint_enabled`) sitzt
   NICHT in diesem Kasten, sondern auf `#warte-bot-btn` (Klasse
   `.sq-botangebot`, Unterzeile „KEIN GEGNER GEFUNDEN", Fix FV1). Er wird hier
   nicht angefasst und bleibt damit unveraendert der einzige Ausweg aus einer
   leeren Warteschlange.

   Die Aussenmasse: keine. `#queueStatus` ist kein gefuehrtes Element; Breite
   kommt aus Abschnitt 11 (`max-width: 560px`) und bleibt dort stehen. */

/* Der Kasten selbst: Rahmen der Vorlage. Das `padding` faellt weg, damit die
   Kopfzeile bis an die Kante geht — der Rumpf traegt es stattdessen selbst.
   Genau daran haengt das Sollmass „Rumpf gegen Kopfzeile": beide sind dann
   exakt so breit wie der Kasten. */
body.sq-sprache #screen-lobby #menu-play #queueStatus {
    position: relative;
    padding: 0;
    border-color: rgba(var(--sq-goldRGB), 0.45);
    overflow: hidden;
    text-align: left;
}
/* Der goldene Balken links und der Gefahrenstreifen oben rechts — dieselben
   zwei Pseudo-Elemente wie an jedem Rahmen der Vorlage. */
body.sq-sprache #screen-lobby #menu-play #queueStatus::before {
    content: ''; position: absolute; left: 0; top: 13px;
    width: 3px; height: 30px; background: var(--sq-gold);
}
body.sq-sprache #screen-lobby #menu-play #queueStatus::after {
    content: ''; position: absolute; right: 8px; top: 0;
    width: 40px; height: 8px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.8) 0 4px, transparent 4px 9px);
}
/* Die Kopfzeile ist die VORHANDENE Pulszeile — kein neuer Knoten, kein neuer
   Text. Sie traegt „Suche laeuft..." schon; hier bekommt sie die Form der
   `.sq-kasten-kopf` aus Abschnitt 5. */
body.sq-sprache #screen-lobby #menu-play #queueStatus .lobby-pulse-row {
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: 8px 14px 7px;
    gap: 9px;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--sq-cyanHell);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.28);
    justify-content: flex-start;   /* die Vorlage setzt die Kopfzeile links,
        die Kennung rechts (`.kopf`) — nicht mittig wie die Pulszeile heute */
}
/* Die Indexnummer der Vorlage. Ein Zeichen, kein Text — hier ist nichts zu
   uebersetzen (dieselbe Entscheidung wie `NET` am Status-Kasten). */
body.sq-sprache #screen-lobby #menu-play #queueStatus .lobby-pulse-row::after {
    content: 'Q';
    margin-left: auto;
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-goldRGB), 0.62);
}
/* Der Rumpf. Beide Zeilen tragen dasselbe Seitenmass wie die Kopfzeile und
   sind dadurch exakt so breit wie sie — das ist das Sollmass, nicht „ist da". */
body.sq-sprache #screen-lobby #menu-play #queueStatus > #queueInfo,
body.sq-sprache #screen-lobby #menu-play #queueStatus > #sq-presence-queue {
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: 7px 14px 0;
}
body.sq-sprache #screen-lobby #menu-play #queueStatus > #queueInfo:empty {
    display: none;
}
/* Die Zeile der Vorlage: Beschriftung gedimmt, die Zahl gold. Der Text kommt
   unveraendert aus `sqPresenceText()` — gefaerbt wird nur. */
body.sq-sprache #screen-lobby #menu-play #queueStatus > #sq-presence-queue {
    font-family: 'Share Tech Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    color: var(--sq-gold);
    /* ⚠ Ausdruecklich, nicht geerbt: `.sq-presence` (game-v3.css) setzt
       `text-align:center`, das `text-align:left` am Kasten erreicht sie also
       nicht. Mittig unter einer linksbuendigen Kopfzeile sieht aus wie ein
       Versehen — die Vorlage setzt beide Zeilen links. */
    text-align: left;
}
/* Abbrechen — die rote Rolle der Vorlage. Gefahr wird nicht eingefaerbt. */
body.sq-sprache #screen-lobby #menu-play #queueStatus > .menu-link {
    display: block;
    /* `auto` und nicht das Seitenmass des Rumpfes: ein <button> mit
       `display:block` bleibt inhaltsbreit, er waechst nicht auf die
       Kastenbreite — mit festem Seitenmass klebte er links am Rand. */
    margin: 12px auto;
    padding: 7px 14px;
    border: 1px solid rgba(224, 32, 32, 0.6);
    background: rgba(224, 32, 32, 0.07);
    color: #ff8a8a;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    clip-path: polygon(0 6px, 6px 0, calc(100% - 8px) 0, 100% 8px,
                       100% 100%, 8px 100%, 0 calc(100% - 6px));
    transition: background 0.15s ease, color 0.15s ease;
}
body.sq-sprache #screen-lobby #menu-play #queueStatus > .menu-link:hover {
    background: rgba(224, 32, 32, 0.18);
    color: #ffc2c2;
}


/* ══ 14. Die Annahme (#match-proposed-overlay) ═════════════════════════════
   IR1 (2026-09-17). Marcel, 17.09.: „Annahme soll vom Effekt sein wie aktuell
   beim Anmeldeweg, nur halt in der Designsprache nun."

   🚨 DIE CHOREOGRAFIE BLEIBT VOLLSTAENDIG. Hier steht KEINE Regel, die
   `animation`, `animation-delay`, `animation-name` oder die Reihenfolge der
   Kinder anfasst. Die fuenf Verzoegerungen sind unveraendert die aus
   game-v3.css (gemessen vor UND nach dem Umbau, scripts/ir1-nachweis.js):
       .mp-d1 180ms mpRiseRight · .mp-d2 270ms mpRiseLeft · .mp-d3 400ms mpPop
       · .mp-d4 520ms mpRise     · .mp-d5 640ms mpRise
   Ebenso unberuehrt: `SqRing` (EIN Ring, dasselbe Bauteil wie Ladering und
   Peilring), der Textknoten `#match-proposed-countdown` mit den Restsekunden
   und die Handler/Kennungen von Annehmen und Ablehnen.

   ⚠ WARUM DIESE REGELN NICHT MIT `#screen-lobby` BEGINNEN (Ausnahme zur
   Dateiregel oben): die Ueberlagerung haengt an `<body>`, nicht in einem
   Bildschirm — `showMatchProposedOverlay()` macht `document.body.appendChild`.
   Der Vorfahre IST weiterhin der Schalter, und nur er.

   🚨 DER RING WANDERT NICHT IN DIE MITTE. Die Vorlage (`#s-annahme`) setzt ihn
   zwischen die beiden Seiten; das waere eine Umsortierung der gestaffelten
   Kinder und damit genau die Choreografie, die Marcel behalten will
   („wie aktuell"). Die Anordnung von heute bleibt: Kopfzeile · Duell · Ring ·
   Hinweis · Knoepfe.

   ⚠ BEFUND, NICHT HIER GELOEST: die beiden Wege zeigen NICHT dasselbe Bild.
   `backboneMatchProposed` (Anmeldeweg) reicht `faction`/`opponentFaction`
   durch — Wappen, Fraktionsnamen, Hinweiszeile, Kasten 428x439.
   `matchProposed` (freies Spiel) bekommt sie vom Server gar nicht
   (plugins/game.js:3703 sendet `{matchToken, opponent, timeoutMs}`) — zwei
   Fragezeichen-Platzhalter, keine Fraktionsfarbe, Kasten 340x398. Die
   Formsprache kleidet beide gleich; die fehlende Auskunft kann sie nicht
   erfinden. Der Weg dorthin fuehrt ueber die Server-Nachricht und damit ueber
   `plugins/` — Kandidatenliste, nicht diese Runde. */

/* Der Kasten. Gold = Gehaeuse; die Eckabschnitte der Vorlage ersetzen den
   zweiseitigen Chamfer von heute. `padding: 0`, damit die Kopfzeile an die
   Kante geht — der Rumpf traegt sein Seitenmass selbst (Sollmass „Rumpf gegen
   Kopfzeile"). */
body.sq-sprache #match-proposed-overlay .mp-box {
    padding: 0 0 20px;
    background: rgba(4, 8, 16, 0.94);
    border-color: rgba(var(--sq-goldRGB), 0.45);
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    overflow: hidden;
}
/* Der goldene Balken links. Er ERSETZT die Verlaufslinie von heute
   (`.mp-box::before` in game-v3.css) — dasselbe Pseudo-Element, andere
   Kleidung, kein zusaetzlicher Knoten. */
body.sq-sprache #match-proposed-overlay .mp-box::before {
    left: 0;
    top: 14px;
    right: auto;
    width: 3px;
    height: 32px;
    background: var(--sq-gold);
}
body.sq-sprache #match-proposed-overlay .mp-box::after {
    content: ''; position: absolute; right: 10px; top: 0;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
    pointer-events: none;
}
/* Die Kopfzeile ist der VORHANDENE Titel („GEGNER GEFUNDEN"). Kein neuer
   Knoten, kein neuer Text — dieselbe Form wie `.sq-kasten-kopf`. */
body.sq-sprache #match-proposed-overlay .mp-title {
    box-sizing: border-box;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 0 14px;
    padding: 8px 14px 7px;
    font-size: 10px;
    letter-spacing: 0.28em;
    color: var(--sq-cyanHell);
    text-shadow: none;
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.28);
}
/* Die Indexnummer. Ein Zeichen, kein Text. */
body.sq-sprache #match-proposed-overlay .mp-title::after {
    content: 'M';
    position: absolute;
    right: 14px;
    /* 🚨 Senkrecht GESETZT, nicht geraten: ein absolut gesetztes Kind eines
       Flex-Kastens bekaeme sonst die „statische Lage", und die haengt an
       align-items. Der Bezugskasten ist `.mp-box` (das einzige positionierte
       Element darueber), darum reicht `right` allein nicht. */
    top: 12px;
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-goldRGB), 0.62);
}
/* Der Rumpf: dasselbe Seitenmass wie die Kopfzeile, volle Kastenbreite. */
body.sq-sprache #match-proposed-overlay .mp-duel,
body.sq-sprache #match-proposed-overlay .mp-hint,
body.sq-sprache #match-proposed-overlay .mp-btns {
    box-sizing: border-box;
    width: 100%;
    padding-left: 14px;
    padding-right: 14px;
}
/* Der Fragezeichen-Platzhalter des freien Spiels bekommt die Kante der
   Vorlage — er bleibt ein Platzhalter, er wird kein geratenes Wappen. */
body.sq-sprache #match-proposed-overlay .mp-icon-unknown {
    border-color: rgba(var(--sq-goldRGB), 0.30);
    background: rgba(var(--sq-goldRGB), 0.05);
    color: rgba(var(--sq-goldRGB), 0.55);
}
/* Die Hinweiszeile: die gedimmte Sperrschrift der Vorlage. */
body.sq-sprache #match-proposed-overlay .mp-hint {
    font-family: 'Share Tech Mono', monospace;
    font-size: 10px;
    letter-spacing: 0.16em;
    color: #8b93a8;
}
/* Die Knopfform der Vorlage (`.knopf`), fuer beide gleich. */
body.sq-sprache #match-proposed-overlay .mp-btn {
    border-radius: 0;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    clip-path: polygon(0 8px, 8px 0, calc(100% - 10px) 0, 100% 10px,
                       100% 100%, 10px 100%, 0 calc(100% - 8px));
}
/* 🚨 ANNEHMEN ist der EINZIGE Knopf, der von sich aus leuchtet (`.knopf.bereit`)
   — er ist genau der, der etwas vom Spieler will. Dieselbe Bauform und
   dasselbe Keyframe wie der Pre-Enlist-Knopf in Abschnitt 5.
   ⚠ ABLEHNEN bekommt es NICHT: pulsieren zwei, bedeutet es nichts mehr. */
body.sq-sprache #match-proposed-overlay .mp-btn-yes {
    background: rgba(var(--sq-cyanRGB), 0.12);
    border-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
    animation: sqBereitPuls 2.4s ease-in-out infinite;
}
body.sq-sprache #match-proposed-overlay .mp-btn-yes:hover {
    background: rgba(var(--sq-cyanRGB), 0.22);
    color: #ffffff;
    filter: none;
}
/* Ablehnen traegt die rote Rolle der Vorlage — dieselbe wie „Abbrechen" in
   der Suche. Gefahr ist eine eigene Rolle und wird nicht eingefaerbt. */
body.sq-sprache #match-proposed-overlay .mp-btn-no {
    background: rgba(224, 32, 32, 0.07);
    border-color: rgba(224, 32, 32, 0.6);
    color: #ff8a8a;
}
body.sq-sprache #match-proposed-overlay .mp-btn-no:hover {
    background: rgba(224, 32, 32, 0.18);
    border-color: rgba(224, 32, 32, 0.85);
    color: #ffc2c2;
}
/* Wer Bewegung abbestellt hat, bekommt kein Pulsieren — dieselbe Entscheidung
   wie in Abschnitt 9. Der Knopf bleibt cyan und damit weiterhin der eine, der
   antwortet; nur der Herzschlag faellt weg. */
@media (prefers-reduced-motion: reduce) {
    body.sq-sprache #match-proposed-overlay .mp-btn-yes { animation: none; }
}


/* == 12. Das Versionsschild wandert in die Spalte =========================
   IW1 (2026-09-17). Marcel: „Die Versionsnummer wandert zwischen den
   ,Spiel starten'-Knopf und den ,Kickstarter 2026'-Schriftzug, so hatten wir
   das auch im Mockup." Die Vorlage hat dort genau eine solche Zeile —
   `Trading Card Game · v0.7.370`, direkt unter dem Titelblock und ueber dem
   Menue (mockups/bildschirme-neue-sprache.html, Zeile 190-193).

   WER DAS SCHILD IST — am laufenden Bildschirm gefunden, nicht im Markup
   gesucht (scripts/iw1-fund.js): `#version-label-lobby`, ein
   `div.version-tag` aus views/play-v3.ejs:695. Sein TEXT hat ZWEI Schreiber:
     * der Bau setzt ihn (scripts/render-play-html.js:61 -> „Star Squadrons
       v0.7.423-live.<Zeitstempel> · Datum Zeit"), und
     * die Verbindung ueberschreibt ihn beim Ereignis `serverVersion`
       (public/js/game-core.js:4277-4282 -> `VERSION.full`).
   Auf dem Bildschirm steht deshalb etwas ANDERES als im ausgelieferten HTML,
   und beides aendert sich mit jedem Bau. Genau darum nimmt jeder
   Bildvergleich dieser Woche das Schild aus.

   VERSCHOBEN WIRD MIT `order`, NICHT MIT KOORDINATEN.
   `#lobby-main` ist ohnehin eine Flex-Spalte (game-v3.css `.lobby-main`:
   `display:flex; flex-direction:column; align-items:center`), und `order` ist
   in dieser Datei schon der Weg (IN1, Abschnitt 10: „kein Knoten wird
   geloescht, ersetzt oder verschoben"). Der Knoten bleibt, wo er im Markup
   steht — er wird nur an anderer Stelle gemalt. Ein absoluter Ort waere eine
   Zahl, die bei jeder Aenderung am Titelblock nachgezogen werden muesste.
   ⚠ `.menu-container` braucht dafuer eine EIGENE `order`: bleiben beide
   Geschwister auf 0, gewinnt die Markup-Reihenfolge, und das Schild stuende
   weiterhin zuletzt — hinter dem Menue.

   `position: static` nimmt das `position: fixed` aus game-v3.css:3276 zurueck
   (nur so ist das Schild ueberhaupt ein Flex-Kind); `left/bottom: auto`
   raeumen die dort gesetzten Koordinaten mit ab.
   `white-space: nowrap` ist keine Schoenheit: der Text traegt einen
   Zeitstempel und waechst mit jedem Bau — ohne ihn braeche er irgendwann um
   und schoebe die Knoepfe nach unten.

   DAS SOLLMASS KOMMT AUS DER VORLAGE, nicht aus dem Gefuehl: dort steht die
   Zeile 6px unter dem Titelblock, das Menue 26px unter ihr
   (`padding:18px 0 6px` am Titelblock, `margin-top:26px` am Menue).
   Hier uebernimmt das Schild die 28px `margin-bottom` des Titelblocks
   (game-v3.css `.lobby-header`) als Abstand nach unten, damit das Menue
   genau dort stehen bleibt, wo es heute steht — der Titelblock gibt sie ab.

   ⚠ NUR IM EIN-ZUSTAND. Im Aus-Zustand bleibt das Schild unten links; die
   Formsprache verschiebt es, sie zieht nicht um. */
body.sq-sprache #screen-lobby .lobby-header        { order: 0; margin-bottom: 0; }
body.sq-sprache #screen-lobby #version-label-lobby { order: 1; }
body.sq-sprache #screen-lobby .menu-container      { order: 2; }

body.sq-sprache #screen-lobby #version-label-lobby {
    position: static;
    left: auto;
    bottom: auto;
    margin: 6px 0 28px;
    max-width: 100%;
    white-space: nowrap;
    text-align: center;
}


/* ══ 15. DIE VORSPIELKETTE — die drei Bildschirme vor der ersten Runde ══════
   IY1 (2026-09-17). Vorlagen in mockups/bildschirme-neue-sprache.html:
   `#s-starthand` (Starthand-Auswahl) · `#s-beide` (beide Starthaende) ·
   `#s-wurf` (Startspieler-Wurf).

   🚨 DIE KARTENAUSWAHL BLEIBT UNANGETASTET. Sie ist die Bedienung; was hier
   steht, kleidet den Rahmen darum. `.vanguard-grid`, `.vanguard-card*` und
   `#vg-confirm-btn` kommen in diesem Abschnitt nicht vor — nachgemessen im
   A/B: die Auswahl waehlt, waehlt ab und bestaetigt unveraendert.

   MASSREGEL (CLAUDE.md, Weg A). Gemessen, nicht angenommen: von diesen drei
   Bildschirmen fuehrt `layout-config.js` genau EIN Element — `vanguard-panel`
   (`vanguard` -> `stretch-both`, Raender 0). `start-roll` fuehrt nichts
   (`"start-roll": { "default": {} }`). Deshalb:
     * `#vanguard-panel` bekommt hier KEIN Mass.
     * `.sq-vg-tafel`, `.sq-vg-rumpf` und `.sq-wurf-hof` sind NEUE, ungefuehrte
       Knoten (sq-sprache.js baut sie im Ein-Zustand). Sie tragen ihre eigene
       Breite — ohne `!important`, ohne eine Zeile in layout-config.js.
     * Kein `width: … !important` irgendwo: es staeche auch den Inline-Stil des
       AUS-Zustands, sobald ein Selektor einmal zu weit gefasst ist (IO1).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 15.1 Starthand-Auswahl (#screen-vanguard) ─────────────────────────────
   Kopf UND Punkteleiste in EINER Tafel. Der Grund steht im Mockup-Kommentar:
   „auf dem hellen Hintergrund war der freistehende Text kaum zu lesen."
   Gemessen im Aus-Zustand: heute stehen `.vanguard-title`, `.vanguard-info`
   und `.vanguard-vp-meter` als drei freistehende Geschwister im Panel
   (`einTafel: false`). Die Tafel traegt dieselbe Form wie die Kaesten der
   Lobby (Abschnitt 5/6): angeschnittene Ecken, goldener Balken links,
   Gefahrenstreifen oben rechts. */
body.sq-sprache #screen-vanguard .sq-vg-tafel {
    position: relative;
    box-sizing: border-box;
    width: 100%;
    max-width: 900px;
    margin: 0 auto 16px;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-goldRGB), 0.45);
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    text-shadow: none;
    flex: none;
}
body.sq-sprache #screen-vanguard .sq-vg-tafel::before {
    content: ''; position: absolute; left: -1px; top: 14px;
    width: 3px; height: 34px; background: var(--sq-gold);
}
body.sq-sprache #screen-vanguard .sq-vg-tafel::after {
    content: ''; position: absolute; right: 8px; top: -1px;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
}

/* Die Kopfzeile ist der VORHANDENE Titel (`.vanguard-title`, Schluessel
   VG_TITEL) — kein neuer Knoten und keine neue Zeichenkette. Die Vorlage
   nennt ihn „Starthand"; im Bestand heisst er „STARTHAND AUSWAHL", und das
   ist derselbe Satz. Ein eigener Text waere ein zwoelfter Woerterbuch-
   eintrag fuer nichts. */
body.sq-sprache #screen-vanguard .sq-vg-tafel .vanguard-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 16px 7px;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--sq-gold);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.28);
}
/* Die Indexnummer der Vorlage. 🚨 Ziffern, kein Text — hier ist nichts zu
   uebersetzen, und ein Wort im Stylesheet waere hartkodiertes Deutsch. */
body.sq-sprache #screen-vanguard .sq-vg-tafel .vanguard-title::after {
    content: '001';
    font-size: 9px;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-cyanRGB), 0.62);
}

/* Der Rumpf: links die Anleitung, rechts die Vanguardpunkte, darunter die
   Leiste ueber die volle Breite — genau die Anordnung der Vorlage.

   🚨 `display: contents` an `.vanguard-vp-meter`: die Leiste liegt im Markup
   IM Messer, soll aber eine eigene Rasterzeile ueber die volle Breite tragen.
   Ohne `contents` muesste sq-sprache.js den Knoten aus dem Messer heraus-
   heben — ein Umbau am Bestand fuer eine reine Anordnungsfrage. So bleibt
   das Markup, wie es ist, und nur die Box faellt weg. */
body.sq-sprache #screen-vanguard .sq-vg-rumpf {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    column-gap: 24px;
    row-gap: 4px;
    padding: 14px 20px 16px;
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-info {
    grid-area: 1 / 1 / 3 / 2;
    align-self: start;
    font-family: 'Rajdhani', sans-serif;
    font-size: 13px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.82);
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-meter {
    display: contents;
}
/* Die Beschriftung „VANGUARDPOINTS" ist die VORHANDENE — sie traegt einen
   Inline-Stil aus dem EJS (Orbitron, 9px, gesperrt, gedimmt). Der wird NICHT
   ueberstimmt: er sagt bereits dasselbe wie die Vorlage, und ein `!important`
   dagegen waere genau die Sorte Regel, die den Aus-Zustand mitreisst. Hier
   wird sie nur PLATZIERT. */
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-meter > span:first-child {
    grid-area: 1 / 2 / 2 / 3;
    justify-self: end;
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-label {
    grid-area: 2 / 2 / 3 / 3;
    justify-self: end;
    font-family: 'Orbitron', sans-serif;
    font-size: 26px;
    line-height: 1.1;
    color: rgba(255, 255, 255, 0.45);
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-label #vg-vp-cur {
    color: var(--sq-gold);
    font-weight: 700;
}

/* Die unterteilte Leiste der Vorlage: vier Felder, angeschnittene Ecken,
   goldener Rahmen. Die Unterteilung ist ein Verlauf im Stylesheet und KEIN
   neuer Knoten — vier `<span>` waeren vier Knoten fuer drei Striche. */
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-bar-wrap {
    grid-area: 3 / 1 / 4 / 3;
    position: relative;
    height: 15px;
    margin-top: 12px;
    padding: 1px;
    background: rgba(2, 4, 10, 0.55);
    border: 1px solid rgba(var(--sq-goldRGB), 0.45);
    border-radius: 0;
    clip-path: polygon(7px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-bar-wrap::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;      /* die Leiste ist Anzeige, kein Ziel */
    background: repeating-linear-gradient(to right,
        transparent 0 calc(25% - 1px), rgba(2, 4, 10, 0.75) calc(25% - 1px) 25%);
}
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-bar-fill {
    border-radius: 0;
    background: linear-gradient(90deg,
        rgba(var(--sq-goldRGB), 0.22), rgba(var(--sq-goldRGB), 0.75));
    box-shadow: none;
}
/* Ueberzogen bleibt rot — Gefahr ist eine eigene Rolle und wird nicht
   eingefaerbt (dieselbe Entscheidung wie beim Beenden-Knopf, Abschnitt 2). */
body.sq-sprache #screen-vanguard .sq-vg-rumpf .vanguard-vp-bar-fill.over {
    background: linear-gradient(90deg, rgba(208, 96, 96, 0.3), rgba(208, 96, 96, 0.85));
}

/* ── 15.2 Beide Starthaende (#sq-beide-haende-overlay) ─────────────────────
   Die Struktur steht seit IU1 und ist die der Vorlage: ein Titel, zwei Reihen
   mit Kopfzeile (Fraktion · Name | N KARTEN · M VP) und Rumpf, darunter der
   Zaehler. Hier kommt NUR die Formsprache dazu — kein Knoten, kein Text.

   🚨 Die Grenze aus IU1 gilt unveraendert: gezeichnet wird, was in
   `vanguardCardIds` steht, also NUR die aufgedeckte Vorhut. Dieser Abschnitt
   fasst die Nutzlast nicht an; es gibt hier keine Regel, die „alle
   Handkarten" zeichnen wuerde, und der erzwungene Gegenbeweis steht im
   Bericht. */
body.sq-sprache #sq-beide-haende-overlay .sq-dr-label {
    display: inline-block;
    margin: 0 auto 18px;
    padding: 9px 32px;
    background: rgba(2, 4, 10, 0.94);
    border: 1px solid rgba(var(--sq-goldRGB), 0.5);
    clip-path: polygon(14px 0, 100% 0, calc(100% - 14px) 100%, 0 100%);
    font-family: 'Orbitron', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3em;
    color: var(--sq-gold);
    text-shadow: none;
}
body.sq-sprache #sq-beide-haende-overlay .sq-bh-reihe {
    position: relative;
    background: rgba(4, 8, 16, 0.90);
    border-radius: 0;
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    text-shadow: none;
}
/* Der goldene Balken links — an JEDER Reihe derselbe, in ihrer Fraktions-
   farbe. Der Gefahrenstreifen oben rechts bleibt gold: er gehoert zum
   Gehaeuse, nicht zur Partei. */
body.sq-sprache #sq-beide-haende-overlay .sq-bh-reihe::before {
    content: ''; position: absolute; left: -1px; top: 14px;
    width: 3px; height: 34px; background: currentColor;
}
body.sq-sprache #sq-beide-haende-overlay .sq-bh-reihe.vs  { color: rgba(220, 100, 100, 0.85); }
body.sq-sprache #sq-beide-haende-overlay .sq-bh-reihe.ued { color: rgba(51, 204, 204, 0.85); }
body.sq-sprache #sq-beide-haende-overlay .sq-bh-reihe::after {
    content: ''; position: absolute; right: 8px; top: -1px;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
}
body.sq-sprache #sq-beide-haende-overlay .sq-bh-kopf {
    padding: 8px 16px 7px;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.28em;
    text-transform: uppercase;
}
/* Die Kartenzahl und die VP stehen rechts wie die Indexnummer der Vorlage. */
body.sq-sprache #sq-beide-haende-overlay .sq-bh-zahl {
    font-size: 9px;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-cyanRGB), 0.62);
}
body.sq-sprache #sq-beide-haende-overlay .sq-bh-zahl b { color: var(--sq-gold); }
/* Der Zaehler unten: die gedimmte Sperrschrift der Vorlage, der Balken gold. */
body.sq-sprache #sq-beide-haende-overlay .sq-bh-fuss .sq-dr-timer {
    font-family: 'Orbitron', sans-serif;
    font-size: 11px;
    letter-spacing: 0.26em;
    color: rgba(139, 147, 168, 0.85);
}
body.sq-sprache #sq-beide-haende-overlay .sq-bh-fuss .sq-dr-timer-bar {
    background: var(--sq-gold);
}

/* ── 15.3 Startspieler-Wurf (#sq-start-roll-overlay) ───────────────────────
   Fix OF1 (2026-10-03): ENTFALLEN. Das Aussehen steht jetzt nach
   mockups/versus-und-startwurf.html (v6) in game-v3.css („Fix OF1"), fuer beide
   Schalterstellungen gleich. Ring und `.sq-dr-die` gibt es im Wurf nicht mehr — der
   Wuerfel ist ein W20 (SVG, `.sq-w20`); sq-sprache.js findet deshalb keinen
   `.sq-dr-die` mehr und kleidet nichts ein. */


/* ══ 16. SIEG UND NIEDERLAGE ═══════════════════════════════════════════════
   Fix OG1 (2026-10-03): ENTFALLEN. Der Spielende-Bildschirm ist nach
   mockups/spielende-mit-wiederholung.html neu gebaut; sein Aussehen steht in
   game-v3.css („Fix OG1"), fuer beide Schalterstellungen gleich. Die
   IZ1-Kaesten (Orte am Ende, Verlauf, Kachel Zerstoert) traegt der neue
   Bildschirm selbst. */


/* ══ 17. DER CHAT ══════════════════════════════════════════════════════════
   IZ1 (2026-09-17). Vorlage: `#s-chat`.

   🚨 GEMESSEN VOR DEM BAU (scripts/iz1-lage.js, Abschnitt B): der Chat ist
   KEINE Ebene und kein Vollbild-Modal, sondern ein angedocktes, festes Panel
   (`position: fixed`, 320 x 194 px, unten rechts, Kind von <body>) — Fix AT1
   hat das ausdruecklich so gebaut, damit das Match dahinter sichtbar bleibt.
   Diese Bauart wird NICHT angetastet: die zweite Spalte der Vorlage
   (Schnellzeichen, Einstellungen) haette daraus ein Fenster gemacht, das das
   Brett verdeckt. Uebernommen wird die FORM, nicht die Flaeche.

   🚨 UND `cleanupChatPanel()` BLEIBT DER AUSGANG. Es setzt `.hidden` am
   Panel, leert den Verlauf und stellt den Schubladenzustand zurueck
   (game-chat.js, gerufen aus showScreen()). Hier steht KEINE Regel, die
   `.hidden` uebersteuert — sonst bliebe nach dem Spielende eine Huelle
   stehen. Der Anwesenheitspunkt haengt IM Kopf und geht mit ihm weg. */

body.sq-sprache #modal-chat {
    background: linear-gradient(180deg, rgba(8, 13, 24, 0.95), rgba(5, 8, 16, 0.96));
    border: 1px solid rgba(var(--sq-goldRGB), 0.42);
    border-radius: 0;
    clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}
/* Der Balken links — der Gefahrenstreifen entfaellt hier bewusst: der Chat
   ist kein Gefahrenort, und der Streifen ist in der Vorlage die Ausnahme,
   nicht die Regel. */
body.sq-sprache #modal-chat .sq-chat-header {
    position: relative;
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--sq-cyanHell);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.28);
}
body.sq-sprache #modal-chat .sq-chat-header::before {
    content: ''; position: absolute; left: 0; top: 9px;
    width: 3px; height: 20px; background: var(--sq-gold);
}
/* Die Kennung mit dem Anwesenheitspunkt. Sie steht rechts, vor dem Kreuz. */
body.sq-sprache #modal-chat .sq-chat-kennung {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    margin-right: 8px;
    font-family: 'Orbitron', monospace;
    font-size: 8.5px;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: rgba(var(--sq-cyanRGB), 0.85);
}
body.sq-sprache #modal-chat .sq-chat-punkt {
    width: 6px; height: 6px;
    background: var(--sq-cyan);
    /* 🚨 Kein Pulsieren. Ein blinkender Punkt zoege den Blick vom Brett ab —
       und „online" ist ein Zustand, kein Ereignis. */
    box-shadow: 0 0 7px rgba(var(--sq-cyanRGB), 0.7);
}
body.sq-sprache #modal-chat .sq-chat-kennung.sq-weg { color: rgba(255, 138, 138, 0.85); }
body.sq-sprache #modal-chat .sq-chat-kennung.sq-weg .sq-chat-punkt {
    background: #e02020;
    box-shadow: 0 0 7px rgba(224, 32, 32, 0.7);
}
/* Verlauf, Eingabe und Senden — die Kachel und der Knopf der Vorlage. */
body.sq-sprache #modal-chat .sq-chat-input-row {
    border-top: 1px solid rgba(var(--sq-goldRGB), 0.22);
}
body.sq-sprache #modal-chat .sq-chat-input {
    background: rgba(12, 18, 32, 0.7);
    border: 1px solid rgba(139, 147, 168, 0.28);
    border-radius: 0;
    font-family: 'Share Tech Mono', monospace;
    color: rgba(204, 213, 226, 0.92);
}
body.sq-sprache #modal-chat .sq-chat-input:focus {
    border-color: rgba(var(--sq-cyanRGB), 0.6);
    outline: none;
}
body.sq-sprache #modal-chat .sq-chat-send-btn {
    background: rgba(var(--sq-goldRGB), 0.1);
    border: 1px solid rgba(var(--sq-goldRGB), 0.5);
    border-radius: 0;
    clip-path: polygon(0 5px, 5px 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 5px));
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--sq-gold);
    transition: background 0.15s ease, color 0.15s ease;
}
body.sq-sprache #modal-chat .sq-chat-send-btn:hover {
    background: rgba(var(--sq-cyanRGB), 0.16);
    border-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
}
body.sq-sprache #modal-chat .sq-chat-mute-row {
    font-family: 'Share Tech Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    color: rgba(139, 147, 168, 0.8);
}


/* ══ 18. DIE OPTIONEN — BEIDE OBERFLAECHEN ═════════════════════════════════
   IZ1 (2026-09-17). Vorlage: `#s-optionen`.

   🚨 GEMESSEN VOR DEM BAU, und der Befund weicht vom Rundenauftrag ab
   (scripts/iz1-lage.js, Abschnitt C). Der Auftrag sagt, game-sounds.js
   schreibe in vier Regler und es gebe die Optionen deshalb zweimal —
   in der Uebersicht (`sq-ov-*`) und in den Einstellungen (`sq-settings-*`).
   Gemessen ist es anders und in einem Punkt gefaehrlicher:

     * `sq-ov-music-slider` / `sq-ov-sfx-slider` sind `display:none` — sie
       stehen als unsichtbare Spiegel im Uebersichts-Markup (game-overview.js)
       und sind KEINE Oberflaeche. Sie zu kleiden waere Arbeit an nichts.
     * Die beiden SICHTBAREN Oberflaechen sind `#menu-settings` (Lobby,
       Einstellungs-Ebene) und `#modal-options` (im Spiel, mit Aufgeben und
       Tipps).
     * 🚨 `#modal-options` benutzt ein DRITTES Reglerpaar (`sq-options-*`), in
       das game-sounds.js gerade NICHT schreibt. Der Auftrag haette also die
       eine Oberflaeche gekleidet, die keine ist, und die eine uebersehen, die
       die Vorlage zeigt.

   Gekleidet werden deshalb BEIDE sichtbaren Oberflaechen — mit denselben
   Regeln fuer die gemeinsame Bauform (`.setting-row`, `.menu-slider`), damit
   sie nicht auseinanderlaufen koennen. Das ist der Sinn von Zusicherung 9. */

/* ── Die gemeinsame Zeile: Beschriftung links, Regler rechts ─────────────── */
body.sq-sprache #menu-settings .setting-row,
body.sq-sprache #modal-options .setting-row {
    border-bottom: 1px solid rgba(139, 147, 168, 0.12);
    /* 🚨 `.setting-row` steht in game-v3.css auf `width: 270px`. Gemessen passt
       „🔊 Soundeffekte" samt Regler und Schalter dort nicht hinein — der
       Schalter stand 6 px ausserhalb seiner eigenen Zeile, schon vor dieser
       Runde. Die Zeile nimmt jetzt die Breite ihrer Tafel. */
    /* `100%` und nicht `auto`: in der Lobby steht die Zeile in einer
       Flex-Spalte, und `auto` liess jede Zeile ihre eigene Inhaltsbreite
       nehmen — 356 gegen 422 px (gemessen). Gegen die TAFEL gemessen sind
       beide gleich breit, und genau das ist die Zusage. */
    width: 100%;
    box-sizing: border-box;
}
body.sq-sprache #menu-settings .setting-label,
body.sq-sprache #modal-options .setting-label {
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(139, 147, 168, 0.85);
    /* 🚨 Die Beschriftung nimmt den Rest der Zeile — und gibt ihn wieder her,
       wenn es eng wird. Ohne `min-width: 0` kann ein Flex-Kind NICHT unter
       seine Inhaltsbreite schrumpfen; die laengere Beschriftung schob dann
       Regler und Schalter aus der Zeile heraus (gemessen: 43 px). */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}
/* Ein Mass fuer beide Schalterstellungen: „OFF" ist breiter als „ON", und ohne
   festes Mass hingen die Regler der beiden Zeilen verschieden weit links. */
body.sq-sprache #menu-settings .setting-row button,
body.sq-sprache #modal-options .setting-row button {
    min-width: 34px;
    text-align: center;
    flex: 0 0 auto;
}
body.sq-sprache #menu-settings .menu-slider,
body.sq-sprache #modal-options .menu-slider {
    accent-color: var(--sq-gold);
}
/* Die Tafel im Spiel ist 360 px breit; mit dem 140-px-Regler aus game-v3.css
   bleibt fuer „Soundeffekte" zu wenig und die Beschriftung wurde gekuerzt.
   Der Regler gibt hier Platz ab — die Beschriftung ist die Bedeutung, der
   Regler nur ihr Stellweg. */
body.sq-sprache #modal-options .menu-slider {
    /* Gemessen: „🔊 Soundeffekte" braucht 134 px, bei 104 px Regler standen
       122 zur Verfuegung — 12 px zu wenig, die Beschriftung wurde gekuerzt. */
    width: 88px;
    flex: 0 0 88px;
}
/* ⚠ Hier stand eine engere Sperrschrift nur fuer diese Tafel. Zusicherung 9
   hat sie verworfen, und zu Recht: zwei Oberflaechen, die verschieden gesetzt
   sind, sind zwei verschiedene Optionen. Der schmalere Regler allein schafft
   den Platz. */
/* Die AN/AUS-Knoepfe: Gold, wenn an — die Rolle „Zustand", nicht „Aktion". */
body.sq-sprache #menu-settings .setting-row button,
body.sq-sprache #modal-options .setting-row button {
    background: rgba(var(--sq-goldRGB), 0.1);
    border: 1px solid rgba(var(--sq-goldRGB), 0.45);
    border-radius: 0;
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    letter-spacing: 0.12em;
    color: var(--sq-gold);
    transition: background 0.15s ease, color 0.15s ease;
}
body.sq-sprache #menu-settings .setting-row button:hover,
body.sq-sprache #modal-options .setting-row button:hover {
    background: rgba(var(--sq-cyanRGB), 0.16);
    border-color: var(--sq-cyan);
    color: var(--sq-cyanHell);
}

/* ── Oberflaeche 1: die Einstellungen der Lobby ──────────────────────────── */
body.sq-sprache #screen-lobby #menu-settings {
    position: relative;
    padding: 0 0 6px;
    border: 1px solid rgba(var(--sq-goldRGB), 0.38);
    clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}
body.sq-sprache #screen-lobby #menu-settings::before {
    content: ''; position: absolute; left: 0; top: 11px;
    width: 3px; height: 26px; background: var(--sq-gold);
}
/* Fix OP2 (2026-10-03): die Kennung `SET` oben rechts ist entfernt — sie lag ueber dem
   Musik-ON/OFF-Knopf (Marcel). Nur hier; `NET` und `Q` an den anderen Kaesten bleiben. */
body.sq-sprache #screen-lobby #menu-settings .setting-row {
    padding: 9px 13px;
    margin: 0;
}

/* ── Oberflaeche 2: die Optionen im Spiel ────────────────────────────────── */
body.sq-sprache #modal-options .sq-options-panel {
    position: relative;
    background: linear-gradient(180deg, rgba(8, 13, 24, 0.95), rgba(5, 8, 16, 0.96));
    border: 1px solid rgba(var(--sq-goldRGB), 0.42);
    border-radius: 0;
    clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
}
body.sq-sprache #modal-options .sq-options-panel::before {
    content: ''; position: absolute; left: 0; top: 14px;
    width: 3px; height: 30px; background: var(--sq-gold);
}
body.sq-sprache #modal-options .sq-options-header {
    position: relative;
    font-family: 'Orbitron', sans-serif;
    font-size: 11px;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--sq-cyanHell);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.26);
}
body.sq-sprache #modal-options .sq-options-header::after {
    content: 'SYS';
    /* 🚨 `right: 0` ist die Stelle des Schliessen-Kreuzes (`.sq-options-close`,
       absolut oben rechts). Die Kennung sass darauf. Sie rueckt daneben. */
    position: absolute; right: 26px; bottom: 6px;
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: rgba(var(--sq-goldRGB), 0.62);
}
body.sq-sprache #modal-options .sq-options-section-title {
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: rgba(var(--sq-goldRGB), 0.62);
}

/* ── „Aufgeben" ──────────────────────────────────────────────────────────
   🚨 DER GEFAEHRLICHSTE KNOPF DES SPIELS. Er bekommt die Formsprache — die
   rote Rolle, die angeschnittene Ecke —, aber AUSDRUECKLICH:

     * kein Pulsieren (`animation: none`), auch nicht geerbt. Was pulsiert,
       zieht den Finger an; dieser Knopf soll ihn nicht anziehen.
     * kein Fadenkreuz. Der Zeiger ist ein gewoehnlicher Finger — der
       Kommentar in game-v3.css sagt das schon („ein Fadenkreuz ueber
       ‚Aufgeben' waere falsch"), hier steht es ausdruecklich, weil die
       Zielwahl `cursor` am Brett setzt und Vererbung billig ist.
     * keine Hervorhebung gegenueber den anderen Knoepfen: gleiche Hoehe,
       gleiche Schrift, kein Leuchten. Rot ist hier Warnung, nicht Werbung. */
body.sq-sprache #modal-options .sq-options-surrender-btn {
    background: rgba(224, 32, 32, 0.08);
    border: 1px solid rgba(224, 32, 32, 0.6);
    border-radius: 0;
    clip-path: polygon(0 6px, 6px 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 6px));
    font-family: 'Orbitron', sans-serif;
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #ff8a8a;
    animation: none;
    box-shadow: none;
    text-shadow: none;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
body.sq-sprache #modal-options .sq-options-surrender-btn:hover {
    background: rgba(224, 32, 32, 0.18);
    color: #ffc2c2;
    animation: none;
    box-shadow: none;
}
/* Die Rueckfrage bleibt, wie sie ist — nur in der Schrift der Sprache. */
body.sq-sprache #modal-options .sq-options-confirm-text {
    font-family: 'Share Tech Mono', monospace;
    color: rgba(255, 194, 194, 0.9);
}
body.sq-sprache #modal-options .sq-options-confirm-yes,
body.sq-sprache #modal-options .sq-options-confirm-cancel {
    border-radius: 0;
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    animation: none;
}


/* ══ 18a. DIE KOPFLEISTE IM SPIEL — Fix OJ1 (2026-10-03), Variante B ══════════════════
   Vorlage: mockups/kopfleiste-uebersicht.html, Variante B (Marcel, 03.10.): einzelne
   FUI-Module mit Abstand, Fraktionskante links/rechts, Siegpunkte als Gold-Modul, Tipp als
   Cyan-Schild. Gilt fuer BEIDE Instanzen des Banners (#ov-bar-top Uebersicht, #cb-bar-top
   Kampf), weil beide aus _renderSqTopbarHTML() stammen.

   🚨 NUR Aussehen. Keine Regel hier setzt Breite, Hoehe, flex-basis oder Position einer
   Zone — die Aufteilung aus CW1/DE1/EB1/EG1 (game-v3.css) und das Hoehenbudget des
   46px-Bands bleiben unangetastet. Rahmen und Fraktionskanten sind deshalb INSET-Schatten
   statt `border`: ein Rahmen nimmt Platz, ein Schatten nicht (die Initiativezone braucht
   ihre 44 von 46 px).
   Fraktionsfarben kommen als `--sq-kante` aus den Fraktionsdaten (getFaction().color,
   gesetzt in _renderSqTopbarHTML() bzw. _iniChip()) — hier steht keine Fraktion.
   `?sprache=0` nimmt `body.sq-sprache` weg und damit jede Regel dieses Blocks. */

/* Das Band selbst tritt zurueck — die Module tragen die Flaeche. */
body.sq-sprache .sq-topbar {
    background: transparent;
    border-bottom: 0;
    gap: 4px;
}

/* Fix OR1 (2026-10-03): der durchgehende Hintergrundbalken, Variante 3b
   (mockups/kopfleiste-balken-3-vergleich.html, untere Leiste; Marcel, 03.10.). Ein EIGENES
   Element hinter der Kopfleiste (_renderSqTopbarHTML(), Geschwister von #ov-bar-top /
   #cb-bar-top), weil er eine EIGENE Ebene zwischen den verdeckten Gegnerkarten und den Modulen
   braucht — ein Pseudo-Element der Kopfleiste (z-index 35) laege zwangslaeufig ueber allem.
   ⛔ Fix OS1 (2026-10-03, Marcel: „die Handkarten muessen hinter den Balken oben sein"): die
   Ebenenfolge ist jetzt Spielfeld/Gegnerhand (#ov-enemy-hand, z-index 15) < Balken (16) <
   Module (Kopfleiste, 35). Die Karten scheinen im Balken abgedunkelt durch, darunter normal;
   OR1 hatte den Balken UNTER die Karten gelegt (14). Volle Breite der Buehne, Hoehe = Kopfleiste
   (layout-config.js ov-bar-top/cb-bar-top: margins.h 46), nimmt keinen Platz (absolut,
   pointer-events:none). Module, Groessen und Lagen bleiben, wie sie sind.
   Fraktionsfarben als --sq-balken-l (eigener Spieler) / --sq-balken-r (Gegner) aus den
   Fraktionsdaten (dieselben Farben wie --sq-kante) — hier steht keine Fraktion.
   `?sprache=0`: kein Balken. */
.sq-topbar-balken { display: none; }
body.sq-sprache .sq-topbar-balken {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 46px;
    box-sizing: border-box;
    z-index: 16;
    pointer-events: none;
    background: rgba(2, 4, 10, 0.62);
    border-top: 1px solid rgba(var(--sq-goldRGB), 0.45);
    border-bottom: 1px solid rgba(var(--sq-goldRGB), 0.45);
}
/* Die vier Enden: je 220 px Verlauf auf der Linie, oben und unten — links die Farbe des eigenen
   Spielers, rechts die des Gegners. Kinder-Ebenen, damit sie die Goldlinie ueberdecken (wie die
   .ecke-Spannen der Vorlage, top/bottom -1px, 2px hoch). */
body.sq-sprache .sq-topbar-balken::before,
body.sq-sprache .sq-topbar-balken::after {
    content: '';
    position: absolute;
    top: -1px;
    bottom: -1px;
    width: 220px;
    pointer-events: none;
}
body.sq-sprache .sq-topbar-balken::before {
    left: 0;
    background:
        linear-gradient(90deg, var(--sq-balken-l, rgba(var(--sq-goldRGB), 0.45)), transparent) left top / 100% 2px no-repeat,
        linear-gradient(90deg, var(--sq-balken-l, rgba(var(--sq-goldRGB), 0.45)), transparent) left bottom / 100% 2px no-repeat;
}
body.sq-sprache .sq-topbar-balken::after {
    right: 0;
    background:
        linear-gradient(270deg, var(--sq-balken-r, rgba(var(--sq-goldRGB), 0.45)), transparent) right top / 100% 2px no-repeat,
        linear-gradient(270deg, var(--sq-balken-r, rgba(var(--sq-goldRGB), 0.45)), transparent) right bottom / 100% 2px no-repeat;
}

/* Das gemeinsame Modul. */
body.sq-sprache .sq-topbar-player,
body.sq-sprache .sq-topbar .sq-banner-phase,
body.sq-sprache .sq-topbar .sq-banner-ini,
body.sq-sprache .sq-topbar .sq-topbar-sp {
    position: relative;
    background: rgba(4, 8, 16, 0.90);
    border-left: 0;
    border-right: 0;
    box-shadow: inset 0 0 0 1px rgba(var(--sq-goldRGB), 0.35);
    clip-path: polygon(0 7px, 7px 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px));
}
/* Gefahrenstreifen oben rechts, wie im Mockup — reine Zierde, kein Platz. */
body.sq-sprache .sq-topbar-player::after,
body.sq-sprache .sq-topbar .sq-banner-phase::after,
body.sq-sprache .sq-topbar .sq-banner-ini::after,
body.sq-sprache .sq-topbar .sq-topbar-sp::after {
    content: '';
    position: absolute;
    right: 16px;
    top: 0;
    width: 26px;
    height: 4px;
    background: repeating-linear-gradient(115deg, rgba(var(--sq-goldRGB), 0.75) 0 3px, transparent 3px 7px);
    pointer-events: none;
}

/* Spieler: Fraktionskante aussen — links beim eigenen, rechts beim Gegner. */
body.sq-sprache .sq-topbar-mine {
    box-shadow: inset 3px 0 0 var(--sq-kante, rgba(var(--sq-goldRGB), 0.6)), inset 0 0 0 1px rgba(var(--sq-goldRGB), 0.35);
}
body.sq-sprache .sq-topbar-enemy {
    box-shadow: inset -3px 0 0 var(--sq-kante, rgba(var(--sq-goldRGB), 0.6)), inset 0 0 0 1px rgba(var(--sq-goldRGB), 0.35);
}
body.sq-sprache .sq-topbar-mine  { padding-left: 13px; }
body.sq-sprache .sq-topbar-enemy { padding-right: 13px; }
body.sq-sprache .sq-topbar-enemy::after { right: auto; left: 16px; }
body.sq-sprache .sq-topbar-faction-sub {
    color: rgba(139, 147, 168, 0.85);
    letter-spacing: 1.6px;
}

/* Handkarten-Zaehler als Kachel. */
body.sq-sprache .sq-topbar .sq-hand-chip {
    padding: 2px 7px 2px 4px;
    background: rgba(4, 8, 16, 0.85);
    box-shadow: inset 0 0 0 1px rgba(139, 147, 168, 0.35);
    clip-path: polygon(0 4px, 4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%);
}
body.sq-sprache .sq-topbar-enemy .sq-hand-chip { padding: 2px 4px 2px 7px; }
/* Fix OR1 (2026-10-03): das Karten-Symbol groesser (Marcel: „bekommen wir das Karten-Symbol da
   noch größer hin? bei beiden?"). Das Bild ist quer (320 x 199): im 22 x 22-Feld fuellte es nur
   22 x 13,7 px — oben und unten Luft. Jetzt ist es so HOCH, wie die Kachel innen hergibt
   (--sq-hand-symbol-h = 26 px Kachel − 2 × 2 px Polster = 22 px), die Breite folgt dem Bild:
   sichtbar 22 statt 13,7 px hoch (1,61×). Die Kachel behaelt ihre Hoehe und das Spielerfeld
   seine Masse; der Abstand Symbol–Zahl wird kleiner (4 → 2 px). Dasselbe Bild, dieselbe
   Fraktionsfarbe, Zahl unveraendert 17 px. Uebersicht und Kampfleiste (beide .sq-topbar). */
body.sq-sprache .sq-topbar { --sq-hand-symbol-h: 22px; }
body.sq-sprache .sq-topbar .sq-hand-chip { gap: 2px; }
body.sq-sprache .sq-topbar .sq-hand-chip-icon {
    width: calc(var(--sq-hand-symbol-h) * 320 / 199);
    height: var(--sq-hand-symbol-h);
}
body.sq-sprache .sq-topbar .sq-hand-chip-count {
    font-weight: 400;
    font-size: 17px;
    font-variant-numeric: tabular-nums;
    color: var(--txt, #e6edf3);
}

/* Phase: mittig im Modul, Phase in Cyan, "Dein Zug" bleibt gold (Schreiber setzt die Farbe). */
body.sq-sprache .sq-topbar .sq-banner-phase { justify-content: center; }
body.sq-sprache .sq-topbar .sq-banner-phase-panel { align-items: center; }
body.sq-sprache .sq-topbar .sq-banner-phase-action { text-align: center; color: rgba(139, 147, 168, 0.85); }
body.sq-sprache .sq-topbar .sq-banner-phase-name {
    color: var(--sq-cyanHell);
    letter-spacing: 1.2px;
    text-shadow: 0 0 10px rgba(var(--sq-cyanRGB), 0.45);
}
body.sq-sprache .sq-topbar .sq-banner-phase-turn { letter-spacing: 2.4px; }
/* Einsatz als Cyan-Felder — Anzahl und Fuellung unveraendert aus renderOvPhaseStatus(). */
body.sq-sprache .sq-topbar .sq-phase-panel-deploy-label { color: rgba(139, 147, 168, 0.9); }
body.sq-sprache .sq-topbar .sq-deploy-seg {
    width: 14px;
    height: 5px;
    border-radius: 0;
    background: transparent;
    border: 1px solid rgba(var(--sq-cyanRGB), 0.65);
    transform: skewX(-20deg);
}
body.sq-sprache .sq-topbar .sq-deploy-seg-filled {
    background: var(--sq-cyan);
    border-color: var(--sq-cyan);
    box-shadow: 0 0 4px rgba(var(--sq-cyanRGB), 0.5);
}

/* Siegpunkte: das Gold-Modul (nur in der Uebersicht — in der Kampfansicht traegt dieselbe
   Zone das Phasen-Panel und bleibt ein normales Modul). */
body.sq-sprache .sq-topbar .sq-topbar-sp:not(.sq-topbar-phase-mid) {
    box-shadow: inset 0 0 0 1px rgba(var(--sq-goldRGB), 0.60), inset 0 0 24px rgba(var(--sq-goldRGB), 0.10);
}
body.sq-sprache .sq-topbar .sq-topbar-sp-row { align-items: center; gap: 5px; }
body.sq-sprache .sq-topbar .sq-topbar-sp-val { font-weight: 400; font-variant-numeric: tabular-nums; }
body.sq-sprache .sq-topbar .sq-topbar-sp-colon { color: var(--sq-gold); }
body.sq-sprache .sq-topbar .sq-topbar-sp-label { color: rgba(139, 147, 168, 0.9); letter-spacing: 1.6px; }
/* Die kleine Leiste bis zum Ziel (Felder aus _ovSpLeiste(), Farbe = Fraktionsfarbe am Element). */
body.sq-sprache .sq-topbar .sq-sp-leiste[hidden] {
    display: flex;
    gap: 2px;
    flex: 0 1 auto;
    min-width: 0;
}
body.sq-sprache .sq-topbar .sq-sp-leiste-mine { flex-direction: row-reverse; }
body.sq-sprache .sq-topbar .sq-sp-leiste i {
    display: block;
    width: 4px;
    height: 6px;
    flex: 0 1 4px;
    min-width: 2px;
    background: rgba(139, 147, 168, 0.28);
    transform: skewX(-20deg);
}
body.sq-sprache .sq-topbar .sq-sp-leiste i.v { background: currentColor; }

/* Kampf: Phasen-Panel in der Mitte, Beschriftung der Initiative gold. */
body.sq-sprache .sq-topbar .sq-banner-ini .sq-topbar-sp-label { color: var(--sq-gold); letter-spacing: 2px; }

/* Initiative als laufendes Band (Marcel, 03.10.): das aktive Schiff steht links und ist
   cyan, wer dran war, ist weg, die uebrigen folgen in Server-Reihenfolge. Die Leiste behaelt
   ihre Breite (Zone unveraendert) und schneidet rechts ab — rueckt der Angreifer weiter,
   kommt von rechts der Naechste ins Bild. Ausgeblendet wird nur, solange es einen aktiven
   Eintrag gibt; davor und danach zeigt die Leiste alles wie bisher. */
body.sq-sprache .sq-topbar .sq-topbar-ini-row:has(.sq-ini-chip-aktiv) .sq-ini-chip-gefeuert { display: none; }
body.sq-sprache .sq-topbar .sq-ini-chip {
    border-radius: 0;
    border: 0;
    background: rgba(2, 4, 10, 0.85);
    box-shadow: inset 3px 0 0 var(--sq-kante, rgba(139, 147, 168, 0.6)), inset 0 0 0 1px rgba(139, 147, 168, 0.35);
    clip-path: polygon(0 5px, 5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%);
    padding: 1px 6px 1px 8px;
    color: var(--txt, #e6edf3);
}
body.sq-sprache .sq-topbar .sq-ini-chip-ini { font-variant-numeric: tabular-nums; }
body.sq-sprache .sq-topbar .sq-ini-chip.sq-ini-chip-aktiv,
body.sq-sprache .sq-topbar .sq-ini-chip.ini-bar-active {
    border: 0 !important;
    animation: none;
    color: var(--sq-cyanHell);
    background: rgba(var(--sq-cyanRGB), 0.16);
    box-shadow: inset 3px 0 0 var(--sq-kante, var(--sq-cyan)), inset 0 0 0 1px var(--sq-cyan);
}
/* Nur in dem Anstrich, in dem der Angreifer weitergerueckt ist (game-combat.js setzt
   `sq-ini-ruckt`): der gerade Gefeuerte steht noch einmal da und faltet sich weg, der Rest
   rueckt dadurch nach links, und von rechts kommt der Naechste ins Bild. */
body.sq-sprache .sq-topbar .sq-topbar-ini-row.sq-ini-ruckt .sq-ini-chip-gefeuert:has(+ .sq-ini-chip-aktiv) {
    display: flex;
    overflow: hidden;
    animation: sq-ini-raus 0.45s ease-in forwards;
}
@keyframes sq-ini-raus {
    from { opacity: 0.45; max-width: 78px; }
    to   { opacity: 0; max-width: 0; padding-left: 0; padding-right: 0; margin-right: -4px; }
}

/* Tipp: das Cyan-Schild mit pulsierender Raute. Text, Lage und Breite setzen weiterhin
   updateSelectionHint()/_sqPlaceSelectionHint(); die Raute ist ein Pseudo-Element, damit
   textContent sie nicht loescht. */
body.sq-sprache .sq-hint-bar {
    gap: 7px;
    padding: 5px 12px 5px 10px;
    border: 1px solid rgba(var(--sq-cyanRGB), 0.65);
    background: rgba(4, 8, 16, 0.90);
    clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
    color: var(--sq-cyanHell);
    letter-spacing: 0.6px;
}
body.sq-sprache .sq-hint-bar::before {
    content: '';
    flex: 0 0 6px;
    width: 6px;
    height: 6px;
    background: var(--sq-cyan);
    transform: rotate(45deg);
    animation: sq-tipp-puls 1.4s infinite;
}
@keyframes sq-tipp-puls { 50% { opacity: 0.3; } }

/* Fix OM1 (2026-10-03): der Zug-Timer-Ring (#ov-ps-timer / #cb-ps-timer, befuellt und
   sichtbar geschaltet NUR von game-pvp-timer.js) steht im Phasen-Modul. Der Gefahrenstreifen
   oben (::after, 4 px hoch, rechts 16 px) kann seine obere Kante um ~1 px treffen, wenn das
   Modul voll ist — der Ring liegt deshalb darueber. Keine Groesse, keine Lage: nur die
   Stapelfolge. Farben (cyan -> gold -> rot) zeichnet der Ring selbst (SqRing, ton/warn). */
body.sq-sprache .sq-topbar .sq-ps-timer.sq-banner-ring {
    position: relative;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    body.sq-sprache .sq-hint-bar::before { animation: none; }
    body.sq-sprache .sq-topbar .sq-topbar-ini-row.sq-ini-ruckt .sq-ini-chip-gefeuert:has(+ .sq-ini-chip-aktiv) { display: none; animation: none; }
}

/* ══ 18b. ORTSKACHELN UND FLEETZONES — Fix OK1 (2026-10-03) ══════════════════════════════
   Vorlage: mockups/orte-und-fleetzones.html (freigegeben). Marcel, 03.10.: „wichtig ist,
   dass wir nichts an der Groesse der Elemente aendern."

   🚨 NUR Aussehen. Keine Regel hier aendert Breite, Hoehe, Rand-STAERKE, Polster in der
   Hoehe oder Position einer Kachel, einer Fleetzone, einer Schiffsreihe oder der Ortsleiste:
     · Die Ortsleiste (.sq-locbar) ist so hoch wie ihr Inhalt, die Schiffsreihen teilen sich
       den Rest (CX1). Jede Hoehe in der Leiste bleibt deshalb exakt: das Namensschild nimmt
       sein Polster (2+2 px) aus der Zeilenhoehe (1.2em -> 1.2em - 4px), die SP-Plakette
       liegt als ::before HINTER der Zahl (line-height 1 bleibt), Marken nur Farbe/Schnitt.
     · 🚨 KEIN clip-path an der Kachel: er schnitte die Klickflaeche (location-click,
       Einsetzen, Zielwahl) in den Ecken ab. Die Kachel bleibt ein Rechteck; die
       abgeschnittenen Ecken, die Goldkante und der Gefahrenstreifen sind EIN ::after ueber
       der Kachel mit pointer-events:none — Klicks fallen durch auf die Kachel.
     · Rahmen bleiben 1 px (inline), nur die FARBE wird ueberschrieben; Radius 0.
   Farben aus Daten: --sq-halter (getFaction(controller).color, renderLocations()),
   --sq-fz-farbe (getFaction(...).color, renderFleetzones()). Hier steht keine Fraktion.
   `?sprache=0` nimmt `body.sq-sprache` weg und damit jede Regel dieses Blocks; die
   Kampfmarke ist dann `hidden`. */

/* ── Ortskachel: Rahmen nach Halter ─────────────────────────────────────────── */
body.sq-sprache #ov-locations > .ov-loc {
    --sq-rand: rgba(240, 180, 41, 0.35);           /* neutral: gold */
    --sq-linie: 1px;                                /* Rahmenlinie (ON1: im ::after gezeichnet) */
    --sq-schraeg: 0.75px;                           /* halbe Staerke der Schraege (Diagonale) */
    /* ON1: der eigene 1-px-Rand bleibt (gleiche Masse), wird aber DURCHSICHTIG — sonst stuende
       sein rechteckiges Eck in den abgeschnittenen Ecken. Den Rahmen zeichnet das ::after. */
    border-color: transparent !important;
    border-radius: 0 !important;
    background-color: #050a14;
}
body.sq-sprache #ov-locations > .ov-loc[data-sq-halter] {
    --sq-rand: color-mix(in srgb, var(--sq-halter) 60%, transparent);
}
/* Umkaempft: Cyan-Rand. Ein Inline-box-shadow (Einsatzziel) oder eine Animation
   (sq-board-highlight, Einsatzpuls) gewinnt wie bisher — die beiden Zustaende schliessen
   sich ohnehin aus (Kampfort-Wahl vs. Hauptphase). */
body.sq-sprache #ov-locations > .ov-loc[data-sq-umkaempft] {
    --sq-rand: var(--sq-cyan, #2dd4bf);
    /* ON1: statt des rechteckigen Inset-Schattens (er zeigte die Ecken wieder) eine
       kraeftigere Rahmenlinie — derselbe Rahmen, der die Ecken schraeg fuehrt. */
    --sq-linie: 2px;
    --sq-schraeg: 1.25px;
}
/* Einsatzziel: der Gold-Rahmen, den `hl` inline setzt, muss gegen das !important oben
   bestehen — dieselbe Bedingung (isDeployTarget) als Attribut. Funktion = Hinweis. */
body.sq-sprache #ov-locations > .ov-loc[data-sq-ziel] {
    --sq-rand: #f0b429;
}
body.sq-sprache #ov-locations > .ov-loc .sq-loc-veil {
    background: linear-gradient(180deg, rgba(2, 4, 10, 0.55), rgba(2, 4, 10, 0.35) 30%,
                rgba(2, 4, 10, 0.30) 60%, rgba(2, 4, 10, 0.60));
}

/* FUI-Rahmen: abgeschnittene Ecken (oben links 14, oben rechts 28, unten links 28 —
   wie der clip-path der Vorlage), Goldkante links, Gefahrenstreifen oben rechts.
   🚨 ON1 (Marcel, 03.10.): die Ecken sind NICHT gefuellt — nur eine Linie schraeg ueber die
   Ecke, dahinter bleibt das Ortsbild sichtbar. Der ganze Rahmen steht deshalb hier: vier
   gerade Kanten, die an den Schnitten enden, und drei Schraegen; der Rand der Kachel selbst
   ist durchsichtig (oben). Der Gefahrenstreifen beginnt links der oberen rechten Ecke (er
   lag bisher teils im Schnitt und war dort von der Fuellung verdeckt). */
body.sq-sprache #ov-locations > .ov-loc::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 4;
    pointer-events: none;
    background:
        linear-gradient(135deg, transparent 0 calc(50% - var(--sq-schraeg)), var(--sq-rand) calc(50% - var(--sq-schraeg)) calc(50% + var(--sq-schraeg)), transparent calc(50% + var(--sq-schraeg))) left top / 14px 14px no-repeat,
        linear-gradient(225deg, transparent 0 calc(50% - var(--sq-schraeg)), var(--sq-rand) calc(50% - var(--sq-schraeg)) calc(50% + var(--sq-schraeg)), transparent calc(50% + var(--sq-schraeg))) right top / 28px 28px no-repeat,
        linear-gradient(45deg,  transparent 0 calc(50% - var(--sq-schraeg)), var(--sq-rand) calc(50% - var(--sq-schraeg)) calc(50% + var(--sq-schraeg)), transparent calc(50% + var(--sq-schraeg))) left bottom / 28px 28px no-repeat,
        linear-gradient(var(--sq-rand), var(--sq-rand)) left 14px top 0 / calc(100% - 42px) var(--sq-linie) no-repeat,
        linear-gradient(var(--sq-rand), var(--sq-rand)) right 0 top 28px / var(--sq-linie) calc(100% - 28px) no-repeat,
        linear-gradient(var(--sq-rand), var(--sq-rand)) left 28px bottom 0 / calc(100% - 28px) var(--sq-linie) no-repeat,
        linear-gradient(var(--sq-rand), var(--sq-rand)) left 0 top 14px / var(--sq-linie) calc(100% - 42px) no-repeat,
        repeating-linear-gradient(115deg, rgba(240, 180, 41, 0.9) 0 4px, transparent 4px 9px) right 30px top 0 / 40px 9px no-repeat,
        linear-gradient(#f0b429, #f0b429) left 0 top 20px / 3px 46px no-repeat;
}

/* „⚔ Umkaempft" — pulsierendes Schild oben links, nur an umkaempften Orten (Markup nur
   dort). Liegt ueber der gegnerischen Reihe und faengt keine Klicks. */
body.sq-sprache #ov-locations .sq-loc-kampfmarke[hidden] {
    display: block;
}
body.sq-sprache #ov-locations .sq-loc-kampfmarke {
    position: absolute;
    left: 14px;
    top: 12px;
    z-index: 5;
    pointer-events: none;
    padding: 3px 10px;
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    letter-spacing: 2px;
    line-height: 1.2;
    white-space: nowrap;
    color: #7fe6d6;
    background: rgba(2, 4, 10, 0.85);
    box-shadow: inset 0 0 0 1px var(--sq-cyan, #2dd4bf);
    clip-path: polygon(6px 0, 100% 0, calc(100% - 6px) 100%, 0 100%);
    animation: sq-ok1-puls 1.6s ease-in-out infinite;
}
@keyframes sq-ok1-puls { 50% { opacity: 0.5; } }

/* ── Infoband: dunkles Band zwischen zwei Gold-Haarlinien ────────────────────
   Die Haarlinien SIND die vorhandenen 1-px-Raender oben/unten (border-image statt Farbe —
   gleiche Staerke, gleiche Hoehe). */
body.sq-sprache #ov-locations .sq-locbar {
    background: linear-gradient(180deg, rgba(2, 4, 10, 0.62), rgba(2, 4, 10, 0.90) 18%,
                rgba(2, 4, 10, 0.90) 82%, rgba(2, 4, 10, 0.62));
    border-image: linear-gradient(90deg, transparent 4%, rgba(240, 180, 41, 0.65) 50%, transparent 96%) 1;
}
/* Name auf Gold-Schild: Breite = Text (Ellipsis bleibt), Polster 2+2 px aus der Zeilenhoehe
   genommen — 13 px x 1.2 = 15,6 px vorher, 11,6 + 4 = 15,6 px nachher. Der Rahmen ist ein
   Inset-Schatten (nimmt keinen Platz); die schraegen Kanten schneidet der clip-path wie in
   der Vorlage. */
body.sq-sprache #ov-locations .sq-locbar-name {
    width: fit-content;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
    box-sizing: border-box;
    padding: 2px 18px;
    line-height: calc(1.2em - 4px);
    letter-spacing: 2.4px;
    color: #e6edf3;
    background: rgba(2, 4, 10, 0.95);
    box-shadow: inset 0 0 0 1px rgba(240, 180, 41, 0.55);
    clip-path: polygon(9px 0, 100% 0, calc(100% - 9px) 100%, 0 100%);
}
/* SP-Plakette: dasselbe Gold-Sechseck wie NV1 (.nv1-sp) — HINTER der Zahl, die Zahl behaelt
   line-height 1 und damit die Zeilenhoehe. Seitliches Polster nur fuer die Breite. */
body.sq-sprache #ov-locations .sq-locbar-vp {
    position: relative;
    z-index: 0;
    padding: 0 6px;
    font-family: 'Rajdhani', sans-serif;
    font-weight: 800;
    color: #1a1200;
}
body.sq-sprache #ov-locations .sq-locbar-vp::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 24px;
    height: 22px;
    transform: translate(-50%, -50%);
    z-index: -1;
    background: radial-gradient(circle at 35% 30%, #ffe08a, #f0b429 55%, #8a5d00);
    clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0 50%);
}
body.sq-sprache #ov-locations .sq-locbar-vplbl {
    color: #8b93a8;
    letter-spacing: 2px;
}
/* Art („Hold") — Gold-Marke; tritt wie bisher zurueck, sobald jemand haelt (.sq-hold-on). */
body.sq-sprache #ov-locations .sq-locbar-vprow .sq-hold-badge {
    clip-path: polygon(5px 0, 100% 0, calc(100% - 5px) 100%, 0 100%);
    color: rgba(240, 180, 41, 0.55);
    border-color: rgba(240, 180, 41, 0.30);
}
body.sq-sprache #ov-locations .sq-locbar-vprow .sq-hold-badge.sq-hold-on {
    color: #f0b429;
    border-color: rgba(240, 180, 41, 0.5);
    background: transparent;
}
body.sq-sprache #ov-locations .sq-locbar-vprow .sq-loc-attack-btn {
    clip-path: polygon(5px 0, 100% 0, calc(100% - 5px) 100%, 0 100%);
}
/* Halter-Schild: Farbe/Rand/Grund kommen inline aus den Fraktionsdaten — hier nur Schnitt. */
body.sq-sprache #ov-locations .sq-locbar-owner {
    border-radius: 0;
    padding-left: 12px;
    padding-right: 12px;
    letter-spacing: 2px;
    clip-path: polygon(6px 0, 100% 0, calc(100% - 6px) 100%, 0 100%);
}
/* Effekte als rotes Schild. */
body.sq-sprache #ov-locations .sq-locbar-eff {
    border-radius: 0;
    padding-left: 11px;
    padding-right: 11px;
    color: #ff8a7a;
    border-color: rgba(255, 90, 74, 0.65);
    background: rgba(224, 32, 32, 0.14);
    clip-path: polygon(6px 0, 100% 0, calc(100% - 6px) 100%, 0 100%);
}

/* ── Fleetzones ──────────────────────────────────────────────────────────────
   Dunkle Flaeche, Zielerfassungs-Ecken (oben links, unten rechts) in der Fraktionsfarbe
   der Zone, Leuchtlinie unten — alles EIN ::before mit pointer-events:none (die Zone ist
   Klickziel: Ablegen, Angriff, Kampfort-Wahl). Rand 1 px bleibt; Farbe/Stil im Ruhezustand
   gedaempft, in den Zustaenden (Ziel/angreifbar/umkaempft) bleibt die Inline-Farbe aus
   renderFleetzones() — die traegt die Aussage. */
body.sq-sprache .sq-fleetzone {
    --sq-fz-c: var(--sq-fz-farbe, #8b93a8);
    border-radius: 0;
    border-style: solid !important;
    background: rgba(4, 8, 16, 0.55);
}
body.sq-sprache .sq-fleetzone:not(.sq-fleetzone-ziel):not(.sq-fleetzone-angreifbar):not(.sq-fleetzone-umkaempft) {
    border-color: rgba(139, 147, 168, 0.22) !important;
}
body.sq-sprache .sq-fleetzone::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(color-mix(in srgb, var(--sq-fz-c) 75%, transparent), color-mix(in srgb, var(--sq-fz-c) 75%, transparent)) left top / 22px 2px no-repeat,
        linear-gradient(color-mix(in srgb, var(--sq-fz-c) 75%, transparent), color-mix(in srgb, var(--sq-fz-c) 75%, transparent)) left top / 2px 22px no-repeat,
        linear-gradient(color-mix(in srgb, var(--sq-fz-c) 75%, transparent), color-mix(in srgb, var(--sq-fz-c) 75%, transparent)) right bottom / 22px 2px no-repeat,
        linear-gradient(color-mix(in srgb, var(--sq-fz-c) 75%, transparent), color-mix(in srgb, var(--sq-fz-c) 75%, transparent)) right bottom / 2px 22px no-repeat,
        linear-gradient(90deg, transparent, color-mix(in srgb, var(--sq-fz-c) 50%, transparent), transparent) left bottom / 100% 2px no-repeat;
}
/* Beschriftung als Schild am oberen Rand — liegt absolut (CX1), nimmt keinen Platz. */
body.sq-sprache .sq-fleetzone-label {
    top: 0;
    padding: 2px 10px 2px 12px;
    letter-spacing: 2px;
    color: var(--sq-fz-c);
    background: rgba(2, 4, 10, 0.92);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sq-fz-c) 70%, transparent);
    clip-path: polygon(7px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
}
body.sq-sprache .sq-fleetzone-note { top: 4px; }
/* ON1 (Marcel, 03.10.: „so war es ja vorher, da war kein Strich"): in den Schiffsreihen der
   ORTE ist der Platzhalter unsichtbar. Er entsteht in renderShipsInto() fuer jede leere Reihe
   (unveraendert seit vor OK1: 10 px, grau 50 %, kursiv — also schwach sichtbar); das Element
   bleibt im DOM, nur sein Bild faellt weg. Die Fleetzone zeigt weiter „leer" (unten). */
body.sq-sprache #ov-locations .sq-loc-row > .sq-zone-leer {
    visibility: hidden;
}
/* Leer -> dezent „leer" statt des Gedankenstrichs (Text aus data-leer, DE/EN). Der Strich
   bleibt im DOM (Inline-Stil), nur seine Schrift geht auf 0. */
body.sq-sprache .sq-fleetzone-row > .sq-zone-leer {
    font-size: 0 !important;
}
body.sq-sprache .sq-fleetzone-row > .sq-zone-leer::before {
    content: attr(data-leer);
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    font-style: normal;
    letter-spacing: 3px;
    color: rgba(139, 147, 168, 0.45);
}

@media (prefers-reduced-motion: reduce) {
    body.sq-sprache #ov-locations .sq-loc-kampfmarke { animation: none; }
}

/* ══ 19. DIE ROADMAP ────────────────────────────────────────────────────────
   LO1 (2026-09-23). Links vom Textmenue, nur im Hauptmenue. Gebaut von
   sq-sprache.js (roadmapBauen), Daten in ROADMAP_EINTRAEGE dort, Texte im
   Woerterbuch (SQ_RM_*).

   🚨 AUSSERHALB DER FUEHRUNG. `#sq-roadmap` hat KEINEN Eintrag in
   layout-config.js; die Engine schreibt nichts an sie. Ihre Lage steht deshalb
   hier — und darf hier stehen, weil sie KEIN gefuehrtes Mass aendert (Weg A
   betrifft die Elemente der Engine; dieses gehoert ihr nicht). Kein
   !important, kein min-/max-Wert.

   DIE LAGE, GERECHNET (LO1, B.1 — gemessen mit scripts/lo1-messung.js):
       Die Menuespalte steht seit IM1 bei  links = W/4 - 96   (default)
                                          links = W/4 - 86   (narrow)
       Die Roadmap haelt dieselbe 32-px-Fuge wie die Kaesten rechts und 8 px
       zur Buehnenkante:
           Breite = (W/4 - 96) - 32 - 8 = 25% - 136px    (1280: 184, 1707: 291)
           Breite = (W/4 - 86) - 32 - 8 = 25% - 126px    (narrow 1280: 194)
       `%` bezieht sich auf `#screen-lobby`, und der ist genau buehnenbreit
       (gemessen IM1) — dieselbe Bezugsgroesse wie IM1s `calc(104px - 25%)`.
       Senkrecht steht sie dort, wo die rechte Spalte steht: Oberkante des
       Status-Kastens bis Unterkante des Pre-Enlist-Kastens (default 128..550,
       narrow 142..536). Die Gruppe wird dadurch dreispaltig, ohne dass Menue
       oder Kaesten sich bewegen.

   DIE HOEHE: FORM B — alle sieben, der Bereich rollt. Bei 184 px Breite
   brauchen die sieben Karten in lesbarer Groesse mehr als die 422 px der
   Spalte; die Schrift wird NICHT so weit verkleinert, bis es passt. Der Kopf
   bleibt stehen, die Liste darunter rollt.

   KEINE NEUEN FARBEN: --sq-gold / --sq-cyan / --sq-cyanHell mit ihren
   RGB-Tripeln, der Kastenhintergrund rgba(4, 8, 16, …) und das gedaempfte
   #8b93a8 des Status-Kastens. Keine neuen Masse: Rahmen, Balken und Streifen
   des Kastens sind die von #sq-status (Abschnitt 6), die Karte traegt den
   Gefahrenstreifen der Menueknoepfe (Abschnitt 1) woertlich. */

body.sq-sprache #screen-lobby #sq-roadmap {
    display: none;
    position: absolute;
    left: 8px;
    top: 128px;
    width: calc(25% - 136px);
    height: 422px;
    box-sizing: border-box;
    flex-direction: column;
    background: rgba(4, 8, 16, 0.90);
    border: 1px solid rgba(var(--sq-goldRGB), 0.34);
    clip-path: polygon(0 12px, 12px 0, calc(100% - 26px) 0, 100% 26px,
                       100% 100%, 26px 100%, 0 calc(100% - 26px));
    overflow: hidden;
    z-index: 3;
}
body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-roadmap {
    display: flex;
}
/* Balken links und Gefahrenstreifen oben rechts — wie #sq-status. */
body.sq-sprache #screen-lobby #sq-roadmap::before {
    content: ''; position: absolute; left: -1px; top: 14px;
    width: 3px; height: 34px; background: var(--sq-gold);
}
body.sq-sprache #screen-lobby #sq-roadmap::after {
    content: ''; position: absolute; right: 8px; top: -1px;
    width: 44px; height: 9px;
    background: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.85) 0 4px, transparent 4px 9px);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-kopftext {
    display: flex;
    flex-direction: column;
    gap: 3px;
}
/* Die Laufweite des Kastenkopfs (0.28em) bricht „ROADMAP 2026/2027" bei 184 px
   Breite in zwei Zeilen — hier die halbe, damit die Ueberschrift eine Zeile bleibt. */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-ueberschrift { letter-spacing: 0.14em; }
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-vorbehalt {
    font-size: 9px;
    letter-spacing: 0.2em;
    color: #8b93a8;
}

/* Die Liste: der rollbare Bereich. Die senkrechte Linie und die Kreise haengen
   an den Eintraegen, nicht an der Liste — so rollen sie mit. */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-liste {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    margin: 0;
    padding: 10px 8px 10px 34px;
    list-style: none;
    counter-reset: sq-rm;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--sq-cyanRGB), 0.45) transparent;
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-eintrag {
    position: relative;
    counter-increment: sq-rm;
    margin: 0 0 8px;
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-eintrag:last-child { margin-bottom: 0; }
/* Der nummerierte Kreis — ein CSS-Zaehler, kein Text im Knoten. */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-eintrag::before {
    content: counter(sq-rm);
    position: absolute;
    left: -28px;
    top: 8px;
    width: 18px;
    height: 18px;
    box-sizing: border-box;
    border: 1px solid var(--sq-cyan);
    border-radius: 50%;
    background: rgba(4, 8, 16, 0.90);
    box-shadow: 0 0 7px rgba(var(--sq-cyanRGB), 0.55);
    font-family: 'Orbitron', monospace;
    font-size: 9px;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
    color: var(--sq-cyanHell);
    z-index: 1;
}
/* Die senkrechte Linie: je Eintrag ein Stueck bis zum naechsten Kreis. */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-eintrag::after {
    content: '';
    position: absolute;
    left: -20px;
    top: 17px;
    bottom: -25px;
    width: 1px;
    background: rgba(var(--sq-cyanRGB), 0.45);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-eintrag:last-child::after { display: none; }

/* Die Karte: abgeschraegte Ecke wie der Menueknopf, cyane Kantenglut, und der
   Gefahrenstreifen oben rechts — WOERTLICH die Hintergrundzeichnung des
   Menueknopfs aus Abschnitt 1 (Winkel, Strich, Luecke, Groesse, Lage). */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-karte {
    position: relative;
    box-sizing: border-box;
    padding: 10px 9px 8px 10px;
    border: 1px solid rgba(var(--sq-cyanRGB), 0.45);
    background-color: rgba(4, 8, 16, 0.80);
    background-image: repeating-linear-gradient(115deg,
        rgba(var(--sq-goldRGB), 0.70) 0 3px, transparent 3px 7px);
    background-repeat: no-repeat;
    background-position: right 30px top 0;
    background-size: 34px 8px;
    box-shadow: inset 0 0 14px -5px rgba(var(--sq-cyanRGB), 0.55);
    clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px,
                       100% 100%, 12px 100%, 0 calc(100% - 12px));
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-kopfzeile {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 6px;
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-datum {
    font-family: 'Orbitron', sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: var(--sq-cyan);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-titel {
    margin-top: 3px;
    font-family: 'Orbitron', sans-serif;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--sq-gold);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-zeile {
    margin-top: 2px;
    padding-right: 16px;        /* das Sinnbild steht unten rechts in der Karte */
    font-size: 10.5px;
    line-height: 1.35;
    color: #8b93a8;
}

/* Die Sinnbilder. Pokal und Schloss sind Zeichen aus dem Zeichensatz (der Pokal
   steht so schon im Siegerbildschirm, game-gameover.js), einfarbig in Gold
   gezogen; Steam ist das geklonte SVG des Steam-Knopfs.
   ⚠ KICKSTARTER: eine Wortmarke gibt es im Bestand NICHT. Statt ein Bild
   einzuhaengen steht der Buchstabe K im Zeichensatz der Sprache — benannt im
   Bericht LO1, auszutauschen, sobald ein Zeichen im Bestand liegt. */
/* Das Sinnbild steht UNTEN RECHTS in der Karte, nicht in der Datumszeile: dort
   haette es „END OF DECEMBER" bei 184 px Breite in zwei Zeilen gedrueckt. */
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild {
    position: absolute;
    right: 8px;
    bottom: 7px;
    width: 14px;
    height: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    color: var(--sq-gold);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild svg {
    width: 12px;
    height: 12px;
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild-pokal::before,
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild-schloss::before {
    color: transparent;
    text-shadow: 0 0 0 var(--sq-gold);
}
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild-pokal::before   { content: '\1F3C6'; }
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild-schloss::before { content: '\1F512'; }
body.sq-sprache #screen-lobby #sq-roadmap .sq-rm-bild-kick::before {
    content: 'K';
    font-family: 'Orbitron', sans-serif;
    font-weight: 700;
}

/* narrow (1/1 .. 6/5): Menuespalte 360 breit, Versatz 94px - 25% (IM1) —
   die Roadmap zieht mit, und senkrecht mit den Kaesten (142..536). */
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby #sq-roadmap {
        top: 142px;
        width: calc(25% - 126px);
        height: 394px;
    }
}
/* 1.2 gehoert der Engine nach zu `default` — derselbe Nachsatz wie in Abschnitt 7. */
@media (min-aspect-ratio: 6/5) {
    body.sq-sprache #screen-lobby #sq-roadmap {
        top: 128px;
        width: calc(25% - 136px);
        height: 422px;
        /* LP1: 32 px vor der Menuespalte, deren Lage aus der Kastenkante folgt
           (Abschnitt 7). Bei 1280 ergibt das die bisherigen 8 px. */
        left: calc(var(--sq-spalte-links) - 32px - (25% - 136px));
    }
}
/* Hochformat und alles unter 1/1: kein Platz neben der Spalte, die Kaesten sind
   dort ebenfalls ausgeblendet (Abschnitt 5 und 6). Marcel hat das Hochformat
   geprueft und fuer gut befunden — es bekommt nichts Neues. */
@media (max-aspect-ratio: 1/1) {
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-roadmap { display: none; }
}


/* ══ 20. LR1 (2026-09-23): BEI 16:9 STEHT DER DREISPALTIGE BLOCK MITTIG ═══════
   Marcel: „in 16:9 muesste alles einfach nur etwas weiter nach rechts." Bei
   16:9 lag der Block aus Roadmap, Menuespalte und rechtem Kasten bei 8 px
   links / 224 px rechts (gemessen LQ1).

   🚨 DER BLOCK WIRD VERSCHOBEN, NICHT SEIN INNERES. Alle drei Spalten bekommen
   DENSELBEN Versatz auf ihre bisherige Lage (LP1 bzw. IM1); die Abstaende
   Roadmap -> Menue -> Kasten bleiben, wie sie sind.

   DIE ABLEITUNG (keine feste Zahl — `%` ist die Buehnenbreite W):
       Blocklinks  = Lage der Roadmap nach LP1   (Abschnitt 19)
       Blockrechts = Kastenkante + 400           (Abschnitt 7, LP1)
       Versatz     = (W - Blockrechts - Blocklinks) / 2
   ⇒ linker Rand = rechter Rand. Bei W = 1280: (1280 - 1056 - 8) / 2 = 108,
   Raender 116 / 116.

   🚨 DIE GRENZE: 21:10 (Seitenverhaeltnis 2,1). Darueber gelten unveraendert
   die Regeln von LP1 — 21:9 (2,37, Raender 221/331, „perfekt") wird von
   diesem Block nicht erfasst. Warum nicht genau 16:9 (1,78, wo die Buehne
   aufhoert, bei 1280 zu klemmen): ein Browserfenster auf einem 16:9-Monitor
   ist wegen der Leisten etwa 1920x950 ≈ 2,0 — bei einer Grenze auf 16:9
   saehe genau der Betrachter, fuer den das gebaut ist, nichts. Zwischen 16:9
   und 21:10 waechst die Buehne bis 1512; die Ableitung gilt dort genauso.
   ⚠ An der Grenze selbst springt der Block beim Aendern der Fenstergroesse
   einmal zurueck in die LP1-Lage — der Preis dafuer, dass 21:9 bleibt.

   Nur unter `body.sq-sprache`, nur im Hauptmenue, nur ab 6/5: narrow,
   Hochformat und `?sprache=0` sind nicht erfasst. Weg A: nur `margin-left`
   bzw. `left` — beides nicht gefuehrt —, kein layout-config.js, kein
   !important. */
@media (min-aspect-ratio: 6/5) and (max-aspect-ratio: 21/10) {
    body.sq-sprache #screen-lobby {
        --sq-block-links: calc(var(--sq-spalte-links) - 32px - (25% - 136px));
        --sq-block-rechts: calc(var(--sq-kasten-kante) + 400px);
        --sq-block-versatz: calc((100% - var(--sq-block-rechts) - var(--sq-block-links)) / 2);
    }
    body.sq-sprache #screen-lobby:has(#menu-main.active) #lobby-main {
        margin-left: calc(var(--sq-spalte-links) - (50% - 200px) + var(--sq-block-versatz));
    }
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-status,
    body.sq-sprache #screen-lobby:has(#menu-main.active) #sq-preenlist {
        margin-left: calc(104px - 25% + var(--sq-block-versatz));
    }
    body.sq-sprache #screen-lobby #sq-roadmap {
        left: calc(var(--sq-block-links) + var(--sq-block-versatz));
    }
}
