/* ==========================================================================
 * FRONTEND-MIGRATION W2-P2 (AUTH-NOVA) — der Vor-Flug-Bereich des 3D-Clients:
 * Anmelden (index.html), Neues Konto (register.html) und das Vor-Spawn-Overlay
 * (game3d.html). Umsetzung der von Max am 01.08. gesichteten Varianten
 * R1 (karg) und V2 (Split-Panel) aus preview/auth-preview.html.
 *
 * WARUM EINE EIGENE DATEI UND NICHT space.css:
 * game3d.html traegt ein eigenes, vollstaendiges HUD-CSS mit denselben
 * generischen Namen (.btn, .field, .card, :root --panel/--text/--accent).
 * Ein globales space.css im Cockpit wuerde das Flug-HUD umfaerben. Darum:
 *   - ALLE Regeln haengen unter .nova-auth (nichts wirkt ausserhalb),
 *   - die Token stehen AUF .nova-auth statt auf :root (keine Kollision mit
 *     den --panel/--text/--accent des Flug-HUD),
 *   - alle Klassen tragen den Praefix auth- (keine Kollision mit space.css).
 * Die Farbwerte sind die NOVA-Terminal-Token aus space.css Paragraph 2 -
 * dieselbe Quelle, aus der die Preview zitiert hat. Aendert sich dort eine
 * Farbe, muss sie hier mitziehen (statisches CSS kann nicht importieren).
 *
 * ECKEN-TOTAL: kein einziges border-radius. Kein Blau/Cyan der Alt-Auth-Seite.
 * ========================================================================== */

/* Self-hosted Faces wie in space.css. Die URLs loesen relativ zu DIESER Datei
   auf: /styles/auth.css + ../fonts/ = /fonts/. Doppelte @font-face mit
   identischer Quelle sind unschaedlich - der Browser laedt je Datei einmal. */
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/Orbitron-Medium.woff2') format('woff2');
}
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/Orbitron-Medium.woff2') format('woff2');
}
/* Orbitron 600 - dieselbe Face wie in space.css. Sie steht AUCH hier, weil
   game3d.html nur dieses Stylesheet laedt (ORBITRON A, Max 15.08.). */
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/Orbitron-SemiBold.woff2') format('woff2');
}
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/Orbitron-Bold.woff2') format('woff2');
}
/* IBM Plex Mono (Stilvertrag V2, Zahlen-Rolle). Steht HIER und nicht nur in
   space.css, weil game3d.html genau dieses Stylesheet laedt (und space.css
   nicht) - das Flug-HUD bekommt seine Schrift also von hier.
   SIL OFL 1.1, Lizenztext liegt bei (fonts/OFL-IBMPlexMono.txt). */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/IBMPlexMono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/IBMPlexMono-500.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/IBMPlexMono-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/Inter-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/Inter-Medium.woff2') format('woff2');
}

.nova-auth {
  /* Stilvertrag V2 (09.08.2026): dieselben Rollen wie space.css :root. Die
     Anmeldung laedt space.css NICHT, darum steht die Abschrift hier. */
  --term-bg: #050508;
  --term-panel: #0E0E12;
  --term-panel-alt: #08080B;
  --term-tile-alt: #16161C;
  --term-border: #26262E;
  --term-border-soft: #1F1F26;
  --term-hairline: #18181E;
  --term-text-primary: #F5F5F5;
  --term-text-body: #D6D9DE;
  --term-text-secondary: #9A9FA8;
  --term-text-muted: #6E7480;
  --term-text-disabled: #42464F;
  --term-accent: #7AE7FF;
  --term-danger: #D62828;
  --term-danger-text: #E24444;
  --term-success: #4ADE80;
  --fd: 'Orbitron', 'Arial Narrow', sans-serif;
  --fb: 'Inter', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  /* PREST-LOBBY-1 P2: die dritte Rolle des Stilvertrags V2 (IBM Plex Mono traegt
     ALLE Zahlen). Die @font-face-Bloecke dafuer stehen seit jeher oben in dieser
     Datei - eine Rolle, die auf sie zeigt, gab es hier noch nicht, weil die
     Lobby bis zum Bestenlisten-Streifen keine Zahlen-Zelle hatte. Die Kette endet
     auf monospace: faellt die Datei aus, kippt die Zeile nicht in die Body-Schrift.
     Gegenstueck in space.css: --font-num. */
  --fn: 'IBM Plex Mono', monospace;

  color: var(--term-text-primary);
  font-family: var(--fb);
  -webkit-font-smoothing: antialiased;
}

.nova-auth *,
.nova-auth *::before,
.nova-auth *::after { box-sizing: border-box; }

/* --- Grundflaeche der beiden eigenstaendigen Seiten ---------------------- */
/* Dezentes Sternenfeld auf NOVA-Grund. Rein aus Gradienten gebaut: keine
   Bilddatei, kein Request. */
.auth-void {
  min-height: 100vh;
  margin: 0;
  background-color: var(--term-bg);
  background-image:
    radial-gradient(ellipse at 50% 40%, transparent 42%, rgba(0, 0, 0, 0.55) 100%),
    radial-gradient(1px 1px at 22% 28%, #566178 50%, transparent 50%),
    radial-gradient(1px 1px at 73% 46%, #3a4356 50%, transparent 50%),
    radial-gradient(1px 1px at 48% 74%, #6b768c 50%, transparent 50%),
    radial-gradient(2px 2px at 86% 20%, #445068 50%, transparent 50%),
    radial-gradient(1px 1px at 14% 82%, #4a5568 50%, transparent 50%);
  background-repeat: no-repeat, repeat, repeat, repeat, repeat, repeat;
  background-size: 100% 100%, 380px 380px, 300px 300px, 500px 500px, 340px 340px, 440px 440px;
}

.auth-center {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}

/* --- gemeinsame Bausteine ----------------------------------------------- */
.auth-kicker {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--fd);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--term-text-muted);
  margin: 0 0 14px;
}
/* Der Akzent-Balken der Preview - als Flaeche gezeichnet statt als Sonder-
   zeichen. Ein Glyph waere von der geladenen Schrift abhaengig; die Flaeche
   sieht in jeder Umgebung gleich aus. */
.auth-kicker::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 12px;
  background: var(--term-accent);
  flex: 0 0 auto;
}
.auth-kicker--center { justify-content: center; }

.auth-brand {
  font-family: var(--fd);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-size: 22px;
  color: var(--term-text-primary);
  margin: 0;
}

/* LADESCREEN-L2 P3 — BRANDING-PUNKT (Max-Entscheid 01.08.): die Wortmarke
   heisst ueberall "SPACE" mit akzentfarbenem Punkt dahinter.
   Warum als ::after und nicht im Text: der Markentext kommt aus dem
   Woerterbuch (data-i18n="auth.brand"), und der i18n-Anwender schreibt
   textContent - ein <span> im Markup wuerde er bei jedem Sprachwechsel wieder
   ueberschreiben. Als Pseudo-Element haengt der Punkt dagegen an der KLASSE und
   gilt damit in EINEM Zug fuer Anmelden (index.html), Neues Konto
   (register.html) und den Vor-Flug-Bereich (preflightOverlay.js) - und er
   ueberlebt jeden Sprachwechsel. Der Text selbst bleibt unangetastet.
   Der Ladebildschirm in game3d.html traegt denselben Punkt als eigenes Element
   (.ls-dot) - er kennt auth.css-Klassen nicht. */
.auth-brand::after {
  content: ".";
  color: var(--term-accent);
}

.auth-title {
  font-family: var(--fd);
  font-size: 18px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--term-text-primary);
  margin: 0 0 6px;
}

.auth-lead {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--term-text-secondary);
  margin: 0 0 6px;
}

.auth-field { text-align: left; margin: 14px 0; }
.auth-field > label {
  display: block;
  font-family: var(--fd);
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  font-size: 11px;
  color: var(--term-text-secondary);
  margin-bottom: 5px;
}

.auth-input {
  width: 100%;
  padding: 10px 11px;
  font-family: var(--fb);
  font-size: 14px;
  color: var(--term-text-primary);
  background: var(--term-bg);
  border: 1px solid var(--term-border-soft);
  border-radius: 0;
  outline: none;
  transition: border-color .1s, box-shadow .1s;
}
.auth-input::placeholder { color: var(--term-text-muted); }
.auth-input:focus { border-color: var(--term-accent); box-shadow: 0 0 0 2px rgba(122, 231, 255, 0.22); }
.auth-field.is-bad .auth-input { border-color: var(--term-danger); }

.auth-err {
  display: none;
  font-size: 11.5px;
  color: var(--term-danger-text, #E24444);
  margin-top: 5px;
}
.auth-field.is-bad .auth-err { display: block; }

.auth-hint {
  font-size: 11px;
  line-height: 1.45;
  color: var(--term-text-muted);
  margin-top: 5px;
}

/* FRAKTION-WAHL-1 (Max 16.08.) — DIE DREI FRAKTIONS-KARTEN des Erst-Starts.
   Drei gleich breite Spalten im Panel: die Wahl ist EIN Blick, kein Scrollen
   und keine Liste, in der die dritte Fraktion unter den Rand rutscht. Die
   Fraktionsfarbe kommt je Karte als --auth-faction-accent aus dem Markup (die
   Farbe steht in sim/stationFraktionSkins.js, nicht hier) - sie ist die EINE
   Ausnahme vom Cyan-Akzent des Stilvertrags, denn sie ist das Merkmal, das
   die Karten unterscheidet.
   Ungewaehlt bleiben die Karten ruhig: Rahmen und Marke tragen die Farbe nur
   gedaempft. Erst die Wahl zieht die Kante voll durch - sonst sehen drei
   leuchtende Karten so aus, als waere schon eine ausgewaehlt. */
.auth-factions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.auth-faction {
  --auth-faction-accent: var(--term-accent);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* ❗height/align-self ausdruecklich: ein <button> streckt sich in einem Grid
     NICHT von selbst auf die Zeilenhoehe (Blink-Eigenheit). Ohne diese zwei
     Zeilen steht die Karte mit dem kuerzesten Satz sichtbar niedriger als ihre
     Nachbarn - im Screenshot der ersten Runde war MERIDIAN eine Zeile flacher
     als AEGIS. */
  align-self: stretch;
  height: 100%;
  gap: 4px;
  padding: 12px 8px 11px;
  text-align: center;
  cursor: pointer;
  background: var(--term-bg);
  border: 1px solid var(--term-border-soft);
  border-radius: 0;
  color: var(--term-text-secondary);
  transition: border-color .1s, background .1s, box-shadow .1s;
}
.auth-faction:hover:not(:disabled) { border-color: var(--auth-faction-accent); }
.auth-faction:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(122, 231, 255, 0.35);
}
.auth-faction:disabled { cursor: default; opacity: 0.55; }
.auth-faction.is-on {
  border-color: var(--auth-faction-accent);
  background: color-mix(in srgb, var(--auth-faction-accent) 12%, var(--term-bg));
  box-shadow: inset 0 0 0 1px var(--auth-faction-accent);
}
.auth-faction__mark {
  width: 34px;
  height: 34px;
  opacity: 0.55;
  transition: opacity .1s;
}
.auth-faction.is-on .auth-faction__mark { opacity: 1; }
.auth-faction__name {
  font-family: var(--fd);
  font-weight: 600;
  letter-spacing: 0.12em;
  font-size: 12px;
  text-transform: uppercase;
  color: var(--auth-faction-accent);
}
/* FRAKTION-WAHL-2: die Regel fuer .auth-faction__core ist mit der Zeile
   gegangen (Keine-Alt-Wahrheit) - eine Karte hat Marke, Name, Satz. */
.auth-faction__doc {
  font-size: 11px;
  line-height: 1.35;
  color: var(--term-text-muted);
}
.auth-faction.is-on .auth-faction__doc { color: var(--term-text-secondary); }
/* Der Feld-Fehler faerbt hier die Kanten aller drei Karten, nicht ein Input:
   die unbeantwortete Frage ist die GRUPPE. */
.auth-field.is-bad .auth-faction { border-color: var(--term-danger); }

/* Schmale Fenster: die Buehne ist dort ohnehin ausgeblendet, das Panel wird
   voll breit - drei Spalten bleiben lesbar, nur enger. Unter 380px wird aus
   der Reihe eine Spalte, sonst bricht der Name um. */
@media (max-width: 380px) {
  .auth-factions { grid-template-columns: 1fr; }
  .auth-faction { flex-direction: row; text-align: left; gap: 10px; }
  .auth-faction__mark { width: 28px; height: 28px; }
}

/* Genau drei Knopf-Rollen (SPEC Paragraph 3), harte Ecken, HARTER Farb-
   Fallback auf dem gefuellten Knopf. */
.auth-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 11px 16px;
  margin-top: 12px;
  font-family: var(--fd);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 13px;
  border: 1.5px solid transparent;
  border-radius: 0;
  cursor: pointer;
  background: transparent;
  transition: background .12s, color .12s, border-color .12s;
}
/* Vertrag: der Primaerknopf ist die gefuellte Akzentflaeche mit dunkler
   Schrift. Die dunkle Schrift steht hart da - ein Token-Ausfall darf hier nie
   Weiss auf Cyan erzeugen. Der Hover hellt nur auf, statt die Farbe zu
   wechseln (ein zweiter Farbwert waere ein zweiter Akzent). */
.auth-btn--primary {
  background: var(--term-accent);
  color: #050508;
  border-color: var(--term-accent);
}
.auth-btn--primary:hover { filter: brightness(1.08); }
.auth-btn--secondary { border-color: var(--term-border); color: var(--term-text-secondary); }
.auth-btn--secondary:hover { border-color: var(--term-text-muted); color: var(--term-text-primary); }
.auth-btn:disabled { opacity: .55; cursor: progress; }
.auth-btn:disabled:hover { background: var(--term-accent); border-color: var(--term-accent); }

.auth-btn--link {
  width: auto;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--fb);
  text-transform: none;
  letter-spacing: 0;
  font-size: 12.5px;
  color: var(--term-text-secondary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.auth-btn--link:hover { color: var(--term-accent); }

.auth-altrow {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--term-hairline);
  font-size: 12.5px;
  color: var(--term-text-muted);
}

/* Inline-Feedback (SPEC Paragraph 6): Fehler rot, Erfolg gruen. */
.auth-banner {
  display: none;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin: 4px 0 2px;
  background: var(--term-panel);
  border: 1px solid var(--term-border);
  border-left: 4px solid var(--term-danger);
  font-size: 12.5px;
  text-align: left;
  line-height: 1.45;
}
.auth-banner.is-shown { display: flex; }
.auth-banner--ok { border-left-color: var(--term-success); }
.auth-banner__t {
  font-family: var(--fd);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--term-text-secondary);
  margin-bottom: 2px;
}
.auth-banner--ok .auth-banner__t { color: var(--term-success); }
.auth-banner__m { color: var(--term-text-primary); }

/* --- R1: karge Karte (Anmelden + Neues Konto) --------------------------- */
.auth-card {
  width: 100%;
  max-width: 360px;
  background: var(--term-panel);
  border: 1px solid var(--term-border);
  border-top: 2px solid var(--term-accent);
  border-radius: 0;
  padding: 26px 26px 22px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
  text-align: center;
}
.auth-card .auth-brand { margin-bottom: 18px; }

/* --- V2: Vor-Spawn-Overlay (Panel links, 3D-Buehne rechts) -------------- */
/* Liegt UEBER dem Cockpit und faengt jede Eingabe ab, bis der Nutzer es
   abschliesst - der Spawn-/Socket-Fluss laeuft erst danach an. */
.auth-overlay {
  position: fixed;
  inset: 0;
  z-index: 4000;
  background: var(--term-bg);
  display: grid;
  grid-template-columns: minmax(340px, 440px) 1fr;
}
/* ❗LOBBY-ANZEIGE-1 (Max 17.08.: "Logo SPACE links oben in der Lobby") — DIE
   WORTMARKE VERLAESST DEN PANEL-FLUSS.

   PRAEMISSE, die dabei stehen bleibt: die Wortmarke gab es HIER schon, seit
   AUTH-NOVA P3. Sie stand aber IM Panel, und das Panel zentriert seinen Inhalt
   senkrecht (justify-content:center) - auf einem 900-px-Fenster sass "SPACE."
   damit auf halber Hoehe und las sich als Ueberschrift des Formulars, nicht als
   Marke der Seite. Genau das hat Max als "fehlt" gemeldet.

   ❗KEIN ZWEITES LOGO: dieselbe Klasse (.auth-brand), derselbe Woerterbuch-
   Schluessel (auth.brand), derselbe Akzent-Punkt aus .auth-brand::after. Diese
   Regel gibt ihr nur eine ANDERE POSITION - Anmelden und Neues Konto (dieselbe
   Klasse in index.html/register.html) bleiben unberuehrt, weil der Selektor an
   der Overlay-Klasse haengt.

   left = das Panel-Padding (44px): die Marke steht damit auf derselben Kante
   wie Titel und Knoepfe darunter, statt frei in der Ecke zu schweben.
   pointer-events:none, weil ein Textknoten ueber dem Panel sonst Klicks auf das
   Namensfeld darunter abfangen koennte. */
.auth-overlay__brand {
  position: absolute;
  top: 34px;
  left: 44px;
  z-index: 1;
  margin: 0;
  pointer-events: none;
}
.auth-overlay__panel {
  background: rgba(15, 21, 31, 0.96);
  border-right: 1px solid var(--term-border);
  box-shadow: 0 0 60px rgba(0, 0, 0, 0.7);
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* ❗LOBBY-ANZEIGE-1 — 'safe center', und das ist kein Feinschliff.
     Ein zentrierter Flex-Container schneidet einen UEBERLAUF NACH OBEN ab: der
     Inhalt wandert ueber die obere Kante hinaus und ist von dort auch nicht
     scrollbar (der Scroll-Bereich beginnt bei 0). Auf einem niedrigen Fenster
     rutschte der Erst-Start-Block damit genau unter die Wortmarke, die jetzt
     absolut darueber liegt - im Bild 820x620 war "ERST-START" von "SPACE."
     ueberdeckt. 'safe' kippt die Ausrichtung in dem Moment auf flex-start; das
     Polster oben ist dann die Luft, die die Marke braucht. Der Doppel-Eintrag
     ist Absicht: ein Browser ohne 'safe' behaelt die erste Zeile. */
  justify-content: safe center;
  /* PREST-LOBBY-1 P2: der seitliche Innenrand steht als Rolle da, weil der
     Bestenlisten-Streifen ihn im Hochformat WIEDER AUFHEBEN muss (er laeuft
     randlos ueber die volle Panel-Breite). Ohne die Rolle stuende die 44 ein
     zweites Mal im Stylesheet, und wer sie hier aendert, veraendert dort still
     die Kante. Der Wert selbst ist unveraendert. */
  --auth-panel-pad: 44px;
  padding: 92px var(--auth-panel-pad) 40px;
  overflow-y: auto;
}
.auth-overlay__stage {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 55% 45%, rgba(60, 80, 120, 0.18), transparent 60%),
    radial-gradient(ellipse at 50% 120%, rgba(20, 30, 50, 0.9), transparent 70%),
    linear-gradient(180deg, #08080B 0%, #050508 60%, #030304 100%);
}
/* Die Leinwand der Schiffs-Vorschau fuellt die Buehne; das Modell dreht sich
   langsam (Galerie-Muster).
   LOBBY-SPIN (Max-Auftrag 02.08.): sie nimmt jetzt Zeiger an - Ziehen dreht das
   Schiff in alle Richtungen, nach einer Ruhefrist richtet es sich von selbst
   wieder aus. touch-action:none ist dabei Pflicht: sonst nimmt der Browser die
   Wischgeste als Scrollen/Zoomen und die Vorschau bekommt sie nie zu sehen.
   Nur DIESE Flaeche ist griffig - Beschriftungen, HUD-Zeile und Ladeanzeige
   bleiben durchlaessig, das Panel mit Knoepfen und Feld liegt daneben. */
.auth-overlay__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: grab;
}
.auth-overlay__canvas.is-dragging { cursor: grabbing; }
.auth-overlay__hudline {
  position: absolute;
  top: 14px;
  left: 16px;
  right: 16px;
  display: flex;
  justify-content: flex-end;
  font-family: var(--fd);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(154, 165, 187, 0.4);
  pointer-events: none;
}
.auth-overlay__caption {
  position: absolute;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--fd);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--term-text-muted);
  text-align: center;
  pointer-events: none;
}
/* ❗LOBBY-ANZEIGE-1 (Max 17.08.): die Bildunterschrift nennt jetzt Rumpf UND
   Klassifikation ("Mira" + "Kurier") statt nur den Datenbank-Schluessel.

   ZWEI ELEMENTE STATT EINER ZEICHENKETTE, und das hat zwei Gruende:
   1. Der Trenner ist eine FLAECHE, kein Zeichen. Der Mittelpunkt U+00B7 ist in
      dieser Codebasis verboten (Lehre Q-E2, bewacht von test/authTexts.test.js)
      und ein Bindestrich im Text saehe in beiden Sprachen anders richtig aus.
      Als ::before-Flaeche haengt der Strich an der KLASSE - dieselbe Loesung,
      die .auth-kicker::before schon fuer den Akzentbalken benutzt.
   2. Fehlt die Klassifikation (Rumpf ohne Klasse, Erst-Start ohne Schiff),
      bleibt das zweite Element LEER - und mit :empty verschwindet auch der
      Trenner. Eine Zeichenkette muesste den Trenner selbst wegrechnen.

   Der Rumpfname traegt die Textfarbe, die Klassifikation bleibt gedaempft: der
   Name ist die Identitaet, die Klasse die Einordnung. */
.auth-overlay__caption {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.auth-caption__hull {
  color: var(--term-text-primary);
}
/* Ohne Klassifikation gibt es kein zweites Element - sonst schoebe die
   Luecke (gap) den Rumpfnamen aus der Mitte. */
.auth-caption__class:empty {
  display: none;
}
.auth-caption__class:not(:empty)::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 9px;
  margin-right: 10px;
  vertical-align: -1px;
  background: var(--term-accent);
}
/* LOBBY-LOAD (Max-Entscheid 02.08., E3): die Ladeanzeige der Vorschau. Stil L2
   wie der Boot-Schleier (2-px-Leiste + Prozent), aber KEIN Schleier: ein
   kleines Element in der Buehne, ueber der Bildunterschrift. Die Lobby bleibt
   waehrenddessen vollstaendig bedienbar - deshalb nimmt die Anzeige keine Maus
   an (pointer-events), auch nicht waehrend des Wegblendens. */
.auth-overlay__stage .auth-load {
  position: absolute;
  bottom: 64px;
  left: 50%;
  transform: translateX(-50%);
  width: min(240px, 46%);
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.auth-overlay__stage .auth-load.is-on { opacity: 1; }
.auth-load__track {
  height: 2px;
  width: 100%;
  background: rgba(140, 172, 200, 0.16);
}
.auth-load__fill {
  height: 100%;
  width: 0;
  background: var(--term-accent);
}
.auth-load__pct {
  margin: 8px 0 0;
  font-family: var(--fd);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  color: var(--term-text-muted);
  font-variant-numeric: tabular-nums;
}

/* --- PREST-LOBBY-1 P2: der Bestenlisten-Streifen (V4 TICKER) ------------- */
/* Max, 22.08.2026: "leaderboard v4". Von den fuenf Formen der Sichtung traegt
   die laufende Zeile die Bestenliste - sie macht die BEWEGUNG zur Hauptsache
   und kostet die Buehne nur 26 px am oberen Rand; das Schiff bleibt die
   Hauptsache. Die Zeilen und die Laufdauer setzt scripts/render/lobbyTicker.js,
   die Form steht hier.
   ❗Der Streifen sitzt UEBER der Buehne und nicht neben ihr: die Buehne ist eine
   Gitterspalte, die das Schiff mittig zeigt - eine sechste Zeile im Gitter
   schoebe das Schiff aus der Mitte. */
.auth-ticker {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 2;
  height: 26px;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: rgba(8, 8, 11, 0.92);
  border-bottom: 1px solid var(--term-border);
}
.auth-ticker__marke {
  flex: none;
  align-self: stretch;
  display: flex;
  align-items: center;
  padding: 0 9px;
  font-family: var(--fd);
  font-size: 8.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--term-accent);
  border-right: 1px solid var(--term-border);
}
.auth-ticker__fenster {
  position: relative;
  flex: 1 1 auto;
  overflow: hidden;
}
/* Das Band traegt die Zeilenfolge ZWEIMAL (sim/lobbyTicker.BAND_RUNDEN) und
   wandert um genau die Haelfte seiner Breite nach links: in dem Moment steht die
   zweite Folge dort, wo die erste begann, und der Sprung zurueck ist unsichtbar.
   Die Dauer kommt als --auth-ticker-dauer vom Knoten (sie haengt an der Anzahl
   der Zeilen, damit jede Zeile gleich lange braucht); der Rueckfallwert gilt nur,
   wenn sie fehlt.

   ❗width: max-content IST DIE BEWEGUNG, nicht Kosmetik. Ein Flex-Container ist
   ein BLOCK: ohne diese Zeile ist seine Randbox so breit wie das Fenster, die
   Posten laufen nur sichtbar darueber hinaus. translateX(-50%) misst aber die
   RANDBOX - im Bild gemessen: Randbox 395,0 px gegen 3743,0 px Inhalt, also
   197,5 px Wanderung statt 1878,3 px (eine Folge). Der Streifen zeigte damit
   dauerhaft dieselben drei Namen und ruckte alle 34 s um zwei Fingerbreit
   zurueck; elf von dreizehn Zeilen kamen nie ins Bild.

   ❗DER ANLAUF IST DER ABSTAND. padding-left und gap sind DIESELBE Zahl, und
   das ist eine Rechnung, keine Symmetrie: die Haelfte der Randbox ist
   padding/2 + Folge + gap/2, der Weg von Posten 0 zu Posten 13 ist Folge + gap.
   Gleich sind beide genau dann, wenn padding == gap. Standen dort 12 gegen 26,
   sprang das Band bei jeder Runde um 7 px - sichtbar als Ruck mitten im Lauf.
   Darum EINE Rolle fuer beide Werte statt zweier Zahlen, die auseinanderlaufen
   koennen. */
.auth-ticker__band {
  --auth-ticker-gap: 26px;
  display: flex;
  width: max-content;
  gap: var(--auth-ticker-gap);
  padding-left: var(--auth-ticker-gap);
  white-space: nowrap;
  will-change: transform;
  animation: auth-ticker-lauf var(--auth-ticker-dauer, 34s) linear infinite;
}
@keyframes auth-ticker-lauf {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
/* Wer Bewegung abgestellt hat, bekommt die Liste im Stand zu lesen statt gar
   nichts: das Band bleibt sichtbar, es laeuft nur nicht. */
@media (prefers-reduced-motion: reduce) {
  .auth-ticker__band { animation: none; }
}
.auth-ticker__post {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  color: var(--term-text-secondary);
}
.auth-ticker__post svg { display: block; }
.auth-ticker__abz { display: flex; align-items: center; }
.auth-ticker__platz {
  font-family: var(--fn);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  color: var(--term-text-disabled);
}
.auth-ticker__name { color: var(--term-text-body); }
.auth-ticker__wert {
  font-family: var(--fn);
  font-variant-numeric: tabular-nums;
  color: var(--term-text-muted);
}
/* Die eigene Zeile ist das EINZIGE, was der Streifen hervorhebt - wer
   vorbeilaeuft, soll sich wiederfinden, ohne die Liste zu lesen. Akzent, kein
   Gold: Gold gehoert dem Rang und kommt aus dem Abzeichen daneben. */
.auth-ticker__post.is-self .auth-ticker__name { color: var(--term-accent); }

@media (max-width: 760px) {
  .auth-overlay { grid-template-columns: 1fr; }
  .auth-overlay__stage { display: none; }
}

/* ❗DER ZWEITE SITZ. Unter 760 px gibt es keine Buehne (Regel darueber) - dann
   haengt lobbyTicker.js den Streifen ins Panel und setzt diese Klasse. Er steht
   dort im Fluss unter den Knoepfen und laeuft randlos ueber die volle
   Panel-Breite; den seitlichen Innenrand hebt er ueber --auth-panel-pad wieder
   auf, statt die Zahl ein zweites Mal zu schreiben.
   Die Klasse und nicht der @media-Zweig entscheidet, weil die Sichtung beide
   Formate NEBENEINANDER in EINEM Fenster zeigt - ein @media misst dort das
   falsche Mass. */
.auth-ticker--im-panel {
  position: static;
  margin: 16px calc(var(--auth-panel-pad, 44px) * -1) 0;
  flex: none;
  border-bottom: 0;
  border-top: 1px solid var(--term-border);
}

/* --- Wiederkehrer: Schiffs-Zusammenfassung ------------------------------ */
.auth-ship { text-align: left; margin: 6px 0 2px; }
.auth-ship__name {
  font-family: var(--fd);
  font-size: 16px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--term-text-primary);
}
/* Huellen-Meter NEUTRAL in Akzent (Max-Default 01.08.; SPEC Paragraph 2 haelt
   Gruen fuer Feedback frei, nicht fuer Dauerzustaende). */
.auth-meter {
  height: 4px;
  margin-top: 8px;
  background: var(--term-tile-alt);
  overflow: hidden;
}
.auth-meter > span {
  display: block;
  height: 100%;
  background: var(--term-accent);
}
.auth-stats { display: flex; gap: 8px; margin-top: 12px; }
.auth-stat {
  flex: 1;
  padding: 10px 11px;
  background: var(--term-tile-alt);
  border: 1px solid var(--term-border-soft);
}
.auth-stat__lbl {
  font-family: var(--fd);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--term-text-muted);
}
.auth-stat__val {
  font-family: var(--fd);
  font-size: 17px;
  color: var(--term-accent);
  font-variant-numeric: tabular-nums;
  margin-top: 3px;
}

.auth-hidden { display: none !important; }
