/* Chat Tower Companion -- pages/highscore.css
 * P6-Kette Glied 6/8 (web-241). Reine Verschiebung aus web/public/style.css.
 * Scope: /highscore + Dashboard-Runs-Tab (geteiltes .hs-table, s. eigener
 * Kopfkommentar unten), ui-367 Ehrenhalle, ui-138 DPS-Verlaufs-Graph,
 * ui-396 Highscore mobil als Karten.
 *
 * Kaskaden-Lock: MUSS vor pages/dashboard.css UND pages/shared-mobile.css
 * laden (.hs-table/.hs-expand-link/.hs-profile-ref/a.hs-version werden dort
 * per spaeterer Datei-Position ueberschrieben/ergaenzt, s. web-241-Ticket
 * Cross-File-Sweep). */


/* =====================================================================
   Highscore / Runs (web/highscore-rankings, 2026-05-26)
   ===================================================================== */
/* Public /highscore + Dashboard-Runs-Tab teilen .hs-table — strukturell
   identisch zu .hexa-table aber visuell separat damit Tweaks an einer Seite
   die andere nicht versehentlich mit-bewegen. */
.highscore {
  display: flex;
  flex-direction: column;
  gap: 1.5em;
}

/* ui-058: .ct-rank* — geteiltes Ranking/Table Utility-Set (Companion-Kopie, DL-2)
   Zwei Definitions-Orte: desktop.css (Game) + hier (Companion).
   Rollen, nicht Struktur: Font + tabular-nums + Akzent-Rollen + Podium.
   Keine Größen/Paddings — die bleiben pro Surface.
   .hs-table ist Co-Selektor → kein Markup-Change in highscore.js nötig.
   web-240-Re-Spawn (Review cd1cd70f): NUR die drei Regeln direkt unten
   (.ct-rank/.ct-rank-head/.ct-rank-num) sind ECHTE Co-Selektoren mit
   .hs-table/.hs-participant-table — die restlichen fünf Familienmitglieder
   (.ct-rank-name/-pos/-1/-2/-3) sind bare Regeln OHNE Co-Selektor und
   liegen seither in client/css/companion/components.css (s. dortiger
   Kopfkommentar "Ranking-Akzente"). */
.ct-rank,
.hs-table,
.hs-participant-table { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-variant-numeric: tabular-nums; }
.ct-rank-head,
.hs-table th,
.hs-participant-table th { color: var(--muted); text-transform: uppercase; letter-spacing: .1em; border-bottom: 1px solid var(--line); }
.ct-rank-num,
.hs-table td.num,
.hs-table th.num,
.hs-participant-table td.num,
.hs-participant-table th.num { text-align: right; }

.hs-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.5em;
  font-size: 0.92em;
  /* ui-495: identischer Root-Cause + Fix wie ui-481 (.ip-stbl)/ui-490
     (.hs-participant-table) — Auto-Layout (Default) verteilt Spaltenbreite
     nach Zellen-Min-Content; die AEUSSERE Run-Listen-Tabelle (# / DMG done /
     Wave / Bosse / Tower / Top-Tower / Datum / Version / Detail, 9 Spalten
     Global+KW, 10 Spalten Profil — s. Kommentar unten) wuchs dadurch bei
     ~700px Containerbreite ueber `.hs-scroll` hinaus (Prod-Fund: ui-490-
     Re-Review-should-fix, live gemessen 711 vs. 611px Rang / 688 vs. 611px
     Profil), auch OHNE aufgeklappte Detail-Zeile — die 8-9 "normalen"
     Uebersichts-Spalten allein reichten. ui-495 loeste das damals mit
     table-layout:fixed (harte Klemmung auf width:100%, Inhalt der nicht
     passt musste wrappen/ellipsieren).
     ui-572-UPDATE (2026-09-02, PTR-Fund Fifty): GENAU dieses erzwungene
     Wrappen war der neue Bug — 9-stellige "Dein DMG"-Werte, dreistellige
     Wellen-Zahlen, sogar Spalten-Header wie "Bosse" brachen mitten in der
     Ziffernfolge/im Wort um (schlechter lesbar als ein horizontaler Scroll).
     table-layout:auto (unten) kehrt die Klemmung um: die th-Breiten unten
     bleiben BASIS-Hints (Normalfall bleibt optisch unveraendert — realistische
     Werte passen locker), aber `white-space:nowrap`-Inhalt (s. Kompakt-/
     Zahlen-Spalten-Regeln unten) darf die Spalte/Tabelle ueber ihren Hint
     hinaus wachsen lassen — `.hs-scroll` (Wrapper unten) scrollt dann
     horizontal, nichts bricht mehr mitten in der Zahl um. Die ~700px-
     Ueberlauf-Situation von ui-490/495 ist damit kein Bug mehr, sondern der
     gewollte Fallback (Fifty-Entscheid ui-572: "scrollen statt umbrechen"). */
  table-layout: auto;
}
.hs-table th {
  /* ui-058: color/uppercase/border-bottom kommen aus .ct-rank-head co-selector */
  /* DL-4: Companion-Original-Wert; ueberschreibt .ct-rank-head's .1em zurueck */
  letter-spacing: 0.08em;
  /* ui-344: 0.75em→0.85em, war ~10.35px (0.75em x 0.92em-Tabellenkontext). Höher als der
     hexa-table-Zwilling (0.82em), weil .hs-table bei ≤600px auf 0.88em schrumpft
     (pages/dashboard.css „Runs-Tab: Highscore-Tabelle kompakter") — 0.82em wäre dort wieder unter 11px gefallen
     (0.82 x 0.88 x 15 = 10.824px). 0.85em x 0.88em x 15 = 11.22px (Mobile) / 0.85em x 0.92em
     x 15 = 11.73px (Desktop). */
  font-size: 0.85em;
  font-weight: 500;
  text-align: left;
  padding: 0.4em 0.8em;
}
.hs-table th.hs-th-expand { text-align: center; }
.hs-table td {
  padding: 0.55em 0.8em;
  border-bottom: 1px solid var(--line);
}

/* ui-495: Spaltenbreiten fuer die AEUSSERE Run-Listen-Tabelle `.hs-table`.
   NUR auf th (das automatische Tabellen-Layout uebernimmt die erste Zeile als
   Basis-Hint fuer die GESAMTE Spalte, Muster ui-481/ui-490 — seit ui-572
   `table-layout:auto` statt `fixed`, s. `.hs-table`-Kommentar oben: der th-
   Wert bleibt jetzt ein HINT/Minimum statt einer harten Deckelung) — bewusst
   KEIN width auf td.

   BESONDERHEIT ggue. ui-490 (dort: EINE Spaltenstruktur an zwei Render-
   Stellen): `.hs-table` wird von DREI Render-Funktionen mit VERSCHIEDENER
   Spaltenzahl/-reihenfolge benutzt (highscore.js):
     - renderGlobalTable()  (9 Spalten): # / DMG done / Wave / Bosse / Tower /
       Top-Tower / Datum / Version / Detail — "Rang"-Boards (Aktuelle Version/
       All Time/7 Tage/Letzte 10), th[1] traegt .num. ui-542/ui-543: fuer
       eingeloggte Betrachter wird DIESE Tabelle zur 11-Spalten-Variante
       (`.hs-table--own`, eigener Regelblock direkt unterhalb dieses Blocks,
       ui-542 mit Board 'recent' gestartet, ui-543 auf alle vier Boards
       ausgeweitet) — 9 Spalten bleibt der Default fuer den ausgeloggten
       Zustand.
     - renderKwTable()      (9 Spalten, IDENTISCH ab Spalte 2): th[1] ist
       "# · Preis" (.th-preis statt .num — Podest-Reward-Pille braucht mehr
       Breite als eine nackte Rang-Zahl), Rest 1:1 wie renderGlobalTable().
       ui-543: eingeloggt traegt AUCH diese Tabelle `.hs-table--own` (dieselbe
       Klasse/Regeln wie renderGlobalTable — die eigenen Spalten sitzen bei
       BEIDEN Renderern an identischer Position ab th[2], s. own-Regelblock
       unten) — 9 Spalten bleibt der Default ausgeloggt.
     - renderPersonalTable() (10 Spalten, "Profil" /u/:login): # / Pos. /
       DMG done / Wave / Bosse / Tower / Hexas / Datum / Version / Detail —
       eine ZUSAETZLICHE Pos.-Spalte (globaler Rang) nach #, KEINE Top-Tower-
       Spalte (eigenes Profil zeigt nicht den eigenen Namen), stattdessen
       Hexas (Summe + Breakdown-Subzeile, .col-total-cell — dieselbe Zelle/
       CSS wie im ui-490-Fix, hier aber in der AEUSSEREN statt der inneren
       Tabelle).
   Reine nth-child(n)-Selektoren waeren deshalb AMBIG (nth-child(2) ist
   "DMG done" bei Global/KW, aber "Pos." bei Profil) — stattdessen zwei
   robuste Anker-Strategien, beide OHNE Markup-Aenderung (nutzen NUR
   bestehende Klassen):
     1. `:first-child`/`:last-child`/`:nth-last-child(n)` — Detail/Version/
        Datum/Tower/Bosse/Wave/DMG done sitzen bei ALLEN drei Renderern an
        DERSELBEN Position VON HINTEN gezaehlt (Profil hat nur eine
        Spalte MEHR ganz vorne bei Pos., das verschiebt nichts von hinten).
     2. Bestehende Klassen-Splits wo dieselbe hintere Position semantisch
        divergiert: `.num` (Profils Hexas-th) vs. `:not(.num)` (Global/KWs
        Top-Tower-th) bei nth-last-child(4); `.num` vs. `.th-preis` bei
        `:first-child` (erste Spalte).
   "Pos." (nur Profil, kein Gegenstueck bei Global/KW) ist die einzige
   Spalte OHNE robusten Hinten-Anker — sitzt bei Profil auf nth-child(2),
   was bei Global/KW (9 Spalten) DIESELBE Zelle wie "DMG done" waere
   (nth-last-child(8) trifft dort ebenfalls nth-child(2)). Geloest per
   bewusster CASCADE-ORDER: die nth-child(2)-Regel (Pos.) steht im Quelltext
   VOR der nth-last-child(8)-Regel (DMG done) — bei GLEICHER Selektor-
   Spezifitaet (je 1 Klasse+1 Pseudoklasse+1 Typ) gewinnt bei Global/KWs
   tatsaechlicher DMG-done-Zelle (matcht BEIDE Selektoren) die SPAETERE
   Regel (nth-last-child(8)); bei Profils "Pos."-Zelle (matcht NUR
   nth-child(2), nth-last-child(8) ist dort eine andere Zelle) bleibt die
   nth-child(2)-Regel unwidersprochen wirksam. Regressions-Anker im Test:
   Reihenfolge-Vertauschung macht (b-Pos-Cascade) rot.
   ui-510-Fix: ALLE Selektoren in diesem Block sind jetzt `.hs-table > thead
   > tr > th...` statt bloss `.hs-table th...` — der bare Nachfahren-
   Kombinator matchte bis hierher NICHT NUR die eigene (direkte) Kopfzeile,
   sondern (da `.hs-participant-table` als Detail-Inhalt TIEF VERSCHACHTELT
   in derselben `.hs-table` sitzt, s. `.hs-participant-table`-Kommentar
   weiter unten fuer die volle DOM-Kette) AUCH deren th, sobald Position UND
   Klassen zufaellig uebereinstimmen. Konkret bewiesen (Live-CDP + CDP
   CSS.getMatchedStylesForNode, Ticket ## Notes): User ist in der 7-spaltigen
   `.hs-participant-table` SOWOHL nth-child(4) ALS AUCH nth-last-child(4)
   OHNE `.num` — genau das Muster von Zeile "Top-Tower" unten (fuer die
   AEUSSERE Tabelle gedacht). Die Top-Tower-Regel `:not(.num)` traegt eine
   Spezifitaet MEHR als `.hs-participant-table th:nth-child(4)` (3 vs. 2
   Klassen/Pseudoklassen) und GEWINNT deshalb GEGEN die eigentlich
   zustaendige ui-490-Regel, unabhaengig von der Datei-Reihenfolge — User
   bekam so effektiv `width:34%` statt der beabsichtigten `12%` (rechnerisch
   bestaetigt: 34/(34+30+28+30)=27,87% der Restbreite, exakt der gemessene
   Wert). FUENF der sechs UEBRIGEN inneren Positionen (Rank/Slot/Waffe/DMG
   done/Credits — nicht Hexas, dafuer existiert in diesem Block keine
   `nth-last-child(1)`-Regel) matchen ebenfalls je eine der Regeln hier,
   blieben aber bisher NUR durch gleiche Spezifitaet + spaetere Datei-Position
   der ui-490-Regeln unfallfrei (fragiles Gluecks-Tie-Break, keine
   strukturelle Garantie — geprueft per Handrechnung gegen alle Live-CDP-
   Messwerte in Ticket ## Notes, inkl. der einzigen Ausnahme Hexas). `.hs-table`s
   `<thead>` ist bei ALLEN DREI Renderern (renderGlobalTable/renderKwTable/
   renderPersonalTable, s. Funktionskopf oben) IMMER `table.hs-table > thead
   > tr > th` — ein fixer, dreistufiger Direkt-Kind-Pfad, den KEINE
   verschachtelte Tabelle je erreichen kann (der `<table>`-Tag selbst
   unterbricht jede Kind-Kombinator-Kette). Der Scope macht den Leak fuer
   ALLE Positionen strukturell unmoeglich, nicht nur fuer den einen
   nachgewiesenen Fall — verhaltensgleich fuer die AEUSSERE Tabelle selbst
   (deren eigene Kopfzeile ist immer exakt dieser Pfad), NEU (und korrekt)
   fuer die INNERE `.hs-participant-table` (bekommt jetzt ausschliesslich
   ihre EIGENEN ui-490-Werte, ungestoert). */
.hs-table > thead > tr > th:first-child.num { width: 36px; white-space: nowrap; }        /* # (Global/Profil): 1-2-stellige Rang-Zahl */
.hs-table > thead > tr > th:first-child.th-preis { width: 92px; white-space: nowrap; }    /* # · Preis (KW): Header-Label + Podest-Pille brauchen mehr Raum als eine nackte Zahl (Pille selbst live gemessen ~55px natural, 92px hat Puffer) */
.hs-table > thead > tr > th:nth-child(2) { width: 62px; white-space: nowrap; }            /* Pos. (NUR Profil) — s. Cascade-Order-Kommentar oben, MUSS vor der DMG-done-Regel stehen */
/* Version + Detail sind FESTE px, keine Flex-(%)-Spalten — Live-CDP-Fund
   (Ticket ## Notes): beide Zellen-Inhalte sind FLEX-CONTAINER mit dem
   Browser-Default `flex-wrap: nowrap` (.tipwrap bei Version — CTTip-System,
   components.css; der "+ aufklappen"-Button bei Detail ist zwar kein Flex-
   Container, aber ein <button> mit unbrechbarem Wort "aufklappen") — BEIDE
   haben dadurch eine HARTE Mindestbreite, die weder durch `overflow-wrap`
   NOCH durch normales Text-Wrapping unterlaufen werden kann (anders als die
   Flex-Spalten unten, die aus BLOCK-Elementen/reinem Text bestehen und bei
   Platzmangel echt umbrechen). Ist die td schmaler als dieser harte Min-
   Content, rendert der Inhalt trotzdem in voller Breite (`overflow:visible`
   Default) und ragt SICHTBAR in die naechste Spalte hinein — das faellt
   NICHT unter den `scrollWidth>clientWidth`-Container-Check (das Gesamt-
   Tabellenende bleibt unveraendert, nur eine INNERE Spaltengrenze wird
   verletzt), deshalb eigens per Kind-Element-`getBoundingClientRect()`
   verifiziert (Ticket ## Notes "Flex-Nowrap-Falle"). Live gemessen (3000px,
   unverengt): .tipwrap (Baseline-Pille "pre-v0.1.0" + Tooltip-Icon, der
   laengste der drei moeglichen Versions-Zustaende) ~94,8px Inhalt, "+
   aufklappen"-Button ~84,1px Inhalt (nur das unbrechbare Wort "aufklappen"). */
.hs-table > thead > tr > th:nth-last-child(2) { width: 124px; white-space: nowrap; }      /* Version: 94,8px Tipwrap-Inhalt + ~22px td-Padding ≈ 117px Untergrenze, 124px laesst ~7px Puffer (weniger grosszuegig als Detail — Version hat KEINEN Wrap-Ausweg mehr, sobald die harte Untergrenze unterschritten wird, deshalb bewusst nicht enger). ui-572: nowrap ergaenzt fuers Header-Label — der Pillen-Inhalt selbst war durch den Flex-nowrap-Container schon vorher hart (s. Kommentar oben), betraf nur potenzielle Label-Umbrueche. */
.hs-table > thead > tr > th.hs-th-expand { width: 112px; }           /* Detail: 84,1px Button-Inhalt + ~22px td-Padding ≈ 106px Untergrenze; 112px laesst ~6px Puffer. Bewusst NICHT auf 128px (der Button bleibt dort komplett einzeilig) — der Button DARF am Leerzeichen umbrechen ("+"/"aufklappen", live verifiziert sauber, kein Ueberlauf), das gesparte Budget braucht die dichte 10-Spalten-Profil-Tabelle dringender fuer DMG done/Hexas/Datum (s.u.) */
/* Die drei verbleibenden Flex-(%)-Spalten muessen NICHT literal auf 100%
   summieren — Chromium skaliert die bei EINER konkreten Tabelle tatsaechlich
   VORHANDENEN %-Spalten proportional auf die Restbreite (CSS2.1 "excess
   space redistributed in proportion to allotted percentages", empirisch
   bestaetigt: Review-Beleg ui-490 + eigene Iteration hier). Da Top-Tower/
   Hexas EXKLUSIV je nach Tabellenform vorkommen (nie beide gleichzeitig in
   einer Tabelle), koennen sie bewusst UNTERSCHIEDLICHE Gewichte tragen
   (Top-Tower hat mit Ellipsis + Bindestrich-Umbruch zwei Auswege, Hexas
   keinen) — die jeweils tatsaechlich aktiven drei Werte pro Tabelle
   skalieren unabhaengig auf 100% der Restbreite. Alle drei sind reine
   BLOCK-/Text-Elemente (kein Flex-nowrap-Container wie Version/Detail oben)
   — `overflow-wrap:anywhere` greift hier tatsaechlich als Sicherung.
   ui-572: DMG done/Datum (Zahlen-/Kompakt-Spalten laut Ticket-AK1) bekommen
   zusaetzlich `white-space:nowrap` — bei realistischen Werten aendert das
   nichts sichtbar (`overflow-wrap:anywhere` blieb wirkungslos, weil der
   Inhalt ohnehin passte, s. Ticket-Notes-Messung), verhindert aber
   strukturell ein kuenftiges Umbrechen bei noch groesseren Zahlen — dann
   greift die table-layout:auto-Wachstumsgarantie oben statt eines
   Zeilenumbruchs. Top-Tower (Namensspalte) bleibt bewusst OHNE nowrap —
   Bindestrich-Umbruch + td-Ellipsis bleiben ihr zweiter/dritter Ausweg
   (unveraendert, kein AK1-Ziel). */
.hs-table > thead > tr > th:nth-last-child(8) { width: 34%; overflow-wrap: anywhere; white-space: nowrap; }   /* DMG done: groesstes/wichtigstes Zahlen-Token (fett hervorgehoben) — Live-Iteration zeigte: ein zu kleines Gewicht (26%) liess es bei der dichten 10-Spalten-Profil-Tabelle auf ~24px schrumpfen (7 Zeilen) — mit den drei Flex-Spalten bewusst ausbalanciert statt einseitig geopfert */
.hs-table > thead > tr > th:nth-last-child(7) { width: 44px; white-space: nowrap; }       /* Wave */
.hs-table > thead > tr > th:nth-last-child(6) { width: 52px; white-space: nowrap; }       /* Bosse */
.hs-table > thead > tr > th:nth-last-child(5) { width: 52px; white-space: nowrap; }       /* Tower */
.hs-table > thead > tr > th:nth-last-child(4):not(.num) { width: 34%; overflow-wrap: anywhere; }  /* Top-Tower (Global/KW) — Name-Spalte, ellipsiert auf td-Ebene (s.u.); Label bricht im Engpass am Bindestrich ("Top-"/"Tower") UND hat mit der td-Ellipsis einen zweiten Ausweg — ui-572: bewusst KEIN nowrap, s. Kommentar oben */
.hs-table > thead > tr > th:nth-last-child(4).num { width: 34%; overflow-wrap: anywhere; white-space: nowrap; }        /* Hexas (NUR Profil) — dieselbe Position wie Top-Tower bei Global/KW, aber EIN Wort ohne Bindestrich/Ellipsis-Ausweg */
.hs-table > thead > tr > th:nth-last-child(3) { width: 32%; overflow-wrap: anywhere; white-space: nowrap; }   /* Datum — EIN Wort ohne jeden Umbruch-Ausweg im Header-Label (die Daten selbst haben Komma/Leerzeichen) */

/* ui-542/ui-543: 11-Spalten-Variante `.hs-table--own` (eingeloggter
   Betrachter — renderGlobalTable() UND renderKwTable(), s. Kommentar oben:
   ui-542 mit Board 'recent' gestartet, ui-543 auf alle vier renderGlobalTable-
   Boards PLUS beide renderKwTable-Boards ausgeweitet). Fuegt "Dein Platz"/
   "Dein DMG" ZWISCHEN Tower und Top-Tower ein (# / DMG done / Wave / Bosse /
   Tower / Dein Platz / Dein DMG / Top-Tower / Datum / Version / Detail).
   Die KW-Variante unterscheidet sich NUR in der ERSTEN Spalte (`.th-preis`
   "# · Preis" statt `.num` "#", separat gescopte Basis-Regel oben, width
   92px statt 36px) — ab th[2] (nth-child-Zaehlung startet bei 2) sind beide
   Tabellen strukturell identisch, die VORWAERTS gezaehlten Regeln unten
   gelten deshalb fuer BEIDE ohne eigenen KW-Zweig.

   Das verschiebt Tower/Bosse/Wave/DMG done um genau zwei Positionen weiter
   VON HINTEN gezaehlt (Tower nth-last-child(5)->(7), Bosse (6)->(8), Wave
   (7)->(9), DMG done (8)->(10)) — die vier RUECKWAERTS-Regeln oben wuerden
   ab hier also die FALSCHEN (verschobenen) Spalten treffen (z.B. traefe die
   Wave-Regel oben, nth-last-child(7)=44px, in der 11-Spalten-Tabelle auf
   Tower). Top-Tower/Datum/Version/Detail bleiben dagegen UNVERAENDERT
   richtig (nth-last-child(4)/(3)/(2) + .hs-th-expand-Klasse zaehlen weiterhin
   korrekt, weil NACH ihnen keine Spalte hinzukam) — fuer die brauchen wir
   keine eigene Regel hier.

   Deshalb: eigene VORWAERTS-Regeln (nth-child(n)) fuer die vier verschobenen
   Bestandsspalten, gescopet auf `.hs-table.hs-table--own` (zwei Klassen +
   nth-child = hoehere Spezifitaet als die bare `.hs-table`-Regeln oben,
   gewinnt unabhaengig von der Datei-Reihenfolge — kein Verlass auf
   Kaskaden-Order noetig, anders als die "fragile Gluecksfall"-Tie-Breaks im
   Basis-Block oben). `.hs-table--own` tritt NIE gleichzeitig mit der
   10-spaltigen Profil-Form auf (exklusiv fuer diese Variante) — deshalb ist
   nth-child(n) hier eindeutig, ohne die .num/:not(.num)-Disambiguierung des
   Basis-Blocks zu brauchen. Die zwei NEUEN Spalten bekommen eigene Klassen
   (.hs-own-rank/.hs-own-dmg) statt Positions-Zaehlung — robust gegen
   kuenftige Markup-Verschiebungen. */
.hs-table.hs-table--own > thead > tr > th:nth-child(2) { width: 26%; overflow-wrap: anywhere; white-space: nowrap; }  /* DMG done (verschoben) */
.hs-table.hs-table--own > thead > tr > th:nth-child(3) { width: 40px; white-space: nowrap; }                          /* Wave (verschoben) — ui-572-PTR-Fund: 3-stellige Wellen ("123") brachen hier um ("12"/"3"), live per Range.getClientRects() verifiziert (Ticket ## Notes) */
.hs-table.hs-table--own > thead > tr > th:nth-child(4) { width: 46px; white-space: nowrap; }                          /* Bosse (verschoben) */
.hs-table.hs-table--own > thead > tr > th:nth-child(5) { width: 46px; white-space: nowrap; }                          /* Tower (verschoben) */
.hs-table.hs-table--own > thead > tr > th.hs-own-rank  { width: 76px; white-space: nowrap; }                          /* Dein Platz (NEU) — "#12"-Format + "DEIN PLATZ"-Headerlabel — ui-572: Header-Label brach vorher um ("Dein"/"Platz"), jetzt nowrap */
.hs-table.hs-table--own > thead > tr > th.hs-own-dmg   { width: 100px; overflow-wrap: anywhere; white-space: nowrap; } /* Dein DMG (NEU) — formatNum(), gleiche Groessenordnung wie DMG done — ui-572-PTR-Fund: 9-stellige Werte brachen hier um ("271.966.89"/"6"), Ticket-Ausgangsbefund */
/* Werteszellen der zwei neuen Spalten in Cyan (Kanon "das bist du" — s.
   .hall .hr-row.me/.mine-tag) — nur der WERT, nicht der Header (Konsistenz
   mit den uebrigen Spalten-Headern). Der Em-Dash-Fallback (own===null) traegt
   .muted direkt am <span> und ueberschreibt die geerbte Cyan-Farbe (direkte
   Zuweisung schlaegt Vererbung, unabhaengig von Spezifitaet). ui-572: nowrap
   ergaenzt (white-space ist NICHT vom th vererbbar, th/td sind Geschwister-
   Zeilen-Kinder, keine Ahnen-Nachfahren-Beziehung — jede Werte-Spalte braucht
   ihre EIGENE td-Regel, s. den ui-572-td-nowrap-Block bei den Werte-Zellen
   unten fuer die uebrigen Kompakt-Spalten). */
.hs-table.hs-table--own > tbody > tr > td.hs-own-rank,
.hs-table.hs-table--own > tbody > tr > td.hs-own-dmg {
  color: var(--cyan);
  font-weight: 600;
  white-space: nowrap;
}

/* Werte-Zellen: Lock "Zahlen nie kuerzen" (ui-481/490-Kanon) — nur die
   Top-Tower-Namensspalte ellipsiert (einzige reine Text-Spalte, AK3). ALLE
   anderen Werte-Zellen (inkl. der Hexas-Zelle bei Profil, .col-total-cell —
   dieselbe .es-total/.es-breakdown-Kette wie ui-490, dort bereits ohne
   eigenes nowrap) bekommen `overflow-wrap:anywhere` als strukturelle zweite
   Sicherung (falls ein einzelnes Zahlen-/Pill-Token ohne Leerstelle breiter
   als seine Spalte ist — bricht im Notfall MITTEN im Token um, keine Ziffer
   geht verloren) statt die Tabelle zu verbreitern oder Container-Overflow
   zu riskieren. Bewusst EINE Regel statt eines separaten `.col-total-cell`-
   Selektors direkt an dieser Stelle: ein eigener Block fuer diese Klasse
   wuerde (Selektor + oeffnende geschweifte Klammer als eine Zeichenkette
   gelesen) den Prefix-`indexOf()`-Anker von ui-490s Testdatei
   (`ruleBody()`, sucht exakt nach Selektor+Klammer) auf DIESE (spaeter im
   File stehende, andere) Regel statt der echten Basis-Regel
   (`text-align:right`, weiter unten) treffen lassen — exakt dieselbe
   Kollisionsklasse, die ui-490s eigener `hsParticipantTableBody()`-Helfer
   bereits umschifft (s. dortiger Kommentar in der Testdatei). Die
   Top-Tower-Zelle bekommt durch das gemeinsame `:not(.hs-th-expand)`
   zusaetzlich `overflow-wrap:anywhere` — wirkungslos redundant neben ihrem
   eigenen `white-space:nowrap` (das unterdrueckt jeden Zeilenumbruch,
   overflow-wrap greift nur wenn Umbrechen ueberhaupt erlaubt ist), aber
   nicht schaedlich.
   ui-510-Fix (Teil 1): `.hs-table > tbody > tr > td` statt `.hs-table td` —
   dieselbe Nesting-Leak-Begruendung wie beim th-Block oben (Kommentar dort).
   ui-510-Fix (Teil 2, `:not(.hs-details-cell)` unten): der `> tbody > tr >
   td`-Scope allein reicht hier NICHT — anders als beim th-Block (dort matcht
   der bare Nachfahren-Selektor die INNERE Tabelle direkt), ist die INNERE
   `.hs-participant-table` fuer JEDE `td`-Regel dieses Blocks selbst KEIN
   direkter Treffer (sie ist kein `td`, sondern lebt INNERHALB eines `td`).
   Stattdessen matcht `.hs-details-cell` (die `<td colspan="9|10">`, die den
   kompletten Detail-Inhalt inkl. der geschachtelten Tabelle traegt) selbst
   `td:not(.hs-th-expand)` — WEIL `overflow-wrap` eine VERERBTE Eigenschaft
   ist, kaskadiert `anywhere` von dort AUCH in JEDE Nachfahren-Ebene, exakt
   bis zu den Kopfzellen der geschachtelten `.hs-participant-table`. Live-CDP
   nach Teil-1-Fix (Ticket ## Notes) zeigte das drastisch: „RANK"/„SLOT" (36/
   38px, KEIN eigenes overflow-wrap, s. th-Block oben — ui-490s expliziter
   Design-Lock "bleiben garantiert einzeilig, bekommen die Regel gar nicht
   erst zugewiesen") brachen live MITTEN IM WORT um ("RAN"/"K"), obwohl
   `getComputedStyle` fuer white-space weiterhin "normal" TROTZ keiner
   direkten Regel zeigte — `CSS.getMatchedStylesForNode` bestaetigte NULL
   direkte Treffer fuer `overflow-wrap` auf dem th selbst, NUR die vererbte
   Kaskade von `.hs-details-cell` erklaerte den COMPUTED-Wert "anywhere".
   Vor diesem Ticket war das UNSICHTBAR (nicht: nicht vorhanden) — derselbe
   Vererbungspfad existierte bereits VOR Teil 1 (ein bare Nachfahren-Selektor
   matcht `.hs-details-cell` genauso), nur ueberdeckte das gleichzeitig VON
   DESKTOP.CSS in denselben th geleakte `white-space:nowrap` (s. dortiger
   ui-510-Fix-Kommentar) jeden Umbruch UNABHAENGIG von overflow-wrap — erst
   das Entfernen DIESES Leaks legte den zweiten, bislang folgenlosen frei.
   `.hs-details-cell` braucht `overflow-wrap:anywhere` fuer ihren EIGENEN
   direkten Inhalt nicht (Run-ID-Meta/Boss-Strip — kurze, unkritische Texte;
   die geschachtelte Tabelle hat fuer IHRE eigenen Werte-Zellen laengst eine
   EIGENE, korrekt gescopte Regel, s. `.hs-participant-table td:not(:nth-
   child(4))` weiter unten) — der Ausschluss kostet nichts, schliesst aber
   die Vererbungs-Bruecke strukturell. */
.hs-table > tbody > tr > td:nth-last-child(4):not(.col-total-cell) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* ui-572-Folgefund (table-layout:auto oben): `overflow:hidden`+`ellipsis`
     brauchen unter Auto-Layout eine EXPLIZITE Breiten-Deckelung, sonst waechst
     die Zelle (wie jede andere nowrap-Zelle) einfach auf ihren Content — bei
     dieser Namensspalte waeren das im Extremfall 40+ Zeichen (Test-Fixture
     "EinWirklichSehrSehrLangerTwitchAnzeigenameUeber40Zeichen", Live-CDP
     nachgewiesen: Tabelle wuchs ohne Deckel ~570px zusaetzlich). `max-width`
     wirkt in Chromium/Firefox AUCH im Auto-Layout als Deckel fuer die
     Spalten-Breiten-Berechnung selbst (nicht nur fuer die Zelle nach
     Layout-Fixierung) — 280px laesst realistische Twitch-Namen (≤25 Zeichen,
     Twitch-Limit) komplett unellipsiert, deckelt nur echte Ausreisser. */
  max-width: 280px;
}
.hs-table > tbody > tr > td:not(.hs-th-expand):not(.hs-details-cell) { overflow-wrap: anywhere; }

/* ui-572 (PTR-Fund Fifty 2026-09-02, Ticket AK1+AK3b): `white-space:nowrap`
   fuer die Werte-Zellen der Zahlen-/Kompakt-Spalten — spiegelt 1:1 die
   th-Regeln oben (gleiche nth-last-child/nth-child-Positionen), weil
   `white-space` NICHT vom th auf die td vererbt wird (th/td sind
   Geschwister-Zeilen-Kinder verschiedener Zeilen, keine Ahnen-Nachfahren-
   Beziehung — jede Spalte braucht ihre eigene th- UND td-Regel). Kombiniert
   mit `table-layout:auto` (oben) darf die Spalte/Tabelle jetzt ueber ihren
   %/px-Hint hinauswachsen statt umzubrechen — `.hs-scroll` (unten) scrollt
   dann horizontal. Top-Tower (Namensspalte, nth-last-child(4):not(.num))
   bleibt bewusst aussen vor — hat bereits eine eigene ellipsis+nowrap-Regel
   direkt oberhalb (Kommentar dort), kein AK1-Ziel.
   Hexas (NUR Profil-Tabelle, `renderPersonalRunRow()`, nth-last-child(4).
   col-total-cell — NICHT `.num`: das TH dieser Spalte traegt zwar `.num`
   [text-align:right, s. Basis-Block oben], die ZUGEHOERIGE td aber
   `.col-total-cell` statt `.num`, ein Live-CDP-Fund dieses Tickets: die
   ERSTE Fassung dieser Regel nutzte `td:nth-last-child(4).num` [gespiegelt
   von der th-Selektion] und traf dadurch NICHTS — computed white-space blieb
   "normal", "★ 7,5" brach weiterhin um]):
   `white-space` ist eine vererbte Eigenschaft — die td-Regel hier kaskadiert
   automatisch in `.es-total`/`.es-breakdown` (keine eigene white-space-Regel
   dort, s. deren Kommentar oben — "★ 7,5" brach vorher zwischen Glyph und
   Zahl um, Ticket-AK3b-Fund). Der `.hs-table > tbody > tr >`-Praefix haelt
   das SKOPT auf die AEUSSERE Tabelle (ui-510-Nesting-Leak-Musters, s.
   Datei-Kopf-Kommentare) — `.hs-participant-table`s EIGENE, geschachtelte
   `.col-total-cell`-Zelle (Detail-Ansicht, Global UND Profil) ist dadurch
   NICHT betroffen und behaelt ihr bewusstes Umbruch-Verhalten aus ui-490
   (390px-Fix, s. dortiger Kommentar bei .es-breakdown weiter unten) —
   diese Zelle sitzt mehrere Ebenen TIEFER als ein direktes tbody>tr>td-Kind
   von `.hs-table` und wird vom Direkt-Kind-Kombinator strukturell nicht
   erreicht. */
.hs-table > tbody > tr > td:first-child,
.hs-table > tbody > tr > td:nth-last-child(8),
.hs-table > tbody > tr > td:nth-last-child(7),
.hs-table > tbody > tr > td:nth-last-child(6),
.hs-table > tbody > tr > td:nth-last-child(5),
.hs-table > tbody > tr > td:nth-last-child(4).col-total-cell,
.hs-table > tbody > tr > td:nth-last-child(3),
.hs-table.hs-table--own > tbody > tr > td:nth-child(2),
.hs-table.hs-table--own > tbody > tr > td:nth-child(3),
.hs-table.hs-table--own > tbody > tr > td:nth-child(4),
.hs-table.hs-table--own > tbody > tr > td:nth-child(5) {
  white-space: nowrap;
}

/* ui-215 DL-1/DL-3/DL-4: Scroll-Wrapper — always-on, aktiviert sich nur bei Overflow.
   Scroll-Schatten (Lea-Verou-Technik): rechter cyan-Fade = „mehr →",
   verschwindet am Tabellenende via background-attachment:local.
   Desktop (Tabelle passt): kein Overflow → kein Schatten, kein Scroll-Indikator.
   ui-396: im Highscore-Scope (.highscore) bei ≤600px neutralisiert — dort
   ersetzen Karten die Tabelle (Block am Datei-Ende); Profil/Tablet behalten
   diesen Wrapper unverändert.
   ui-572: dieser Wrapper ist jetzt der ECHTE horizontale Scroll-Container aus
   Ticket-AK1 ("Tabelle liegt in einem eigenen overflow-x:auto-Container") —
   vor ui-572 konnte `.hs-table` (table-layout:fixed;width:100%) strukturell
   NIE breiter werden als dieser Wrapper (harte Klemmung, s. `.hs-table`-
   Kommentar oben), Overflow blieb rein theoretisch. Mit table-layout:auto +
   den nowrap-Regeln oben WAECHST die Tabelle jetzt tatsaechlich, wenn ein
   Kompakt-/Zahlen-Token mehr Platz braucht als sein Spalten-Hint — genau dann
   greift der Scroll-Schatten UND (neu, AK2) der Scrollbar-Kanon unten zum
   ersten Mal wirklich. Scrollbar-Kanon (ui-464 R2 SSOT, verallgemeinert auf
   die horizontale Achse — Werte identisch zu desktop.css `#panel-scroll`/
   `#popin-mount`, nur width<->height getauscht: thin + `--line-2`-Thumb, 8px,
   transparenter Track): gilt fuer Standalone-Seite UND Popin-Fragment
   gleichermassen (highscore.css laedt in beiden Kontexten, keine
   Popin-Sonderregel noetig). */
.hs-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; /* Firefox */
  /* Schatten-Ebene 1: opaker Bg-Fade am rechten Rand (local = scrollt mit) */
  /* Schatten-Ebene 2: cyan-Glow-Punkt am rechten Rand (fixed = bleibt) */
  background:
    linear-gradient(270deg, var(--bg) 38%, rgba(6, 8, 15, 0)) right / 34px 100% no-repeat local,
    radial-gradient(farthest-side at 100% 50%, rgba(56, 225, 255, 0.30), rgba(56, 225, 255, 0)) right / 13px 100% no-repeat;
}
.hs-scroll::-webkit-scrollbar { height: 8px; }                          /* Chrome/Safari */
.hs-scroll::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 99px; }
.hs-scroll::-webkit-scrollbar-track { background: transparent; }

/* ui-215: Teilnehmer-Tabelle im Detail-Panel benutzt dunkleren Hintergrund (--bg-2) */
.hs-scroll--part {
  background:
    linear-gradient(270deg, var(--bg-2) 38%, rgba(13, 19, 34, 0)) right / 30px 100% no-repeat local,
    radial-gradient(farthest-side at 100% 50%, rgba(56, 225, 255, 0.30), rgba(56, 225, 255, 0)) right / 12px 100% no-repeat;
}

/* ui-215 DL-2: Sticky erste Spalte (#/Rank) — bleibt beim H-Scroll stehen.
   Opaker Hintergrund damit gescrollter Inhalt darunter verschwindet.
   ui-510-Fix: `> thead|tbody > tr >`-Praefix — derselbe Nesting-Leak wie beim
   Spaltenbreiten-Block oben (highscore.css, ui-495-Kommentar dort): OHNE den
   Praefix matcht ein bare Nachfahren-Selektor auf `.hs-table`s erster Spalte
   auch die geschachtelte `.hs-participant-table`s eigene erste Spalte (Rank), die
   direkt darunter ihre EIGENE, korrekt gescopte Sticky-Regel traegt (dunklerer
   `--bg-2`-Hintergrund fuer das Detail-Panel). Bislang folgenlos (gleiche
   Spezifitaet, `.hs-participant-table`s eigene Regel steht SPAETER im File und
   gewinnt den Cascade-Order-Tie-Break — exakt derselbe fragile Glueckfall wie
   bei den th-Breiten), im selben Zug strukturell geschlossen statt als
   Restrisiko stehen gelassen. */
.hs-table > thead > tr > th:first-child,
.hs-table > tbody > tr > td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg);
  box-shadow: 1px 0 0 var(--line);
}
/* Hover: erste Zelle opak halten (kein Transparency-Durchscheinen) */
.hs-row:hover td:first-child {
  background: color-mix(in srgb, var(--bg) 90%, var(--cyan) 10%);
}

/* ui-215: Sticky erste Spalte für Teilnehmer-Tabelle (dunklerer Panel-Hintergrund) */
.hs-participant-table th:first-child,
.hs-participant-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg-2);
  box-shadow: 1px 0 0 var(--line);
}

/* web-196: verschmolzene Hexas-Zelle — Spiegel der Endscreen-Breakdown-Styles (ui-246/ui-260).
   Klassennamen 1:1 aus dem Viewer portiert (DL-5); visuell identisch halten.
   Zwei Ports: desktop.css (Endscreen-Kontext, #hexa-ranking-scoped) + hier (Highscore-SSR). */
/* ui-490: white-space:nowrap sass frueher hier (auf der TD, geerbt von BEIDEN
   Kindern .es-total + .es-breakdown) — die Breakdown-Subzeile (Rank+/DMG+/
   ★/Pakt+, potenziell die laengste Inhaltszeile der ganzen Tabelle) konnte
   dadurch NIE umbrechen und trieb den Spalten-Mindestbedarf hoch (Beitrag
   zum Auto-Layout-Overflow, s. .hs-participant-table-Kommentar oben). JETZT
   traegt WEDER .es-total NOCH .es-breakdown ein eigenes nowrap — Live-CDP-
   Messung (390px, Profil) widerlegte die urspruengliche Annahme "Icon+Zahl
   ist kurz genug, nie erwartet umzubrechen": bei der harten 44px-Spalten-
   verengung am 390px-Profil-Extremfall (Hexas th nur 44px, .es-total-Inhalt
   braucht ~90px+) sprengte das erhaltene nowrap die Zelle NACH AUSSEN
   (kein overflow:hidden auf Werte-Zellen, Lock analog ui-481 "Werte nie
   kuerzen") — `.hs-scroll--part.scrollWidth` wuchs ueber `.clientWidth`
   hinaus (AK1-Verstoss, konkret gemessen 303px > 275px). Default `normal`
   auf BEIDEN Kindern darf bei knappem Platz mehrzeilig umbrechen (Icon
   faellt in eine eigene Zeile) statt die Tabelle zu verbreitern oder Werte
   abzuschneiden — im Normalfall (genug Platz) bleibt beides einzeilig,
   `normal` erzwingt keinen Umbruch. */
.col-total-cell { text-align: right; }
.es-total { color: var(--cur-hexa); font-weight: 700; font-size: 15px; display: block; } /* ui-623: SSOT-Token-Alias, Wert unverändert */
/* Top-Rank: Hexas-Summe in Rang-1-Farbe (ct-rank-1-Konvention) */
tr.ct-rank-1row .es-total { color: var(--rank-1); }
.es-breakdown {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--text-dim);
  letter-spacing: 0.01em;
}
.es-breakdown .bd-k    { color: var(--muted); }
.es-breakdown .bd-boss      { color: var(--yellow); }
.es-breakdown .bd-boss--zero { color: var(--text-dim); }
/* Pakt-Anteil: rot (Pakt-Identitaet), Marker ⚠. Zero = gar nicht gerendert (kein --zero-Selektor). */
.es-breakdown .bd-pact { color: var(--red); }
.es-breakdown .sep     { color: var(--line); }

.hs-row { transition: background 0.12s; }
.hs-row:hover { background: rgba(56, 225, 255, 0.04); }
.hs-row--top td {
  /* Platz 1 leicht hervorgehoben — magenta-Tinge wie Boss-Glow, ohne den
     restlichen Cyan-Akzent zu uebertoenen. */
  color: var(--text);
}
.hs-row--top .hs-rank {
  color: var(--magenta);
  font-weight: 700;
  text-shadow: 0 0 6px rgba(255, 69, 181, 0.4);
}
.hs-row--expanded {
  background: rgba(56, 225, 255, 0.06);
}
.hs-row--expanded td { border-bottom-color: transparent; }

.hs-expand-link {
  display: inline-block;
  padding: 0.15em 0.6em;
  border: 1px solid var(--line-2);
  border-radius: 3px;
  color: var(--muted);
  font-size: 0.85em;
  letter-spacing: 0.03em;
  transition: border-color 0.12s, color 0.12s;
}
.hs-expand-link:hover {
  border-color: var(--cyan);
  color: var(--cyan);
}
/* Aufgeklappte Zeile: Expand-Link ebenfalls cyan */
.hs-row--expanded .hs-expand-link {
  color: var(--cyan);
  border-color: var(--cyan);
}

/* web-099: Highscore Board-Switcher (DL-1..DL-5, gespiegelt von .achievement-weapon-tab)
   ─────────────────────────────────────────────────────────────────────────────── */

/* Bereichs-Umschalter — Bottom-Border-Strip wie Achievement-Sub-Tabs.
   ui-347: die versteckte Scroll-Leiste (overflow-x:auto + scrollbar-width:none) war die
   eigentliche Überlauf-Ursache — Tabs verschwanden ohne jede Affordance. Ersatz: flex-wrap:wrap
   + row-gap, gleiches Muster wie die Haupt-Navi. Targets bleiben ≥44px (WCAG 2.5.5). */
.hs-boardbar {
  display: flex;
  align-items: center;
  gap: 0.5em;
  flex-wrap: wrap;
  row-gap: 0.5em;
  margin: 1.2em 0 1.4em;
  padding-bottom: 0.6em;
  border-bottom: 1px solid var(--line);
}

/* Gruppen-Label vor einer Board-Tab-Gruppe (DL-3). Aktuell nur "Global" — die
   ehemalige "Persönlich"-Gruppe ist seit ui-348 ins Player-Profil umgezogen. */
.hs-group-label {
  font-size: var(--fs-caption); /* ui-505 (M3): 0.7em (~10.5px) -> --fs-caption (K1) */
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  align-self: center;
  margin-right: 0.1em;
  user-select: none;
}

/* Dünner vertikaler Separator zwischen Board-Tab-Gruppen (DL-3). Seit ui-348
   aktuell ohne Konsument (die "Persönlich"-Gruppe, die er vom "Global"-Cluster
   trennte, ist ins Player-Profil umgezogen) — Regel bleibt als Pattern stehen,
   falls eine künftige Board-Gruppierung sie wieder braucht. */
.hs-board-sep {
  width: 1px;
  align-self: stretch;
  background: var(--line-2);
  margin: 0 0.35em;
}

/* ui-348: dezenter Verweis-Link unter dem Board-Umschalter, ersetzt die
   ehemaligen "Persönlich"-Tabs/Panels (Lock 1) — nur wenn eingeloggt. */
.hs-profile-ref {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4em;
  margin: -0.4em 0 1.2em;
  padding: 0.1em 0;
  color: var(--muted);
  font-size: 0.88em;
}
.hs-profile-ref-glyph {
  font-size: 1em;
}
.hs-profile-ref a {
  color: var(--cyan);
  font-weight: 600;
  text-decoration: none;
}
.hs-profile-ref a:hover {
  text-decoration: underline;
}

/* Board-Tab-Pills (1:1 gespiegelt von .achievement-weapon-tab).
   ui-215 DL-5: min-height:44px — Touch-Target ≥44px (WCAG 2.5.5 / Apple HIG).
   flex-shrink:0 — verhindert Quetschen im wrap-Layout (ui-347: Tabs umbrechen statt zu scrollen). */
.hs-board-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.42em 0.95em;
  min-height: 44px;
  flex-shrink: 0;
  white-space: nowrap;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--muted);
  font-size: 0.88em;
  font-weight: 600;
  letter-spacing: 0.03em;
  cursor: pointer;
  border-radius: 2px;
  font-family: inherit;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.hs-board-tab:hover {
  border-color: var(--cyan);
  color: var(--text);
  background: rgba(56, 225, 255, 0.08);
}
/* Aktiver Tab: cyan (Tab-Kanon 2026-06-08, DL-2) */
.hs-board-tab--active {
  border-color: var(--cyan);
  color: var(--cyan);
  background: rgba(56, 225, 255, 0.10);
  text-shadow: 0 0 8px rgba(56, 225, 255, 0.3);
}
.hs-board-tab--active:hover {
  background: rgba(56, 225, 255, 0.14);
}

/* ui-331: Draw-Icon in den Tab-Labels "Diese KW" / "Letzte KW" (ui-333-Asset, Kurzlabel seit ui-347). */
.hs-board-tab .tg { display: inline-flex; }
.hs-board-tab .tg svg { width: 15px; height: 15px; display: block; }

/* ui-331: Kalenderwoche-Board — Reward-Callout ("★ Wochen-Duell" live / "★ Sieger der
   letzten Woche" past) + Preis-Chips + Sieger-Liste + Podest-Reward-Pillen. Farb-Rollen
   (Design-Lock): cyan = Draw-Beträge/Countdown, rank-1/2/3 = Podest-Medaillen, gold = ★
   Wettbewerb-Framing, grün = bezahlt/settled. Guide-Proposal (NICHT im Guide selbst
   gepflegt — Designer-Land, s. .claude/sprint/prototypes/ui-042-proposals/ui-weekly-reward-board.html). */
.kw-reward {
  position: relative;
  overflow: hidden;
  background: linear-gradient(120deg, color-mix(in srgb, var(--gold) 8%, transparent), color-mix(in srgb, var(--cyan) 5%, transparent));
  border: 1px solid color-mix(in srgb, var(--gold) 32%, var(--line));
  border-radius: 8px;
  padding: 0.9em 1em;
  margin-bottom: 2px;
}
/* past (settled, "Letzte Kalenderwoche"): gold→grün statt gold→cyan */
.kw-reward.past {
  background: linear-gradient(120deg, color-mix(in srgb, var(--gold) 6%, transparent), color-mix(in srgb, var(--green) 4%, transparent));
}
.kw-head { display: flex; align-items: center; gap: 0.5em; flex-wrap: wrap; }
.kw-title { font-weight: 800; font-size: 1.05em; }
.kw-title .st { color: var(--gold); }
.kw-hint { font-size: 0.8em; color: var(--text-dim); margin-left: auto; }
.kw-prizes { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 0.7em; }
.kw-prize {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.4em 0.7em;
  border: 1px solid var(--line-2);
  border-radius: 6px;
  background: var(--bg-2);
}
.kw-place { font-weight: 800; font-size: 0.9em; }
.kw-place.p1 { color: var(--rank-1); }
.kw-place.p2 { color: var(--rank-2); }
.kw-place.p3 { color: var(--rank-3); }
/* ui-623: --cur-draw statt Cyan — dies ist die Kalenderwoche-Draws-Auszahlung,
   keine UI-Interaktionsfläche (DL-4). */
.kw-draws { display: inline-flex; align-items: center; gap: 0.32em; color: var(--cur-draw); font-weight: 700; font-size: 0.92em; }
.kw-draws svg { width: 16px; height: 16px; display: block; color: var(--cur-draw); }
.kw-foot {
  display: flex;
  align-items: center;
  gap: 0.5em;
  flex-wrap: wrap;
  margin-top: 0.7em;
  font-size: 0.82em;
  color: var(--muted);
  border-top: 1px dashed var(--line);
  padding-top: 0.65em;
}
.kw-foot b { color: var(--text-dim); }
.kw-paid { color: var(--green); }
/* ui-340: Ledger-Gate — Auszahlung noch nicht belegt (weekly_settlements hat noch keine
   Zeile für die week_id). Gedämpft statt grün, damit die Behauptung nicht zu stark wirkt. */
.kw-pending { color: var(--muted); }
.kw-cd { color: var(--cyan); font-weight: 700; font-variant-numeric: tabular-nums; }

/* Sieger-Liste (Letzte Kalenderwoche) */
.kw-winners { display: flex; flex-direction: column; gap: 6px; margin-top: 0.8em; }
.kw-win { display: flex; align-items: center; gap: 0.6em; font-size: 0.95em; flex-wrap: wrap; }
.kw-win .kw-place { min-width: 1.4em; }
.kw-win b { color: var(--text); }
.kw-wsub { color: var(--muted); font-size: 0.82em; }
.kw-win .kw-draws { margin-left: auto; }

/* Podest-Zeilen (Kalenderwoche + Letzte Kalenderwoche) */
.hs-row.podium td { background: color-mix(in srgb, var(--gold) 5%, transparent); }
.hs-row.podium.p1 td { background: color-mix(in srgb, var(--rank-1) 7%, transparent); }
.kw-rankwrap { display: inline-flex; align-items: center; gap: 0.5em; }
/* ui-623: --cur-draw statt Cyan (Auszahlungs-Pille, Draws-Betrag) — `.paid`
   unten bleibt Grün (Status "ausgezahlt", keine Währungsrolle). */
.kw-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.28em;
  padding: 0.05em 0.45em;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--cur-draw) 45%, transparent);
  color: var(--cur-draw);
  font-size: 0.82em;
  font-weight: 700;
}
.kw-pill svg { width: 13px; height: 13px; display: block; }
.kw-pill.paid { border-color: color-mix(in srgb, var(--green) 45%, transparent); color: var(--green); }
.th-preis { white-space: nowrap; }

/* =====================================================================
   ui-367: Ehrenhalle — Spieler-Rangliste (Top-Spieler je Metrik) als
   /highscore-Board. 2×2-Grid aus vier .hall-Karten, je eine .hr.ct-rank-
   Rangliste (Kanon ui-058: .ct-rank liefert Mono/tabular-nums am Container,
   .ct-rank-head/-pos/-1/2/3 die Akzent-Rollen — Größen/Paddings pro Surface,
   s. Kommentar am .ct-rank-Block oben in dieser Datei). Mobile → 1 Spalte.
   Farb-Rollen (Prototyp ui-367.html): Werte in Metrik-Farbe (magenta Default,
   grün Welle, cyan Sammel-Wert), Podium rank-1/2/3, „du"-Zeile cyan.
   Alle .hr-*-Regeln bewusst unter .hall gescopt: der Endscreen (desktop.css)
   und seine /styleguide-Demo (styleguide.js „Endscreen & Ranking")
   nutzen dieselben .hr-*-Klassennamen mit eigenem display:table-Modell —
   die Companion-CSS lädt auf JEDER Seite, ungescopte Regeln leakten dorthin
   (border-bottom/zentrierte Ränge in der Demo; ui-361-Muster .ac-*→.pf-ach-*).
   ===================================================================== */
.halls {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}
@media (max-width: 720px) {
  .halls { grid-template-columns: 1fr; }
}
/* web-263: Fußnote unter dem 2x2-Grid — Kauf-/Club-Ausschluss-Hinweis. */
.hall-footnote {
  color: var(--muted);
  font-size: 12px;
  margin: 10px 2px 0;
}
.hall {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px 14px 8px;
}
.hall-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 8px;
}
.hall-head .g { display: inline-flex; font-size: 15px; }
.hall-head .g svg { width: 15px; height: 15px; display: block; }
.hall-head .g.mag { color: var(--cur-hexa); } /* ui-623: SSOT-Token-Alias, Wert unverändert (Hexas-Spalte) */
.hall-head .g.grn { color: var(--green); }
.hall-head .g.cy  { color: var(--cyan); }
.hall-head .g.gd  { color: var(--gold); }
.hall-empty {
  color: var(--muted);
  font-size: 12.5px;
  padding: 4px 2px 8px;
}
.hall .hr { display: flex; flex-direction: column; }
.hall .hr-row {
  display: grid;
  grid-template-columns: 2.2em minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  padding: 3px 2px;
  font-size: 13px;
  border-bottom: 1px solid var(--line);
}
.hall .hr-row:last-child { border-bottom: none; }
.hall .hr-row > :last-child { text-align: right; }
/* Header-Zeile: Rollen (muted/uppercase) aus .ct-rank-head (Kanon); Größe +
   letter-spacing pro Surface — 11px = Font-Boden (ui-341/342, Design-Lock). */
.hall .hr-row.ct-rank-head {
  font-size: 11px;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--line-2);
}
/* Rang-Zahl: Farbe aus .ct-rank-pos (gold) bzw. .ct-rank-1/2/3 (Podium-Glow). */
.hall .hr-rank { text-align: center; font-weight: 700; }
/* min-width: 0 via minmax(0,1fr)-Spalte — lange Namen truncaten statt das
   Grid aufzudrücken (Lektion ui-198/ui-203: Clamp braucht einen Block-Träger). */
.hall .hr-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ui-369: geteilte Spielername-Link-Regel — Ehrenhalle (.hr-name a) + companion-
   weite a.name-link (Top-Tower-/Teilnehmer-/KW-Sieger-Namen, highscore.js
   nameLinkHtml()). color:inherit statt var(--text): erbt Kontext-Farbe
   (Podium-Zellen/<strong>/.kw-win b) — im .hall-Kontext identisch, dort ist die
   geerbte Farbe ohnehin --text. Bewusst NUR über die Klasse am <a> gescopet,
   KEINE Regel auf den geteilten .hr-/.ct-rank-Klassen (Guide-Demo-Kollisions-
   Lektion ui-361); die „du"-Zeile (.hr-row.me, unten) bleibt spezifischer → cyan. */
.hall .hr-name a, a.name-link { color: inherit; text-decoration: none; }
.hall .hr-name a:hover, a.name-link:hover { color: var(--cyan); text-decoration: underline; }
.hall .hr-total { font-weight: 600; color: var(--magenta); white-space: nowrap; }
.hall .hr-total.grn { color: var(--green); }
.hall .hr-total.cy  { color: var(--cyan); }
/* „du"-Zeile: cyan abgesetzt, gestrichelte Trennlinie; Rang bewusst OHNE
   Gold-/Podium-Rolle (kein .ct-rank-pos im Markup, s. renderEhrenhalleHall). */
.hall .hr-row.me {
  background: rgba(56, 225, 255, 0.06);
  border-top: 1px dashed var(--line-2);
}
.hall .hr-row.me .hr-rank { color: var(--cyan); }
.hall .hr-row.me .hr-name a { color: var(--cyan); font-weight: 600; }

/* ui-370: Gleichstand-Gruppen — eine Zeile pro Rang, natives <details>
   (Aufklappen OHNE JavaScript, Lock: PJAX/Idiomorph-fest, ui-186/194).
   ALLE Regeln unter .hall gescopt (Lock ui-361/ui-367: die Companion-CSS
   lädt auf jeder Seite, /styleguide demot dieselben .hr-*-Klassen —
   ungescopte Regeln leakten dorthin, zweimal passiert). Prototyp: ui-370.html.
   Trennlinien-Modell: bei Gruppen wandert das border-bottom von der Row auf
   das <details> (Summary bewusst ohne — aufgeklappt keine Binnen-Linie
   zwischen Summary und Mitglieder-Liste, Linie schließt unter der Gruppe). */
.hall details.hr-group { border-bottom: 1px solid var(--line); }
.hall details.hr-group:last-child { border-bottom: none; }
.hall details.hr-group > summary.hr-row {
  border-bottom: none;
  cursor: pointer;
  list-style: none; /* Standard-Marker aus — Chevron kommt als .chev-Span */
}
.hall details.hr-group > summary.hr-row::-webkit-details-marker { display: none; }
.hall details.hr-group > summary.hr-row:hover { background: rgba(56, 225, 255, 0.04); }
.hall details.hr-group[open] > summary.hr-row { background: rgba(56, 225, 255, 0.04); }
.hall .hr-count { color: var(--muted); }
.hall .hr-count b { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }
.hall .chev {
  display: inline-block;
  width: 9px;
  margin-right: 7px;
  color: var(--muted);
  font-size: 10px;
  transition: transform 0.13s ease;
}
.hall details.hr-group[open] .chev { transform: rotate(90deg); color: var(--cyan); }
/* Mitglieder-Chips: padding-left fluchtet mit der Spieler-Spalte des Row-Grids
   (2px Row-Padding + 2.2em Rang-Spalte @13px ≈ 28.6px + 8px gap ≈ 38px). */
.hall .hr-members {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 6px;
  padding: 7px 6px 10px 38px;
}
.hall .hr-members a,
.hall .hr-members .hr-member-plain {
  font-size: 12px;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: 2px 9px;
  background: var(--bg-2);
}
.hall .hr-members a:hover { color: var(--cyan); border-color: var(--cyan); text-decoration: none; }
.hall .hr-members a.me { color: var(--cyan); border-color: var(--cyan); font-weight: 700; }
.hall .hr-more { font-size: 12px; color: var(--muted); align-self: center; padding-left: 2px; }
/* „du dabei"-Markierung der Viewer-Gruppe (schon zugeklappt sichtbar). */
.hall .hr-row.mine { box-shadow: inset 2px 0 0 var(--cyan); }
.hall .mine-tag {
  font-size: 10px;
  color: var(--cyan);
  border: 1px solid var(--cyan);
  border-radius: 999px;
  padding: 0 6px;
  margin-left: 8px;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Board-Container — PE: nur unter [data-hs-js] (DL-9).
   Ohne JS: alle Bereiche gestapelt sichtbar (display:block via user-agent default).
   Mit JS: nur der aktive Bereich sichtbar. */
[data-hs-js] .hs-board {
  display: none;
}
[data-hs-js] .hs-board--active {
  display: block;
}

/* Detail-Zeilen — PE: nur unter [data-hs-js].
   Ohne JS: alle Details offen (benutzbar).
   Mit JS: versteckt, Toggle via .is-open (DL-8). */
[data-hs-js] .hs-details-row {
  display: none;
}
[data-hs-js] .hs-details-row.is-open {
  display: table-row;
}

/* Details-Row mit colspan: keine eigenen Borders, inner-padding nur am
   .hs-details-cell-Container damit's nicht doppelt aussieht. */
.hs-details-row td { border-bottom: 1px solid var(--line); }
.hs-details-cell {
  padding: 0.8em 1.2em 1.2em 1.2em;
  background: rgba(31, 39, 64, 0.35);
}
/* Dezente Run-ID-Zeile am Kopf der aufgeklappten Detail-Zelle (Debug-/Identifikations-Zusatz) */
.hs-details-meta {
  color: var(--muted);
  /* ui-360: 0.78em→0.85em, war ~10.76px (Desktop) / ~10.30px (Mobil ≤600px) — gleiche
     .hs-table-Ambient-Kette wie .hs-table th (oben in dieser Datei, 0.92em Desktop / 0.88em Mobil).
     0.85em x 0.92em x 15 = 11.73px (Desktop) / 0.85em x 0.88em x 15 = 11.22px (Mobil). */
  font-size: 0.85em;
  margin-bottom: 0.6em;
}
.hs-details-meta code {
  color: var(--text-dim);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  /* ui-360: ohne diesen Override zieht die globale `code{font-size:.92em}` (companion/base.css) die
     Run-ID 8% unter die .hs-details-meta-Elternzeile (war ~9.90px Desktop trotz des
     0.85em-Elternwerts); 1em hält den Code-Text auf Elterngröße. */
  font-size: 1em;
}

/* web-094: Admin Top-Earner Expand-Pattern — gespiegelt von .hs-row */
/* Eigene admin-scoped Klassen (.earner-*) — kein Cross-Movement-Risiko
   (ui-058-Konvention: jede Tabelle eigene Klassen, gleiche visuelle Sprache). */
.earner-row { transition: background 0.12s; }
.earner-row:hover { background: rgba(56, 225, 255, 0.04); }
.earner-row--expanded { background: rgba(56, 225, 255, 0.06); }
.earner-row--expanded td { border-bottom-color: transparent; }

.earner-expand-link {
  display: inline-block;
  padding: 0.15em 0.6em;
  border: 1px solid var(--line-2);
  border-radius: 3px;
  color: var(--muted);
  font-size: 0.85em;
  letter-spacing: 0.03em;
  transition: border-color 0.12s, color 0.12s;
}
.earner-expand-link:hover {
  border-color: var(--cyan);
  color: var(--cyan);
}

/* Details-Row mit colspan — analog .hs-details-row/.hs-details-cell */
.earner-details-row td { border-bottom: 1px solid var(--line); }
.earner-details-cell {
  padding: 0.8em 1.2em 1.1em 1.2em;
  background: rgba(31, 39, 64, 0.35);
}

/* Zeilen innerhalb der Detail-Zelle (Pro Waffe / Draws nach Quelle) */
.detail-line {
  display: flex;
  gap: 0.6em;
  padding: 0.25em 0;
  align-items: baseline;
}
.detail-label {
  color: var(--muted);
  /* ui-507 (M4, K1): 0.72em (~10.8px, war eine der 17 Audit-0.72em-Treppen-
     Fundstellen, highscore.css:760) -- Admin-scoped Inhalt trotz Companion-
     Datei-Lage (web-094 Admin-Top-Earner-Expand, exklusiv von admin.js
     konsumiert), von M3/ui-505 explizit dem M4-Scope ueberlassen (s. dessen
     ## Notes "3 NICHT gemappt"). "Pro Waffe"/"Draws nach Quelle" ist echter
     Lese-Text (Zeilen-Label), kein Deko-Kandidat -> var(--fs-caption). */
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  min-width: 9em;
  flex: none;
}
.detail-value { color: var(--text); }

.hs-participant-table {
  /* ui-058: font-family/tabular-nums kommen aus .ct-rank-head co-selector */
  width: 100%;
  border-collapse: collapse;
  /* ui-360: 0.88em→1em, war Teil der 8.50/8.13px-Kette (s. th unten). */
  font-size: 1em;
  /* ui-490: Auto-Layout (Default) verteilt Breite nach Zellen-Min-Content —
     die beiden inhaltsschmalen Spalten Slot (.pn-Badge) und Waffe (18px-SVG-
     Icon, kein Text) bekamen dabei ueberproportional viel Raum zugewiesen
     (derselbe Mechanismus wie ui-481 .ip-stbl), sobald die Summe aller
     Spalten-Mindestbreiten (u.a. die nowrap-Hexas-Subzeile) den Container
     uebersteigt — Ergebnis: Tabelle waechst ueber `.hs-scroll--part` hinaus,
     horizontale Scrollbar (Prod-Fund Fifty, Profil-Popin + Rang-Ansicht).
     table-layout:fixed klemmt die Tabellenbreite HART auf den Container —
     das ist die strukturelle Garantie gegen jeden weiteren Overflow, auch
     bei 390px (nicht nur eine Verbesserung): Spaltenbreiten kommen dann
     ausschliesslich aus den th:nth-child(n)-Regeln unten (erste Zeile der
     Tabelle, CSS2.1 Fixed-Table-Layout-Algorithmus), Inhalt, der nicht
     passt, muss wrappen/ellipsieren statt die Tabelle zu verbreitern. */
  table-layout: fixed;
}
.hs-participant-table th {
  /* ui-058: color/uppercase/border-bottom kommen aus .ct-rank-head co-selector */
  /* DL-4: Companion-Original-Wert; ueberschreibt .ct-rank-head's .1em zurueck */
  letter-spacing: 0.08em;
  /* ui-360: 0.7em→0.85em, war ~8.50px (Desktop) / ~8.13px (Mobil ≤600px) — zusammen mit
     der Tabelle 0.88em→1em oben jetzt 11.73px (Desktop) / 11.22px (Mobil), identisch zum
     bereits gehärteten .hs-table th (ui-344, oben in dieser Datei) auf derselben .hs-table-Ambient-Kette. */
  font-size: 0.85em;
  font-weight: 500;
  text-align: left;
  padding: 0.3em 0.7em;
}
.hs-participant-table td {
  padding: 0.4em 0.7em;
  border-bottom: 1px solid rgba(31, 39, 64, 0.5);
}
/* ui-058: td.num + th.num text-align: right kommt aus .ct-rank-num co-selector */
.hs-participant-table tr:last-child td { border-bottom: none; }
.hs-participant-table .hs-dmg-pct-inline { color: var(--text-dim); }

/* ui-490: Spaltenbreiten — NUR auf th (erste Tabellenzeile) gesetzt, nicht auf
   td: table-layout:fixed uebernimmt die th-Breite fuer die GESAMTE Spalte
   (alle tbody-Zeilen), ein zweiter Satz auf td ist funktional unnoetig UND
   riskant — die ui-396-Mobile-Kartenansicht (weiter unten in dieser Datei,
   ".highscore .hs-board .hs-participant-table tbody tr { display:grid }")
   adressiert dieselben td:nth-child(n) fuer ihre grid-area-Zuordnung; ein
   width auf diesen td waere dort ein Grid-Item-Sizing-Hint und koennte die
   dort bereits funktionierende Kartenansicht verschieben. th ist an dieser
   Stelle unschaedlich, weil dieselbe Regelkette `thead { display:none }`
   setzt (Kopf ist im Karten-Modus unsichtbar).
   Aufteilung: Rank/Slot/Tower sind inhaltsbreit (Zahl/Badge/Icon, kein
   Fliesstext) und bekommen kleine feste px-Werte; User/DMG done/Credits/
   Hexas erhalten den Rest als Prozent (skaliert mit dem Container, NIE >
   100% Gesamtbreite — table-layout:fixed kappt die Tabelle unabhaengig
   davon hart auf ihre eigene width:100%, s. Kommentar oben). Hexas bekommt
   den groessten Anteil (Summe + Rank+/DMG+/★/Pakt+-Subzeile ist die
   laengste Inhaltszeile, s. .es-breakdown unten). User ist die einzige
   TEXT-Spalte und ellipsiert bei langen Namen (AK3) — Zahlen/Werte werden
   NIE gekuerzt (Lock analog ui-481 "nur die Text-/Label-Spalte darf
   schrumpfen, nie ein Wert"); deshalb bewusst KEIN blanket td{overflow:
   hidden} wie ui-481s .ip-stbl td — Clipping wuerde Ziffern abschneiden
   (Lock). KORREKTUR nach Live-CDP-Messung (390px, Profil): ein Value-
   Overflow bleibt NICHT rein optisch auf die eigene Zelle begrenzt, wenn
   die Zelle zusaetzlich `white-space:nowrap` traegt — ohne overflow:hidden
   sprengt ein zu breiter nowrap-Inhalt seine Zellen-Box NACH AUSSEN, und
   das laesst `.hs-scroll--part.scrollWidth` ueber `.clientWidth` wachsen
   (gemessen: 303px > 275px, AK1-Verstoss — Root Cause fuer den Es-Total-
   Fix weiter oben in dieser Datei). Deshalb: KEINE der hier gelisteten
   Werte-Spalten traegt eigenes nowrap (duerfen an Leerzeichen umbrechen,
   AK1 vor AK3), UND als strukturelle zweite Sicherung (falls ein einzelnes
   Zahlen-Token OHNE jede Leerstelle breiter als seine Spalte ist — z.B. ein
   siebenstelliger Credits-Wert bei 390px) `overflow-wrap:anywhere` auf den
   Werte-Spalten (nicht auf User, das hat bereits Ellipsis): bricht MITTEN
   im Token um (haesslich, aber verlustfrei — keine Ziffer fehlt). Bei
   Desktop-/Popin-Breiten (≥ ~900px) inert — dort passt jeder realistische
   Wert einzeilig, Live-CDP-Screenshot zeigt 0 Umbrueche. Bei 390px greift
   es dagegen REGELMAESSIG, auch fuer normale (nicht nur extreme) DMG-/
   Credits-Werte — bewusster Trade-off: 7 dichte Spalten passen bei 390px
   strukturell nicht alle einzeilig, mehrzeiliges Wrapping (AK1, kein
   Overflow) hat Vorrang vor einzeiligem Wert (AK3-Optik gilt fuer den
   Normalfall/Desktop, s. Kommentar oben). Spaltenbreiten (Rank/Slot/Waffe
   inhaltsbreit, User traegt bewusst die groesste relative Verengung — hat
   als einzige Spalte Ellipsis als Ausweg — DMG/Credits/Hexas bekommen den
   groessten Anteil, da sie je ein unbrechbares Zahlen-Token ohne
   Ellipsis-Rueckfall tragen) + volle Vorher/Nachher-Messwerte beider
   Iterationen s. Ticket ## Notes. */
/* ui-490 Review-Fund (Re-Spawn, 2026-08-20): die obigen px-Breiten (Erstfassung
   26/38/28) deckten NUR den DATEN-Inhalt (Rank-Zahl/Slot-Badge/Waffe-Icon) ab —
   nicht die HEADER-LABEL-Woerter selbst ("Rank"/"Slot"/"Waffe", ungekuerzter
   Volltext aus participantTableHeadHtml() oben). Unter table-layout:fixed
   (anders als dem alten table-layout:auto, das jeder Spalte automatisch
   mindestens die Breite ihres Headers gab) laesst ein zu schmaler th sein
   unbrechbares Header-Wort (kein Leerraum zum Umbrechen) optisch in die
   NAECHSTE Spalte auslaufen — Live-CDP (Range.getBoundingClientRect() je
   th-Textknoten, s. Ticket ## Notes) zeigt "RANK"/"WAFFE" ueberlappend mit
   "SLOT"/"USER" auf allen Nicht-Mobile-Breiten (390-1400px, Rang UND Profil).
   WICHTIGER BEFUND: der Overflow laeuft IMMER Richtung Zeilenende (rechts,
   LTR) — auch bei th.num/text-align:right (Rank, DMG done, Credits, Hexas):
   text-align verteilt nur FREIEN Raum um, wenn der Inhalt in die Box passt;
   ist die Box zu schmal, gibt es keinen freien Raum zu verteilen, und der
   Browser rendert ab der Content-Box-Startkante (= Padding-Left-Kante) nach
   rechts weiter, exakt wie bei text-align:left (empirisch bestaetigt, nicht
   nur aus der Spec hergeleitet). Daraus folgt: der sichtbare Abstand zwischen
   dem ueberlaufenden Text von Spalte i und dem Textbeginn von Spalte i+1 ist
   NUR width_i − textBreite_i (das th-Padding kuerzt sich weg, SOLANGE beide
   Nachbarn dasselbe Padding tragen — hier unveraendert der Fall). Schmaleres
   Padding (eine der urspruenglich erwogenen Fix-Richtungen) haette NICHTS
   gebracht, weil es sich exakt herauskuerzt — nur eine breitere Spalte hilft.
   Deshalb Rank (26→36px) und Waffe (28→44px) verbreitert (Live-CDP-Textbreite
   bei Desktop-Fontgroesse: "RANK" ≈29,6px, "WAFFE" ≈37,0px — je +≈6-7px
   Sicherheitsabstand zur naechsten Spalte, auf JEDER getesteten Nicht-Mobile-
   Breite einzeilig OHNE Umbruch). Slot bleibt UNVERAENDERT bei 38px: "SLOT"
   braucht dieselben ≈29,6px wie "RANK", aber Slots eigene 38px liessen schon
   VOR diesem Fix einen positiven Abstand von +8,4px zu Waffe (Live-CDP
   bestaetigt: Slots Overflow blieb innerhalb der eigenen+Waffes Padding-Zone,
   erreichte nie Waffes Text) — der must-fix-Befund listete Slot zwar mit 21%
   rechnerischem Defizit (Volltext-Boxbreite inkl. Padding vs. verfuegbar),
   das ist aber nicht dasselbe wie ein sichtbarer Glyphen-Overlap; Live-Messung
   vor UND nach diesem Fix zeigt Slot ohne Ueberlappung (Ticket ## Notes,
   Tabelle „Header-Messwerte").
   ZWEI WEITERE ITERATIONEN (im selben Re-Spawn, VOR dem Commit korrigiert,
   volle Herleitung s. Ticket ## Notes):
   (1) Rank/Waffe wie oben beschrieben verbreitert, OHNE weitere Aenderung —
       bestand Rang/Profil-Desktop (390-1280px), verschob das Problem aber
       eine Spalte weiter: bei 390px/Profil (einzige Nicht-Karten-390px-
       Ansicht) blieb dem Rest-Anteil fuer User/DMG done/Credits/Hexas so
       wenig Platz, dass STATTDESSEN "User"/"Credits" in ihre jeweils naechste
       Spalte ueberliefen (Live-CDP: User→DMG done −4,0px, Credits→Hexas
       −5,5px) — derselbe Overlap-Mechanismus, nur eine Spalte weiter rechts.
   (2) Testweise `overflow-wrap: anywhere` auf ALLE th (Basisregel) ergaenzt,
       PLUS Rank/Waffe wegen der dadurch knapperen Prozent-Spalten auf
       34/41px zurueckgenommen: behob den Overlap ueberall, aber mit
       Nebenwirkung — sobald Umbrechen ERLAUBT ist, WIRD bevorzugt umgebrochen
       statt ueberzulaufen (CSS-Verhalten, nicht nur ein Grenzfall), d.h. der
       Fit-Schwellwert fuer EINZEILIGKEIT springt zurueck auf textBreite+
       PADDING (~46px Rank/Slot, ~53px Waffe — exakt die urspruenglichen
       Review-Zahlen). Ergebnis: Rank/Slot/Waffe brachen live JETZT AUCH BEI
       700-1280px MITTEN IM WORT um ("RA"/"NK" 2-zeilig) — kein Overlap mehr,
       aber ein voellig unnoetig zerstueckelter Header auf breiten Viewports,
       wo eigentlich reichlich Platz ist.
   FINALE LOESUNG: Rank/Slot/Waffe bleiben bei 36/38/44px OHNE overflow-wrap
   (Variante (1), sauber einzeilig ueberall wo getestet) — der eigentliche
   390px/Profil-Rest-Budget-Engpass wird STATTDESSEN gezielt NUR auf den
   betroffenen Spalten User/DMG done/Credits/Hexas mit einer SCOPED
   overflow-wrap-Regel abgefangen (th:nth-child(n+4), s. dort) statt
   blanket auf allen th — das haelt Rank/Slot/Waffe garantiert einzeilig
   (sie bekommen die Regel gar nicht erst zugewiesen) und beschraenkt den
   Umbruch-Fallback auf genau die Spalten, die ihn bei 390px/Profil
   tatsaechlich brauchen. Neues px-Budget Rank+Slot+Waffe: 36+38+44=118px
   (vorher 92px, +26px); strukturell weiterhin 0 Overflow (table-layout:
   fixed/width:100% garantiert das unabhaengig von der konkreten Aufteilung,
   s. Kommentar oben) — Live-CDP-Nachmessung nach ALLEN drei Iterationen
   bestaetigt (Ticket ## Notes, volle Vorher/Zwischenstand/Nachher-Tabelle). */
.hs-participant-table th:nth-child(1) { width: 36px; }  /* Rank: 1-2-stellig, num — UND Header-Label "Rank" (≈29,6px Text), einzeilig */
.hs-participant-table th:nth-child(2) { width: 38px; }  /* Slot: .pn-Badge #0…#12 — Header-Label "Slot" passt bereits (unveraendert, s. Kommentar oben) */
.hs-participant-table th:nth-child(3) { width: 44px; }  /* Tower (ui-521, vormals "Waffe"): 18px-SVG-Icon, kein Text — UND Header-Label "Tower" (gleiche Zeichenzahl wie "Waffe", Font ui-monospace → identisch ≈37,0px Text, laengstes der drei), einzeilig — live nachgemessen, keine Breitenaenderung noetig */
/* game-153: neue Spalte "Tod" (Killing-Blow-Icon) — inhaltsbreit wie Rank/Slot/
   Tower (18px-SVG-Icon, kein Fliesstext), Header-Label "TOD" (3 Zeichen) kuerzer
   als alle drei Geschwister → dieselbe 44px-Breite wie Tower ist ein sicherer
   oberer Rahmen fuer ein gleich grosses Icon in derselben Zellen-Padding-Zone
   (kein neues Live-Messverfahren noetig, mirrored von einem bereits verifizierten
   Wert). Live-CDP-Messmatrix in Ticket ## Notes bestaetigt keinen Overlap. */
.hs-participant-table th:nth-child(4) { width: 44px; }  /* Tod (game-153) */
.hs-participant-table th:nth-child(5) { width: 11%; }   /* User: flexibel, ellipsiert (AK3) — traegt bewusst die Hauptlast der 390px-Verengung (game-153: 12%→11%, Platz fuer die neue Spalte) */
.hs-participant-table th:nth-child(6) { width: 28%; }   /* DMG done: Zahl + · NN,N % (game-153: 30%→28%) */
.hs-participant-table th:nth-child(7) { width: 26%; }   /* Credits: Zahl + Icon (game-153: 28%→26%) */
.hs-participant-table th:nth-child(8) { width: 27%; }   /* Hexas: Summe + Breakdown-Subzeile (game-153: 30%→27%) */
/* ui-490 Review-Fund (Re-Spawn): strukturelle zweite Sicherung NUR fuer die
   vier Header User/DMG done/Credits/Hexas (game-153: th:nth-child(n+5) = 5.-8.
   Kind, vormals n+4/4.-7. Kind vor der neuen Tod-Spalte) —
   bewusst NICHT auf Rank/Slot/Waffe/Tod (s. Kommentar oben: die brauchen das
   Netz nicht UND wuerden es, einmal aktiv, faelschlich staendig ziehen,
   selbst auf breiten Viewports mit reichlich Platz — overflow-wrap aendert
   den Einzeiligkeits-Schwellwert einer Spalte grundsaetzlich auf textBreite+
   Padding, nicht nur im Engpass-Fall). Bei 390px/Profil reicht der nach dem
   Rank/Waffe-Fix verbleibende Rest-Anteil fuer diese vier Spalten nicht mehr
   fuer jedes Header-Wort einzeilig (v.a. "Credits", laengstes Wort ausser
   "Waffe") — ohne dieses Netz liefe das WIEDER in die naechste Spalte aus
   (Live-CDP bestaetigt: ohne die Regel "User→DMG done" und "Credits→Hexas"
   bei 390px/Profil negativ, s. Ticket ## Notes). MIT der Regel bricht das
   betroffene Wort im Zweifel MITTEN im Wort auf eine zweite Zeile (haesslich,
   aber lesbar, KEIN Overlap) — bei ALLEN 6 Live-CDP-getesteten Nicht-Mobile-
   Szenarien AUSSER dem knappsten (390px/Profil) inert, dort strukturell
   inhaerent (275px Container fuer 7 dichte Spalten, derselbe Trade-off wie
   bei den Werte-Spalten unten: AK1 kein Overlap hat Vorrang vor einzeiligem
   Header bei 390px). game-153 fuegt eine achte, inhaltsbreite Spalte hinzu
   (Tod, s.o.) — die 390px-Restbudget-Rechnung bleibt qualitativ unveraendert
   (Live-CDP-Nachmessung dieses Tickets in ## Notes bestaetigt). */
.hs-participant-table th:nth-child(n+5) { overflow-wrap: anywhere; }
/* ui-490: strukturelle zweite Sicherung gegen Container-Overflow bei extrem
   engen Spalten (s. Kommentar oben) — bricht nur, wenn ein einzelnes Token
   (keine Leerstelle) breiter als seine Spalte ist; Ziffern bleiben immer
   vollstaendig sichtbar (nur der Zeilenumbruch landet mitten im Token statt
   an einer Leerstelle). td:nth-child(5) (User, game-153: vormals 4 vor der
   neuen Tod-Spalte) explizit ausgenommen — hat bereits eigene Ellipsis-Regel
   (kein doppeltes/konkurrierendes Verhalten). */
.hs-participant-table td:not(:nth-child(5)) { overflow-wrap: anywhere; }
/* ui-490 AK3: lange Usernamen ellipsieren statt die Tabelle zu schieben —
   nur diese Spalte (Text, keine Messgroesse) darf schrumpfen. width kommt
   implizit aus der th-Regel oben (table-layout:fixed), hier nicht wiederholt
   (s. Begruendung "NUR auf th" oben). game-153: Index 4→5 (neue Tod-Spalte
   davor). */
.hs-participant-table td:nth-child(5) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ui-157: Waffen-Zelle + SSR-Inline-SVG-Icon (DL-3: 18px, kein Glow) */
.wpn-cell {
  display: flex;
  align-items: center;
  gap: 0;
}
svg.wpn-icon {
  display: block;
  flex: 0 0 auto;
  overflow: visible;
}

/* game-153: Killing-Blow-Zelle — enemyIconSVG()-Output (100x100 viewBox, kein
   eigenes class-/width-/height-Attribut, s. src/enemy-intro.js) auf dieselbe
   visuelle Groesse wie das Waffen-Icon geklemmt. overflow:visible haelt den
   feDropShadow-Glow sichtbar (analog svg.wpn-icon oben). */
.kb-cell {
  display: flex;
  align-items: center;
  gap: 0;
}
.kb-cell svg {
  display: block;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  overflow: visible;
}

/* web-160: Balance-Tabelle — Waffen-Spalte, DMG-Anteil-Zelle, Unknown-Zeile */
/* .wpn: Icon + Label nebeneinander (Flex-Row mit Gap) */
.wpn {
  display: flex;
  align-items: center;
  gap: .5em;
}
.wpn strong {
  color: var(--text);
  font-weight: 600;
}
/* .share-cell: Balken + Prozentzahl inline-flex, rechtsbündig */
.share-cell {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  justify-content: flex-end;
}
/* DL-7: Alt-Runs ohne weapon — gedämpfte Farbe */
tbody tr.unknown td {
  color: var(--text-dim);
}

/* web-077: Versions-Tag-Pill — dezenter Neutral-Chip (DL-3/DL-4).
   Genutzt von /highscore und Dashboard-Runs-Tab.
   Neutral-Farbrolle (muted + line-2): bewusst NICHT Cyan (= interaktiv/primär),
   NICHT Magenta (= Hexa). Kein Glow, kein Hover-Akzent (nicht interaktiv). */
.hs-version {
  display: inline-block;
  padding: 0.1em 0.5em;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--muted);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.82em;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
/* Baseline-Variante: Alt-Runs ohne Versions-Tag (app_version = NULL).
   Gedämpft + kursiv + gestrichelt → liest als "keine echte Version",
   nicht als echte v0.1.0. Deckt sich mit Architektur-Lock "kein Default-Stempel". */
.hs-version--baseline {
  opacity: 0.65;
  font-style: italic;
  border-style: dashed;
}
/* web-079 DL-7: verlinkter Version-Pill (Muster wie .hs-expand-link).
   Default bleibt dezent/muted — kein dauerhaftes Cyan (sonst schreit jede Pille).
   Hover → cyan; Reihenfolge hier direkt nach .hs-version-Block (DL-9). */
a.hs-version {
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s;
  text-decoration: none;
}
a.hs-version:hover {
  border-color: var(--cyan);
  color: var(--cyan);
}

/* =================================================================
   ui-138: DPS-Verlaufs-Graph im Highscore-Run-Detail
   .dps-run = Container-Block, ÜBER der Teilnehmer-Tabelle (DL-1).
   SVG statisch (kein rAF), Hover-Sync via web/public/highscore.js.
   Tokens via var(--*); Palette-Hex nur inline (Datenwert, kein Design-Token).
   ================================================================= */

/* Container + Header */
.dps-run { margin: 0 0 14px; }
.dps-run-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}
.dps-run-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.dps-run-sub {
  font-size: var(--fs-caption); /* ui-505 (M3): 10px -> --fs-caption (K1) */
  color: var(--muted);
  letter-spacing: .03em;
}

/* SVG-Wrapper: responsive (DL-7) */
.dps-graph-wrap { width: 100%; }
.dps-graph { display: block; width: 100%; height: auto; }

/* Achsen + Grid */
.dg-axis      { stroke: var(--line); stroke-width: 1; fill: none; }
.dg-grid      { stroke: rgba(255,255,255,.05); stroke-width: 1; fill: none; }
.dg-grid-dec  { stroke: rgba(255,255,255,.08); stroke-width: 1; fill: none; }
.dg-axis-lbl  { fill: var(--muted); font-size: 10px; }
.dg-axis-lbl.y { text-anchor: end; }
.dg-axis-lbl.x { text-anchor: middle; }
.dg-axis-title { fill: var(--text-dim); font-size: 10px; letter-spacing: .04em; }

/* Boss-Marken (DL-3): unter den Linien, magenta gestrichelt */
.dg-boss-line {
  stroke: var(--magenta);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: .5;
  fill: none;
}
/* ui-505 (M3): 9px -> --fs-micro (K2, 10px-Boden) — Wave-Nr. am Boss-Marker ist
   redundant zu .bc-wave "W{n}" im Boss-Sequenz-Chip-Strip direkt ueber dem
   Graph (renderBossSeqStrip, web-168), gleiche Zahl bereits voll lesbar dort. */
.dg-boss-lbl { fill: var(--magenta); font-size: var(--fs-micro); text-anchor: middle; opacity: .8; }
/* web-168/DL-4: Glyph an Boss-Marke (Magenta, uber Wave-Nr) */
.dg-boss-glyph { fill: var(--magenta); font-size: 12px; text-anchor: middle; opacity: .95; }

/* web-168: Boss-Art-Sequenz-Strip (DL-1..DL-3, DL-5) */
/* Strip-Container -- UBER dem DPS-Verlauf (vor .dps-run, DL-1/DL-6) */
.boss-seq { margin: 0 0 14px; }
.boss-seq-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}
.boss-seq-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.boss-seq-sub { font-size: var(--fs-caption); color: var(--muted); letter-spacing: .03em; } /* ui-505 (M3): 10px -> --fs-caption (K1) */
/* Chip-Reihe (DL-3: farb-neutral, Identitat via Glyph) */
.boss-seq-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.boss-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 3px 9px 3px 7px;
  font-size: 12px;
  line-height: 1.4;
  cursor: default;
  position: relative;
  transition: border-color .15s;
}
.boss-chip:hover { border-color: var(--cyan); }
.boss-chip .bc-glyph {
  font-size: 14px;
  color: var(--text);
  width: 1.2em;
  text-align: center;
  display: inline-block;
}
.boss-chip .bc-wave { color: var(--muted); font-weight: 600; font-variant-numeric: tabular-nums; }
/* CSS-Tooltip (Boss-Art-Name) -- ergaenzt title/aria-label fuer a11y */
.boss-chip[data-name]:hover::after {
  content: attr(data-name);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg);
  border: 1px solid var(--line-2);
  color: var(--text);
  font-size: 11px;
  white-space: nowrap;
  padding: 3px 8px;
  border-radius: 5px;
  box-shadow: 0 2px 10px rgba(0,0,0,.5);
  z-index: 5;
}
/* Fallback (Alt-Run mit Bossen, keine Sequenz -- DL-5) */
.boss-seq-empty {
  color: var(--muted);
  font-size: 12px;
  font-style: italic;
  border: 1px dashed var(--line);
  border-radius: 8px;
  padding: 10px 4px;
  text-align: center;
}

/* DPS-Linien (DL-4/DL-5) */
.dg-line {
  fill: none;
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: .85;
  transition: opacity .12s, stroke-width .12s;
}
.dg-line.dim  { opacity: .18; }
.dg-line.hi   { opacity: 1; stroke-width: 2.8; filter: drop-shadow(0 0 4px currentColor); }

/* End-Labels (#n am Linienende)
   ui-505 (M3): 9.5px -> --fs-micro (K2, 10px-Boden) — "#n" ist redundant zur
   .pn-Farbpille in der Teilnehmer-Tabelle direkt darunter (Kommentar dort:
   "= Legende"), gleiche Nummer/Farbe bereits voll lesbar in der Tabelle. */
.dg-endlbl {
  font-size: var(--fs-micro);
  font-weight: 800;
  paint-order: stroke;
  stroke: var(--bg-2);
  stroke-width: 2.6px;
  stroke-linejoin: round;
}
.dg-endlbl.dim { opacity: .2; }

/* #n-Farbpill in der Teilnehmer-Tabelle = Legende (DL-4) */
.pn {
  display: inline-block;
  min-width: 26px;
  text-align: center;
  font-weight: 800;
  font-size: 11px;
  border-radius: 5px;
  padding: 1px 6px;
  /* color wird inline gesetzt (dunkle Schrift auf hellem Hintergrund) */
}

/* Hover-Highlight Tabellenzeile (DL-5): komplementär zur Linie */
.hs-participant-table tbody tr.hs-row--hi { background: rgba(56,225,255,.08); }

/* „nicht erfasst"-Hinweis (DL-6) */
.dps-empty {
  color: var(--muted);
  font-size: 12px;
  font-style: italic;
  padding: 18px 4px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  text-align: center;
  margin-bottom: 14px;
}

/* =====================================================================
   ui-396: Highscore mobil als Karten (web-221 P3.2) — Prototyp ui-396.html

   Die Run-Ranglisten (public /highscore + Dashboard-Highscore-Tab, EIN
   Render-Kern highscoreBody()) rendern bei ≤600px als aufklappbare Karten
   statt der horizontal scrollenden Tabelle (DL-1..DL-8, Ticket ui-396).
   Markup: jede Run-Zeile hat eine ZUSÄTZLICHE .hs-cardrow (views/
   highscore.js renderRunCardRow) — Sichtbarkeit regelt ausschließlich
   dieser Block.

   SCOPE-KRITISCH: alles unter `.highscore` (section aus highscoreBody) —
   die Profilseite (/u/:login) nutzt DIESELBEN .hs-board/.hs-boardbar/
   .hs-table/.hs-participant-table-Klassen für ihre Top-/Letzte-Runs-Panes
   (ui-365, renderPersonalTable). Ungescopte Blockification würde hier UND
   auf /styleguide (Klassen-Kollisionsfalle dieses Projekts) ungewollt
   greifen — deshalb bleibt DIESER Block strikt `.highscore`.
   ui-399 (2026-08-08) gibt der Profilseite dieselbe Karten-ZEILE dazu, aber
   über einen EIGENEN `.profile-page`-Block am Dateiende (additiv DANEBEN,
   nicht durch Scope-Erweiterung dieses Blocks — s. dortiger Kommentar). Das
   DETAIL (`.hs-participant-table`-Grid/`.dps-graph-m` weiter unten) bleibt
   weiterhin NUR `.highscore` — renderPersonalParticipantsCell bekommt
   bewusst keine Mobile-Varianten (s. highscore.js-Kommentar dort).

   Position am DATEIENDE (nach ui-394/ui-395): die Blockification muss
   Basis-Regeln gleicher/niedrigerer Spezifität überstimmen (Sticky-Spalte
   auf td:first-child der äußeren Run-Tabelle — ui-510: Selektor jetzt
   `.hs-table > tbody > tr > td:first-child`, Scroll-Schatten .hs-scroll,
   ≤600px-Kompakt-Regeln — alle weiter oben in dieser Datei) — Source-Order zählt. Definiert
   sonst nur NEUE Klassen (.hs-card*, .dgm-*, .dps-graph-m/-legend-m,
   .hs-dmg-full/-short); keine Überschneidung mit ui-394-Targets oder
   ui-395-Tooltips (die Pakt-Chips/.tipwrap im Detail-Fragment bleiben
   unangefasst — CTTip positioniert per Portal, unabhängig vom Layout). */

/* --- Basis (alle Viewports): Mobile-only-Markup versteckt.
   .hs-cardrow/.hs-dmg-short/.dps-graph-m/.dps-legend-m existieren im DOM
   beider Welten (ein Render-Kern, DL-8) — sichtbar wird davon nur ≤600px
   im .highscore-Scope etwas. Desktop-Tabellen + Profil bleiben visuell
   unverändert. */
.hs-cardrow { display: none; }
.hs-dmg-short { display: none; }
.dps-graph-m,
.dps-legend-m { display: none; }

@media (max-width: 600px) {
  /* --- ui-628 (loest ui-389/DL-6 fuer DIESE Sub-Nav ab): der vormalige
     Wisch-Strip (nowrap + overflow-x, Ehrenhalle lag rechts ausserhalb
     ohne Scroll-Affordance — Fiftys Symptom) ist ERSATZLOS entfernt. 7
     Boards -> Lock 6 -> immer ein Auswahl-Sheet (renderSubnavPick()/
     renderSubnavSheet() in highscoreBody(), views/highscore.js). Scope
     `.highscore` ist PFLICHT (nicht `.profile-page`): `.hs-boardbar`/
     `.hs-board-tab` sind ein GETEILTER Klassenname mit dem 2-Board-
     Top/Letzte-Runs-Switcher auf JEDEM Spieler-Profil (views/profile.js
     renderPersonalTable()-Umgebung, s. Datei-Kopf "SCOPE-KRITISCH") — der
     bleibt unveraendert ein Pillen-Wisch-Strip (2 Eintraege, Out-of-Scope
     dieses Tickets), ein bare `.hs-boardbar{display:none}` haette ihn
     mit ausgeblendet. --- */
  .highscore .hs-boardbar { display: none; }

  /* --- Tabellen-Blockification der Run-Boards: Desktop-Zeilen weg,
     Karten-Zeilen an. thead entfällt (die Karte beschriftet sich selbst).
     .hs-scroll wird neutralisiert (kein H-Scroll, keine Schatten-Gradients
     der Basis-Regel oben in dieser Datei — sonst malt der cyan-Indikator auf die Karten). --- */
  .highscore .hs-board .hs-scroll {
    overflow-x: visible;
    background: none;
  }
  .highscore .hs-board .hs-table,
  .highscore .hs-board .hs-table tbody { display: block; }
  .highscore .hs-board .hs-table thead { display: none; }
  .highscore .hs-board .hs-table tr.hs-row { display: none; }

  /* --- DL-1: Run-Karte. Die colspan-Zelle selbst ist die Karte (Panel-Optik
     wie .hall). position:static/box-shadow:none neutralisieren die Sticky-
     Erste-Spalte-Regel (oben in dieser Datei, trifft als td:first-child auch diese Zelle). */
  .highscore .hs-board .hs-cardrow { display: block; }
  .highscore .hs-board .hs-cardrow td {
    display: block;
    position: static;
    box-shadow: none;
    padding: 0;
    background: var(--panel);
    border: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    border-radius: 8px;
    margin-bottom: 8px;
    overflow: hidden;
  }

  /* Kopfzeile = Aufklapp-Trigger (DL-2): voller Button, ≥56px, keine Links. */
  .highscore .hs-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 56px;
    padding: 10px 12px;
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
  }
  /* DL-3: Rang-Badge — Podium als Badge-FLÄCHE (rank-1/2/3 + text-on-accent),
     ab Rang 4 neutral. Kein Glow (die .ct-rank-*-Textrollen gelten hier nicht —
     eigene Klasse, Farbe ist der Rang, nicht Dekoration). */
  .highscore .hs-card-rank {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 700;
    background: var(--bg-2);
    color: var(--text-dim);
  }
  .highscore .hs-card-rank.p1 { background: var(--rank-1); color: var(--text-on-accent); }
  .highscore .hs-card-rank.p2 { background: var(--rank-2); color: var(--text-on-accent); }
  .highscore .hs-card-rank.p3 { background: var(--rank-3); color: var(--text-on-accent); }
  /* KW-Reward-Pille neben dem Badge (kwRewardPill, Basis oben in dieser Datei). */
  .highscore .hs-card-head .kw-pill { flex: 0 0 auto; }

  .highscore .hs-card-mid { flex: 1 1 auto; min-width: 0; }
  /* ⚠ DL-1 Inline-Span-Falle: display:block Pflicht — als nackte inline-
     <span> fließen DMG- und Meta-Zeile in EINE Zeile und brechen mitten
     im Wert um (im Prototyp passiert + gefixt). */
  .highscore .hs-card-dmg {
    display: block;
    font-size: 19px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .highscore .hs-card-dmg small {
    font-size: 11px;
    font-weight: 400;
    color: var(--muted);
    margin-left: 4px;
    letter-spacing: 0.04em;
  }
  .highscore .hs-card-meta {
    display: block;
    margin-top: 2px;
    font-size: 12px;
    color: var(--text-dim);
  }
  .highscore .hs-card-meta .sep { color: var(--line-2); margin: 0 4px; }
  .highscore .hs-card-caret {
    flex: 0 0 auto;
    width: 24px;
    text-align: center;
    color: var(--muted);
    font-size: 12px;
    transition: transform 0.18s;
  }
  .highscore .hs-cardrow--open .hs-card-caret { transform: rotate(180deg); }

  /* Top-Tower-Zeile (Kronen-SVG + Profil-Link, Ellipsis) + Fuß (Datum links,
     Version-Pille rechts — .hs-version-Basis oben in dieser Datei). */
  .highscore .hs-card-sub {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 12px 9px;
    font-size: 12.5px;
    color: var(--text-dim);
  }
  .highscore .hs-card-sub svg { flex: 0 0 auto; }
  .highscore .hs-card-top {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
  }
  /* ui-542: "Du: #<Platz> · <DMG> DMG" — nur im Markup, wenn der Betrachter
     selbst an diesem Run teilgenommen hat (ownCardBadgeHtml() in highscore.js
     liefert sonst ''), Karte bleibt sonst unveraendert. Cyan wie die Desktop-
     Own-Spalten (Kanon "das bist du", s. .hall .hr-row.me weiter oben). */
  .highscore .hs-card-own {
    padding: 0 12px 9px;
    font-size: 12px;
    font-weight: 600;
    color: var(--cyan);
  }
  .highscore .hs-card-own .sep {
    color: var(--line-2);
    margin: 0 4px;
    font-weight: 400;
  }
  .highscore .hs-card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 12px 10px;
    font-size: 11px;
    color: var(--muted);
  }

  /* --- Detail-Zeile dockt als Block unter der offenen Karte an (Optik:
     Prototyp .run-body — dunkler Einschub, gemeinsame Rundung unten).
     Spezifität (0,3,1)+ schlägt die Basis-Regeln .hs-details-cell,
     .hs-details-row td (beide oben in dieser Datei) und die Sticky-td:first-child-Kette. --- */
  .highscore .hs-board .hs-cardrow--open td {
    margin-bottom: 0;
    border-bottom: none;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }
  [data-hs-js] .highscore .hs-board .hs-details-row.is-open { display: block; }
  .highscore .hs-board .hs-details-row td,
  .highscore .hs-board .hs-details-row td.hs-details-cell {
    display: block;
    position: static;
    box-shadow: none;
    background: rgba(0, 0, 0, 0.18);
    border: 1px solid var(--line);
    border-top: none;
    border-radius: 0 0 8px 8px;
    margin-bottom: 8px;
    padding: 10px 12px 12px;
  }
  /* Run-ID (36-Zeichen-Code) darf auf 366px nicht überlaufen. */
  .highscore .hs-board .hs-details-meta { overflow-wrap: anywhere; }

  /* --- DL-4: Teilnehmer als flexible Zeilen statt <table>.
     Zeile 1: Pos · #n-Farbpill · Name (flex, Ellipsis) · DMG-Kurzform + %
              · ⬢-Summe — alle Zahlen tabular-nums (erbt vom .hs-participant-
              table-Co-Selektor oben in dieser Datei).
     Zeile 2: Waffen-Icon · Tod-Icon (game-153) · Credits (Waffe entfällt
              nicht — zweite Zeile, nicht dieselbe; DL-4).
     Zeile 3: Hexa-Breakdown (Rank+/DMG+/★/Pakt+, volle Breite rechts —
              inkl. ui-395-Pakt-Tap-Tooltip, bleibt unangetastet).
     Die Hexas-Zelle (td 8, game-153: vormals 7 vor der neuen Tod-Spalte) wird
     per display:contents aufgelöst, damit .es-total (Zeile 1) und
     .es-breakdown (Zeile 3) getrennte Grid-Items werden — sonst zwänge die
     breite Breakdown-Zeile die Namensspalte weg. */
  .highscore .hs-board .hs-scroll--part::before {
    content: 'Teilnehmer';
    display: block;
    font-size: var(--fs-caption); /* ui-505 (M3): 10.5px -> --fs-caption (K1) */
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 2px;
  }
  .highscore .hs-board .hs-participant-table,
  .highscore .hs-board .hs-participant-table tbody { display: block; }
  .highscore .hs-board .hs-participant-table thead { display: none; }
  /* game-153: 'kb' (Tod-Icon) teilt sich Spalte 2 mit 'wpn' (Zeile 2) — dieselbe
     5-Spalten-Grid-Breite bleibt erhalten, nur Zeile 2 splittet ihren vormals
     alleinigen 'cred'-Span (Spalte 1-5) neu auf 'wpn'(1)/'kb'(2)/'cred'(3-5). */
  .highscore .hs-board .hs-participant-table tbody tr {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      'rank slot name dmg  hex'
      'wpn  kb   cred cred cred'
      'bd   bd   bd   bd   bd';
    align-items: center;
    column-gap: 8px;
    row-gap: 2px;
    padding: 7px 0;
    border-top: 1px solid var(--line);
    font-size: 12.5px;
  }
  .highscore .hs-board .hs-participant-table tbody tr:first-child { border-top: none; }
  .highscore .hs-board .hs-participant-table tbody td {
    display: block;
    position: static;
    box-shadow: none;
    background: none;
    border: none;
    padding: 0;
  }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(1) { grid-area: rank; text-align: left; color: var(--muted); }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(2) { grid-area: slot; }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(3) { grid-area: wpn; }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(4) { grid-area: kb; } /* game-153: Tod-Icon */
  .highscore .hs-board .hs-participant-table tbody td:nth-child(5) {
    grid-area: name;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(6) {
    grid-area: dmg;
    text-align: right;
    white-space: nowrap;
  }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(7) { grid-area: cred; text-align: left; }
  .highscore .hs-board .hs-participant-table tbody td:nth-child(8) { display: contents; }
  .highscore .hs-board .hs-participant-table tbody tr .es-total {
    grid-area: hex;
    text-align: right;
    font-size: 13px;
    white-space: nowrap;
  }
  .highscore .hs-board .hs-participant-table tbody tr .es-breakdown {
    grid-area: bd;
    justify-self: end;
    text-align: right;
    white-space: normal;   /* seit ui-490 bereits Basisverhalten (.es-breakdown hat kein
       eigenes nowrap mehr, s. dortiger Kommentar) — hier explizit gehalten als Doku, dass
       der Mobile-Kartenumbruch hierauf angewiesen ist (kein reiner Bugfix-Leftover) */
    margin-top: 0;
  }
  /* DMG-Kurzform statt voller Zahl (nur hier — Desktop + Profil zeigen
     .hs-dmg-full weiter; Spans aus renderGlobalParticipantsCell). */
  .highscore .hs-board .hs-participant-table .hs-dmg-full { display: none; }
  .highscore .hs-board .hs-participant-table .hs-dmg-short { display: inline; }

  /* --- DL-5: DPS-Verlauf bleibt mobil — vereinfachter Graph (volle Karten-
     breite × 96px, preserveAspectRatio:none) + Legende statt Hover. Der
     Desktop-Graph (Achsen/Labels/Hover-Sync) wird ausgeblendet, nicht
     gestaucht (Text würde beim non-uniformen Stretch verzerren). --- */
  .highscore .hs-board .dps-graph-wrap { display: none; }
  .highscore .hs-board .dps-graph-m {
    display: block;
    height: 96px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bg-2);
    overflow: hidden;
  }
  .highscore .hs-board .dps-graph-m svg {
    display: block;
    width: 100%;
    height: 100%;
  }
  .highscore .hs-board .dgm-line { stroke-width: 1.6; }
  .highscore .hs-board .dgm-boss {
    stroke: var(--line-2);
    stroke-width: 1;
    stroke-dasharray: 3 3;
  }
  .highscore .hs-board .dps-legend-m {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 9px;
    margin-top: 6px;
    font-size: var(--fs-caption); /* ui-505 (M3): 10.5px -> --fs-caption (K1) — einzige Linien-Legende mobil (Desktop-Achsen/Hover ausgeblendet, s.o.) */
    color: var(--muted);
  }
  .highscore .hs-board .dgm-lg i {
    display: inline-block;
    width: 8px;
    height: 2px;
    margin-right: 3px;
    vertical-align: middle;
  }
  .highscore .hs-board .dgm-lg--boss { color: var(--line-2); }
}

/* ui-631 AK1/AK4: Desktop-Pendant zum Mobile-Hide oben (≤600px) — 7 Boards
   sind IMMER >= SUBNAV_DESK_PICK_MIN (views/subnav.js), `.hs-boardbar`
   weicht deshalb ab 601px unbedingt dem neuen Auswahl-Chip + Popover (seit
   ui-638 im `.subnav-desk-head`-Kopf-Container statt eines eigenen
   `.subnav-desk-row`, views/highscore.js). `.highscore` scopen ist
   Pflicht aus demselben Grund wie beim Mobile-Hide oben: `.hs-boardbar`/
   `.hs-board-tab` sind ein GETEILTER Klassenname mit dem 2-Board-
   Top/Letzte-Runs-Switcher auf jedem Spieler-Profil (views/profile.js,
   Out-of-Scope dieses Tickets) — der bleibt dort unter `.profile-page`
   (nicht `.highscore`) unveraendert eine Pillen-Leiste. */
@media (min-width: 601px) {
  .highscore .hs-boardbar { display: none; }
}

/* --- ui-396/DL-7 + AK „Touch-Targets ≥44px": Ehrenhalle-Interaktion auf
   Touch (alle Breiten — iPad-Lücke wie ui-394). Gleichstands-Summary wird
   44px hoch; Namens-Links bekommen die ::after-Hitbox (ui-214-Kanon wie
   a.name-link im ui-394-Block — eine BBox-Anhebung würde die Ellipsis der
   .hr-name-Zelle brechen, s. dortige Begründung); Mitglieder-Chips wachsen
   auf 44px (Wrap-Liste — überlappende ::after-Hitboxen wären dort Fehltaps).
   Desktop (hover+fine) byte-gleich. --- */
@media (hover: none), (pointer: coarse) {
  .hall details.hr-group > summary.hr-row { min-height: 44px; }
  .hall .hr-name a { position: relative; }
  .hall .hr-name a::after {
    content: '';
    position: absolute;
    inset: -15px -4px;
  }
  .hall .hr-members a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}
