/**
 * Palette aus dem Gildenlogo von Can't Breathe: tiefes Nachtblau-Violett als
 * Grund, das leuchtende Arkan-Violett der Kristalle und Augen, ein kaltes
 * Blau aus dem Nebel und das Gold des Schriftzugs „Midnight", das wie vorher
 * die Marke traegt. Fuer den Bildschirm etwas aufgehellt.
 */
:root {
  --bg: #0b0a1a;
  --bg-card: #15132e;
  --bg-card2: #1e1b40;
  --border: rgba(160,140,240,.17);
  --border-accent: rgba(212,168,80,.42);

  --text: #e3e0f4;
  --text-muted: #8f8ab2;

  /* Das Gold des Schriftzugs fuehrt */
  --accent: #d4a850;
  --accent-hover: #e8c274;

  /* Arkan-Violett und Nebelblau aus dem Bild, fuer die zweite Betonung.
     Die Namen bleiben, damit nicht jede Regel umgeschrieben werden muss. */
  --teal: #9a7cf2;
  --teal-deep: #5d43b8;
  --venom: #7ec93f;

  --gold: #d4a850;
  --success: #4fb35c;
  --warn: #d9a441;
  --danger: #d1544c;

  --font: 'Inter', system-ui, sans-serif;
  --radius: 6px;
}

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

/**
 * Site zoom, chosen per user in the profile. `zoom` rather than
 * transform: scale() — a transform would scale the box without changing the
 * layout width, so the page would overflow sideways at anything above 100 %.
 */
/* Die Flaeche hinter der Seite.
 *
 * Der Verlauf sitzt auf `body`, aber zwischen zwei Seitenaufrufen gibt es
 * kurz keinen `body` - der Browser malt dann seine eigene Flaeche. Ohne die
 * Farbe hier blitzt beim Wechsel zwischen den Reitern Weiss auf. */
html { background: var(--bg); color-scheme: dark; }

/* Reiterwechsel sind ganze Seitenaufrufe. Wo der Browser es kann, blendet er
   sie ineinander, statt hart umzuschalten; wo nicht, aendert sich nichts. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }

body { zoom: var(--ui-scale, 1); }

body {
  /* Leichter violetter Schimmer, wie der Nebel im Logo */
  background:
    radial-gradient(95% 55% at 50% 0%, rgba(110,70,210,.12), transparent 70%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text); font-family: var(--font); font-size: 13px;
  line-height: 1.5; min-height: 100vh;
}
a { color: var(--accent); text-decoration: none; }

/* ── Navbar ─────────────────────────────── */
.navbar {
  display: flex; align-items: center; gap: 1rem;
  padding: 0 1.5rem; height: 48px;
  background: var(--bg-card); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 100;
}
.nav-brand { display: flex; align-items: center; gap: 0.6rem; font-weight: 800; font-size: 0.95rem; color: var(--gold); letter-spacing: .04em; text-transform: uppercase; }
.nav-logo { width: 24px; height: 24px; border-radius: 4px; }
.nav-links { display: flex; gap: 0.15rem; flex: 1; margin-left: 1.25rem; }
.nav-link { padding: 0.3rem 0.65rem; border-radius: 4px; color: var(--text-muted); font-size: 0.8rem; font-weight: 500; letter-spacing: .02em; text-transform: uppercase; transition: all .15s; }
.nav-link:hover, .nav-link.active { background: rgba(154,124,242,.12); color: var(--accent); }

/* ── Ungelesene Notizen ───────────────────────────────────────────
 *
 * Giftgelb, und zwar ueberall dieselbe Farbe: das Abzeichen in der Navigation
 * und der Rand an der Kachel sind dieselbe Aussage an zwei Orten. Zwei Toene
 * dafuer waeren zwei Aussagen.
 */
:root { --gift: #c8f000; }

.nav-badge {
  display: inline-block; margin-left: 0.35rem; padding: 0 0.32rem;
  min-width: 1.05rem; border-radius: 999px;
  background: var(--gift); color: #1a1a1a;
  font-size: 0.66rem; font-weight: 800; line-height: 1.35;
  text-align: center; font-variant-numeric: tabular-nums;
  /* Der Schimmer macht den Unterschied zwischen „da steht eine Zahl" und „da
     ist etwas fuer dich" — in einer Leiste aus lauter grauen Woertern geht ein
     flacher Punkt unter. */
  box-shadow: 0 0 6px rgba(200,240,0,.45);
}
/* In der aktiven, eingefaerbten Schaltflaeche bleibt es lesbar */
.nav-link.active .nav-badge { box-shadow: none; }
.nav-user { display: flex; align-items: center; gap: 0.6rem; margin-left: auto; }

/* ── Mobile navigation ──────────────────────────────────────────── */
.nav-toggle {
  display: none; flex-direction: column; gap: 4px; margin-left: auto;
  background: none; border: 1px solid var(--border); border-radius: 5px;
  padding: 0.4rem 0.45rem; cursor: pointer;
}
.nav-toggle span {
  display: block; width: 18px; height: 2px; border-radius: 2px;
  background: var(--accent); transition: transform .2s, opacity .2s;
}
.navbar.nav-open .nav-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navbar.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.navbar.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
  .navbar { flex-wrap: wrap; height: auto; padding: 0.5rem 1rem; gap: 0.6rem; }
  .nav-toggle { display: flex; }

  /* Collapsed by default; the toggle reveals it as a full-width list */
  .nav-links {
    order: 3; flex-basis: 100%; margin-left: 0;
    flex-direction: column; gap: 0.15rem;
    max-height: 0; overflow: hidden;
    transition: max-height .25s ease;
  }
  .navbar.nav-open .nav-links { max-height: 70vh; overflow-y: auto; }
  .nav-link { padding: 0.55rem 0.7rem; font-size: 0.86rem; }

  /* The user block moves next to the brand, the toggle stays on the right */
  .nav-user { order: 2; margin-left: 0; }
  .user-name { display: none; }
}
.user-avatar { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border); }
.user-name { font-size: 0.78rem; color: var(--text-muted); }

/* ── Layout ──────────────────────────────── */
.main-content { padding: 1.25rem 1.75rem; max-width: 100%; }
.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; flex-wrap: wrap; gap: 0.6rem; }
.page-header h2 { font-size: 1.1rem; font-weight: 700; letter-spacing: .02em; color: var(--text); }
.page-subtitle { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.15rem; }
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.6rem; }

/* ── Cards ───────────────────────────────── */
.card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 0.9rem 1.1rem;
}
.card-header { font-weight: 700; font-size: 0.72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); margin-bottom: 0.75rem; }

/* ── Buttons ─────────────────────────────── */
.btn { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.35rem 0.85rem; border-radius: 4px; font-size: 0.78rem; font-weight: 600; letter-spacing: .02em; border: 1px solid transparent; cursor: pointer; transition: all .15s; text-decoration: none; background: transparent; color: var(--text); }
.btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-success { background: rgba(34,197,94,.15); color: var(--success); border-color: rgba(34,197,94,.3); }
.btn-success:hover { background: rgba(34,197,94,.25); }
.btn-danger { background: rgba(239,68,68,.15); color: var(--danger); border-color: rgba(239,68,68,.3); }
.btn-warn { background: rgba(245,158,11,.15); color: var(--warn); border-color: rgba(245,158,11,.3); }
.btn-ghost { border-color: var(--border); color: var(--text-muted); }
.btn-ghost:hover { background: rgba(255,255,255,.04); color: var(--text); }
.btn-discord { background: #5865F2; color: #fff; padding: 0.6rem 1.5rem; font-size: 0.9rem; width: 100%; justify-content: center; border-radius: 6px; }
.btn-discord:hover { background: #4752c4; }
.btn-sm { padding: 0.25rem 0.6rem; font-size: 0.75rem; }
.btn-xs { padding: 0.15rem 0.45rem; font-size: 0.72rem; }
.btn-group { display: flex; gap: 0.4rem; flex-wrap: wrap; }

/* ── Forms ───────────────────────────────── */
.form-row { margin-bottom: 0.75rem; }
.form-row label { display: block; font-size: 0.72rem; color: var(--text-muted); margin-bottom: 0.25rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.form-row input, .form-row select, .form-row textarea {
  width: 100%; background: var(--bg); border: 1px solid var(--border);
  border-radius: 4px; padding: 0.4rem 0.65rem; color: var(--text); font-size: 0.82rem;
}
.form-row input:focus, .form-row select:focus, .form-row textarea:focus { outline: none; border-color: var(--accent); }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 1rem; }
.form-actions { display: flex; gap: 0.6rem; margin-top: 0.9rem; }
.checkbox-label { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; font-size: 0.82rem; }

/* ── Badges ──────────────────────────────── */
.badge { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 4px; font-size: 0.75rem; font-weight: 600; }
.badge-open { background: rgba(34,197,94,.12); color: var(--success); }
.badge-closed { background: rgba(154,124,242,.12); color: var(--accent); }
.badge-cancelled { background: rgba(239,68,68,.12); color: var(--danger); }
.badge-confirmed { background: rgba(34,197,94,.12); color: var(--success); }
.badge-late { background: rgba(245,158,11,.12); color: var(--warn); }
.badge-angeschrieben { background: rgba(96,165,250,.14); color: #7fb4f7; }
.badge-absent { background: rgba(239,68,68,.12); color: var(--danger); }
.badge-unknown { background: rgba(107,114,128,.12); color: var(--text-muted); }
/* Herkunft eines Bewerbers. Bewusst nicht in den Farben des Status
   (grün, gelb, rot): „gesucht" und „gefunden" sind keine Bewertung. */
.badge-gesucht { background: rgba(154,124,242,.16); color: var(--teal); }
.badge-gefunden { background: rgba(167,139,250,.14); color: #b9a4f5; }

/* ── Alerts ──────────────────────────────── */
.alert { padding: 0.7rem 1rem; border-radius: 6px; font-size: 0.875rem; margin-bottom: 1rem; }
.alert-error { background: rgba(239,68,68,.1); border: 1px solid rgba(239,68,68,.25); color: #fca5a5; }
/* `alert-danger` steht in zehn Vorlagen (Raidseite, Profil, Videos, Umfragen …)
   und hatte keine einzige Regel: jede Fehlermeldung der Seite stand als nackter
   Text da, ohne Rahmen und ohne Farbe. Derselbe Anstrich wie alert-error. */
.alert-danger { background: rgba(239,68,68,.1); border: 1px solid rgba(239,68,68,.25); color: #fca5a5; }
.alert-warn  { background: rgba(245,158,11,.1); border: 1px solid rgba(245,158,11,.25); color: #fcd34d; }
.alert-success { background: rgba(34,197,94,.1); border: 1px solid rgba(34,197,94,.25); color: #86efac; }

/* ── Login page ──────────────────────────── */
.login-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; }
.login-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 2.5rem 2rem; width: 100%; max-width: 380px; text-align: center; }
.login-logo { width: 64px; height: 64px; border-radius: 14px; margin-bottom: 1rem; }
.login-card h1 { font-size: 1.6rem; margin-bottom: 0.25rem; }
.login-subtitle { color: var(--text-muted); margin-bottom: 1.75rem; }
.login-note { color: var(--text-muted); font-size: 0.8rem; margin-top: 0.75rem; }

/* ── Dashboard ───────────────────────────── */
.dash-char-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.3rem 0; border-bottom: 1px solid var(--border); font-size: 0.8rem; }
.dash-char-row:last-child { border-bottom: none; }
.char-name { font-weight: 600; flex: 1; }
.char-meta { color: var(--text-muted); font-size: 0.75rem; }
.char-ilvl { color: var(--gold); font-weight: 700; min-width: 48px; text-align: right; font-size: 0.78rem; }
.char-rio  { color: var(--accent); font-size: 0.75rem; min-width: 48px; text-align: right; }
.raid-row { display: flex; justify-content: space-between; align-items: center; padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
.raid-row:last-child { border-bottom: none; }
.raid-title { font-weight: 600; font-size: 0.82rem; }
.raid-date { color: var(--text-muted); font-size: 0.75rem; }

/* ── Raid list / card ────────────────────── */
.raid-list { display: grid; gap: 0.75rem; }
.raid-card { display: block; color: var(--text); transition: border-color .15s; }
.raid-card:hover { border-color: var(--accent); }
.raid-card.status-closed { opacity: .7; }
.raid-card.status-cancelled { opacity: .5; }
.raid-card-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.35rem; }
.raid-card-title { font-weight: 700; font-size: 1rem; }
.raid-card-date { color: var(--text-muted); font-size: 0.82rem; }
.raid-card-desc { color: var(--text-muted); font-size: 0.82rem; margin-top: 0.25rem; }
.raid-card-footer { color: var(--text-muted); font-size: 0.78rem; margin-top: 0.5rem; }

/* ── Raid detail ─────────────────────────── */
.role-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; }
.role-card { }
.role-header { font-weight: 700; font-size: 0.9rem; margin-bottom: 0.5rem; display: flex; justify-content: space-between; }
.role-count { color: var(--text-muted); font-weight: 400; }
.signup-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.3rem 0; font-size: 0.82rem; border-bottom: 1px solid rgba(255,255,255,.04); }
.mini-avatar { width: 20px; height: 20px; border-radius: 50%; }
.signup-name { flex: 1; font-weight: 500; }
.signup-ilvl { color: var(--warn); font-size: 0.78rem; }
.signup-class { font-size: 0.75rem; padding: 0.1rem 0.4rem; border-radius: 4px; background: rgba(255,255,255,.06); }
.status-row { padding: 0.3rem 0; font-size: 0.875rem; }
.radio-btn { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.35rem 0.75rem; border: 1px solid var(--border); border-radius: 6px; cursor: pointer; font-size: 0.85rem; }
.radio-btn input { display: none; }
.radio-btn.selected, .radio-btn:has(input:checked) { border-color: var(--accent); background: rgba(154,124,242,.1); color: var(--accent); }

/* ── Stats table ─────────────────────────── */
.stats-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.stats-table th { text-align: left; padding: 0.4rem 0.65rem; color: var(--text-muted); font-size: 0.68rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; border-bottom: 1px solid var(--border); }
.stats-table td { padding: 0.4rem 0.65rem; border-bottom: 1px solid rgba(255,255,255,.035); vertical-align: middle; }
.stats-table tbody tr:hover { background: rgba(255,255,255,.02); }
.ilvl-badge { background: rgba(200,155,60,.12); color: var(--gold); padding: 0.1rem 0.45rem; border-radius: 3px; font-weight: 700; font-size: 0.78rem; }
/* Set-Bonus: das aktuelle Set ist die Auskunft, auf die es ankommt — ein Set
   aus altem Inhalt bleibt sichtbar, tritt aber farblich zurueck. */
.set-badge { padding: 0.1rem 0.4rem; border-radius: 3px; font-weight: 700; font-size: 0.74rem; letter-spacing: .02em; white-space: nowrap; }
.set-badge.set-aktuell { background: rgba(120,200,120,.14); color: #7fce7f; }
.set-badge.set-alt { background: rgba(255,255,255,.05); color: var(--text-muted); border: 1px solid rgba(255,255,255,.10); }

/* Gearscore-Verlauf ueber dem Kader: breit ueber die volle Spalte, damit die
   Wochen als Bewegung lesbar sind und nicht als vier Punkte. Der Goldschimmer
   oben nimmt die Farbe der Linie auf, statt die Karte neutral zu lassen. */
.verlauf-karte {
  width: 100%;
  position: relative;
  overflow: hidden;
  border-color: var(--border-accent);
  background:
    radial-gradient(120% 90% at 82% -20%, rgba(212,168,80,.10), transparent 60%),
    radial-gradient(80% 70% at 0% 0%, rgba(154,124,242,.07), transparent 60%),
    var(--bg-card);
}
.verlauf-karte::before {
  content: '';
  position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, rgba(212,168,80,.15), var(--gold) 55%, var(--venom));
}
.verlauf-kopf { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.verlauf-titel { font-size: 0.94rem; font-weight: 700; letter-spacing: .01em; color: var(--text); }
.verlauf-notiz { color: var(--text-muted); font-size: 0.74rem; margin-top: 0.2rem; max-width: 46ch; }
.verlauf-stand { display: flex; gap: 1.6rem; text-align: right; align-items: flex-start; }
.verlauf-zahl {
  display: block; font-size: 1.85rem; font-weight: 800; line-height: 1;
  color: var(--gold); font-variant-numeric: tabular-nums;
  text-shadow: 0 0 22px rgba(212,168,80,.35);
}
.verlauf-zahl.verlauf-klein { font-size: 1.25rem; }
.verlauf-zahl.verlauf-plus { color: var(--venom); text-shadow: 0 0 22px rgba(126,201,63,.32); }
.verlauf-zahl.verlauf-minus { color: var(--danger); text-shadow: 0 0 22px rgba(209,84,76,.30); }
.verlauf-marke { display: block; margin-top: 0.3rem; font-size: 0.64rem; text-transform: uppercase; letter-spacing: .1em; color: var(--text-muted); }
.verlauf-flaeche { position: relative; width: 100%; height: 260px; }
@media (max-width: 640px) {
  .verlauf-stand { text-align: left; }
  .verlauf-flaeche { height: 180px; }
}
/* Ein pausierender Kaderchar bleibt lesbar, tritt aber zurueck — er steht in
   der Liste, zaehlt bei der Itemlevel-Regel aber nicht mit. */
tr.kader-pause > td { opacity: .55; }
tr.kader-pause:hover > td { opacity: .85; }
/* Steht noch in einer gespeicherten Aufstellung, gehört aber nicht mehr zum
   Kader. Nicht ausblenden: der leere Platz soll auffallen. */
tr.kader-weg > td { opacity: .5; text-decoration: line-through; text-decoration-color: rgba(209,84,76,.6); }
tr.kader-weg:hover > td { opacity: .8; }
/* ── M+-Knopf in der Kaderliste und sein Fenster ────────────────── */
.mplus-knopf {
  font: inherit; font-size: .74rem; font-weight: 700; cursor: pointer;
  padding: .08rem .4rem; border-radius: 3px; white-space: nowrap;
  background: rgba(154,124,242,.12); color: var(--teal);
  border: 1px solid transparent;
}
.mplus-knopf b { color: var(--gold); font-variant-numeric: tabular-nums; }
.mplus-knopf:hover { border-color: var(--teal); color: var(--text); }

.mk-backdrop {
  position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 1.2rem;
  background: rgba(6,5,16,.72);
}
.mk-backdrop[hidden] { display: none; }
.mk-dialog {
  width: min(760px, 100%); max-height: 86vh; display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--border-accent);
  border-radius: var(--radius); box-shadow: 0 18px 50px rgba(0,0,0,.5);
}
.mk-head {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: .6rem .8rem; border-bottom: 1px solid var(--border);
}
.mk-tabs { display: flex; gap: .25rem; }
.mk-tab { background: transparent; border: 1px solid var(--border); color: var(--text-muted); }
.mk-tab.is-on { background: rgba(212,168,80,.14); border-color: var(--gold); color: var(--text); }
.mk-body { padding: .6rem .8rem .8rem; overflow-y: auto; }
.mk-leer { padding: 1.6rem; text-align: center; color: var(--text-muted); font-size: .82rem; }
/* Hinweis unter „Ab +10": die Liste ist so vollstaendig, wie Raider.IO sie
   herausgibt — das gehoert dazugesagt, sonst haelt man sie fuer die Saison. */
.mk-fuss { margin: .5rem .2rem 0; padding-top: .4rem; border-top: 1px solid var(--border); line-height: 1.45; }

.mk-liste { display: flex; flex-direction: column; gap: .1rem; }
.mk-zeile {
  display: grid; grid-template-columns: 62px minmax(0,1fr) 48px 58px 52px 42px 16px;
  gap: .45rem; align-items: center; padding: .16rem .3rem; font-size: .78rem;
  border-radius: 3px; border-left: 2px solid transparent;
}
.mk-zeile:nth-child(odd) { background: rgba(255,255,255,.02); }
.mk-zeile.ist-gewertet { border-left-color: var(--venom); }
.mk-zeile.ist-verpasst { border-left-color: var(--danger); opacity: .8; }
.mk-stufe { font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; }
.mk-stufe i { font-style: normal; font-size: .6rem; color: var(--venom); letter-spacing: -1px; }
.mk-dungeon { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-zeit, .mk-punkte, .mk-tag { font-variant-numeric: tabular-nums; text-align: right; color: var(--text-muted); }
.mk-punkte { color: var(--gold); }
.mk-ab { font-variant-numeric: tabular-nums; text-align: right; font-size: .72rem; }
.mk-ab.ist-schnell { color: var(--venom); }
.mk-ab.ist-langsam { color: var(--danger); }
.mk-link a { color: var(--text-muted); text-decoration: none; }
.mk-link a:hover { color: var(--gold); }
@media (max-width: 700px) {
  .mk-zeile { grid-template-columns: 54px minmax(0,1fr) 52px 46px; }
  .mk-zeit, .mk-tag, .mk-link { display: none; }
}

/* ── Gruppiertes Menü ──────────────────────────────────────────────
   Elf Einträge nebeneinander sind eine Liste, in der man sucht. Gebündelt
   nach der Frage, mit der man kommt. Der Gruppenkopf ist selbst ein Link:
   wer weiß, wo er hinwill, klickt einmal. */
.nav-gruppe { position: relative; }
.nav-kopf { display: inline-flex; align-items: center; gap: .2rem; }
.nav-pfeil { font-size: .58rem; opacity: .5; transition: transform .12s, opacity .12s; }
.nav-gruppe:hover .nav-pfeil,
.nav-gruppe:focus-within .nav-pfeil { opacity: 1; transform: translateY(1px); }
.nav-gruppe.active > .nav-kopf { color: var(--accent); }

.nav-klapp {
  position: absolute; top: 100%; left: 0; z-index: 50;
  min-width: 250px; padding: .3rem; margin-top: .25rem;
  display: flex; flex-direction: column; gap: .1rem;
  background: var(--bg-card); border: 1px solid var(--border-accent);
  border-radius: var(--radius); box-shadow: 0 14px 34px rgba(0,0,0,.45);
  /* Nicht display:none — sonst gibt es keinen Übergang und der Tastaturfokus
     springt in ein Element, das nie sichtbar war. */
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .12s ease, transform .12s ease, visibility .12s;
}
.nav-gruppe:hover > .nav-klapp,
.nav-gruppe:focus-within > .nav-klapp {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav-eintrag {
  display: block; padding: .35rem .5rem; border-radius: 4px;
  text-decoration: none; color: var(--text); line-height: 1.25;
}
.nav-eintrag:hover, .nav-eintrag:focus-visible {
  background: rgba(212,168,80,.10); outline: none;
}
.nav-eintrag-name { display: block; font-size: .82rem; font-weight: 600; }
.nav-eintrag-text { display: block; font-size: .7rem; color: var(--text-muted); }

/* Auf schmalen Schirmen ist das Menü ohnehin ausgeklappt — dort wird aus dem
   Aufklappen eine Einrückung, sonst müsste man zweimal tippen. */
@media (max-width: 900px) {
  .nav-gruppe { width: 100%; }
  .nav-pfeil { display: none; }
  .nav-klapp {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; margin: 0 0 .3rem .7rem; padding: 0;
    background: transparent; border: 0; box-shadow: none;
    border-left: 1px solid var(--border); border-radius: 0; padding-left: .5rem;
  }
  .nav-eintrag-text { display: none; }
}

.gd-leiste { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .6rem; }
.gd-marke { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); font-weight: 700; }
.gd-knopf {
  font: inherit; font-size: .8rem; padding: .22rem .7rem; cursor: pointer;
  text-decoration: none; display: inline-block;
  background: transparent; border: 1px solid var(--border); border-radius: 3px;
  color: var(--text-muted);
}
.gd-knopf:hover { color: var(--text); border-color: var(--border-accent); }
.gd-knopf.is-on { background: rgba(212,168,80,.14); border-color: var(--gold); color: var(--gold); }
.gd-wo { margin-left: auto; }

/* ── Aussenlinks je Charakter ──────────────────────────────────── */
.links-knopf {
  font: inherit; font-size: .74rem; cursor: pointer; margin-left: .2rem;
  padding: .08rem .32rem; border-radius: 3px; line-height: 1;
  background: rgba(255,255,255,.04); color: var(--text-muted);
  border: 1px solid rgba(255,255,255,.09);
}
.links-knopf:hover { border-color: var(--gold); color: var(--gold); }
.lk-liste { display: flex; flex-direction: column; gap: .2rem; }
.lk-zeile {
  display: grid; grid-template-columns: 132px 1fr 14px; gap: .5rem; align-items: baseline;
  padding: .4rem .5rem; border-radius: 4px; text-decoration: none; color: var(--text);
  background: var(--bg-card2); border: 1px solid var(--border);
}
.lk-zeile:hover { border-color: var(--border-accent); background: rgba(212,168,80,.07); }
.lk-titel { font-weight: 700; font-size: .82rem; }
.lk-hinweis { color: var(--text-muted); font-size: .72rem; }
.lk-pfeil { color: var(--text-muted); font-size: .78rem; }
.lk-zeile.ist-offizier { border-color: rgba(212,168,80,.28); }
.lk-bosse { display: flex; gap: .2rem; flex-wrap: wrap; padding: .1rem .5rem .3rem; }
.lk-boss {
  font-size: .66rem; padding: .05rem .3rem; border-radius: 3px; text-decoration: none;
  background: rgba(255,255,255,.04); color: var(--text-muted); border: 1px solid transparent;
}
.lk-boss:hover { border-color: var(--gold); color: var(--gold); }
.lk-boss.ist-gelegt { opacity: .55; }
.lk-boss.ist-dran { background: rgba(212,168,80,.16); color: var(--gold); }

/* ── Mythisch+ der Woche ───────────────────────────────────────── */
.mplus-kopf { display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: .8rem; }
.mplus-liste { display: flex; flex-direction: column; gap: .12rem; }
.mplus-zeile {
  display: grid; grid-template-columns: 130px 26px 70px 42px minmax(0, 1fr);
  gap: .5rem; align-items: center; padding: .12rem 0; font-size: .78rem;
}
.mplus-zeile.ist-leer { opacity: .5; }
.mplus-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.mplus-zahl { text-align: right; font-variant-numeric: tabular-nums; color: var(--text); font-weight: 700; }
.mplus-bar { background: rgba(255,255,255,.05); height: 7px; border-radius: 3px; overflow: hidden; }
.mplus-bar i { display: block; height: 100%; background: var(--teal); opacity: .75; }
.mplus-key { font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 700; text-align: right; }
.mplus-dungeons { display: flex; gap: .22rem; flex-wrap: wrap; overflow: hidden; }
.mplus-chip {
  padding: .02rem .28rem; border-radius: 3px; font-size: .64rem; white-space: nowrap;
  border: 1px solid transparent;
}
.mplus-chip b { font-variant-numeric: tabular-nums; }
.mplus-chip.ist-gewertet { background: rgba(126,201,63,.12); color: var(--venom); }
.mplus-chip.ist-verpasst { background: rgba(255,255,255,.04); color: var(--text-muted); border-color: rgba(255,255,255,.09); }
@media (max-width: 820px) {
  .mplus-zeile { grid-template-columns: 110px 24px 1fr 38px; }
  .mplus-dungeons { display: none; }
}

.pause-badge { margin-left: .4rem; padding: .05rem .35rem; border-radius: 3px; font-size: .62rem;
  text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  background: rgba(160,140,240,.14); color: var(--teal); vertical-align: middle; }

.ilvl-warn  { background: rgba(239,68,68,.12); color: var(--danger); cursor: help; position: relative; }
.ilvl-warn::after { content: attr(title); display: none; position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); white-space: nowrap; background: #1e1e30; border: 1px solid var(--border); border-radius: 4px; padding: 0.25rem 0.5rem; font-size: 0.72rem; font-weight: 400; color: var(--text); z-index: 10; }
.ilvl-warn:hover::after { display: block; }
.rio-badge  { background: rgba(129,140,248,.1); color: var(--accent); padding: 0.1rem 0.45rem; border-radius: 3px; font-weight: 700; font-size: 0.78rem; }

/* ── Class colors ────────────────────────── */
.class-deathknight { color: #C41E3A !important; }
.class-demonhunter  { color: #A330C9 !important; }
.class-druid        { color: #FF7C0A !important; }
.class-evoker       { color: #33937F !important; }
.class-hunter       { color: #AAD372 !important; }
.class-mage         { color: #3FC7EB !important; }
.class-monk         { color: #00FF98 !important; }
.class-paladin      { color: #F48CBA !important; }
.class-priest       { color: #aaa !important; }
.class-rogue        { color: #FFF468 !important; }
.class-shaman       { color: #0070DD !important; }
.class-warlock      { color: #8788EE !important; }
.class-warrior      { color: #C69B3A !important; }

.text-muted { color: var(--text-muted); }
code { background: rgba(255,255,255,.07); padding: 0.1rem 0.4rem; border-radius: 4px; font-size: 0.85em; }

/* ══════════════════════════════════════════════════════════
   View-as preview banner
   ══════════════════════════════════════════════════════════ */
.viewas-banner {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  background: linear-gradient(90deg, #f59e0b, #f97316);
  color: #111; font-size: 0.8rem; font-weight: 600;
  padding: 0.4rem 1rem;
}
.viewas-banner strong { text-transform: uppercase; letter-spacing: .04em; }

/* ══════════════════════════════════════════════════════════
   Tabs
   ══════════════════════════════════════════════════════════ */
.tabs {
  display: flex; gap: 0.25rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--border); margin-bottom: 1rem;
}
.tab {
  padding: 0.45rem 0.85rem; font-size: 0.8rem; font-weight: 600;
  color: var(--text-muted); border-bottom: 2px solid transparent;
  cursor: pointer; background: none; border-top: none;
  border-left: none; border-right: none;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab-panel { display: none; }
.tabs.is-versteckt { display: none; }
.tab-panel.active { display: block; }

/* ══════════════════════════════════════════════════════════
   Compact raid detail
   ══════════════════════════════════════════════════════════ */
.raid-head {
  display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.raid-head h2 { font-size: 1rem; font-weight: 700; }
.raid-meta { font-size: 0.75rem; color: var(--text-muted); }
.raid-meta b { color: var(--text); font-weight: 600; }

/* Slot summary strip */
.slot-strip {
  display: flex; gap: 0.4rem; flex-wrap: wrap;
  margin-bottom: 0.6rem;
}
.slot-pill {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.15rem 0.6rem; font-size: 0.72rem;
}
.slot-pill.full { border-color: var(--success); color: var(--success); }
.slot-pill b { font-variant-numeric: tabular-nums; }

/* Collapsible signup panel — deliberately loud so it is not missed */
.signup-toggle {
  width: 100%; display: flex; align-items: center; gap: 0.5rem;
  background: linear-gradient(90deg, #ea580c, #dc2626);
  color: #fff; border: none; border-radius: 6px;
  padding: 0.5rem 0.85rem; font-size: 0.84rem; font-weight: 700;
  cursor: pointer; letter-spacing: .01em;
}
.signup-toggle:hover { filter: brightness(1.08); }
.signup-toggle .chev { margin-left: auto; transition: transform .18s; }
.signup-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.signup-toggle .mystatus {
  background: rgba(0,0,0,.28); border-radius: 999px;
  padding: 0.05rem 0.5rem; font-size: 0.72rem; font-weight: 600;
}
.signup-body {
  border: 1px solid #dc2626; border-top: none;
  border-radius: 0 0 6px 6px; padding: 0.75rem 0.85rem;
  background: var(--bg-card);
}
.signup-body[hidden] { display: none; }

/* „Warum?" und „ab wann?" — zwei Felder, die nur bei „Später" und
   „Abwesend" dastehen. Sie hängen am hidden-Attribut. Die Regel ist Vorsorge
   wie bei .signup-body darüber: käme hier später eine display-Angabe hinzu,
   schlüge sie das Attribut, und der Block stünde immer offen. */
#grund-block[hidden], #zeit-zeile[hidden] { display: none; }
#grund-block input {
  width: 100%; background: var(--bg); border: 1px solid var(--border);
  border-radius: 4px; color: var(--text); padding: 0.3rem 0.45rem; font-size: 0.8rem;
}
#grund-block input:focus { outline: none; border-color: var(--accent); }

/* Tap targets for role/status choice */
.pick-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.3rem; }
@media (max-width: 560px) { .pick-grid { grid-template-columns: repeat(2, 1fr); } }
.pick {
  display: flex; align-items: center; justify-content: center; gap: 0.35rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 5px;
  padding: 0.35rem 0.4rem; font-size: 0.76rem; font-weight: 600;
  cursor: pointer; user-select: none;
}
.pick:has(input:checked) { border-color: var(--accent); background: rgba(154,124,242,.15); }
.pick.checked { border-color: var(--accent); background: rgba(154,124,242,.15); }

/* ══════════════════════════════════════════════════════════
   Lineup board (drag & drop)
   ══════════════════════════════════════════════════════════ */
.board {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem; margin-bottom: 0.5rem;
}
@media (max-width: 900px) { .board { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .board { grid-template-columns: 1fr; } }

.bucket {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 6px; padding: 0.35rem;
  min-height: 60px; transition: border-color .12s, background .12s;
}
.bucket.dragover { border-color: var(--accent); background: rgba(154,124,242,.09); }
.bucket-head {
  display: flex; align-items: center; gap: 0.3rem;
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted);
  padding: 0.1rem 0.2rem 0.3rem;
}
.bucket-head .cnt { margin-left: auto; font-variant-numeric: tabular-nums; }
.bucket.is-full .bucket-head .cnt { color: var(--success); }
.bucket.bench   { border-style: dashed; }
.bucket.declined, .bucket.abwesend { border-style: dashed; opacity: .85; }

/* Zweite Reihe unter der Aufstellung: Ohne Rolle, Bank, Abgelehnt,
   Abgemeldet, Später, Unklar. Sechs schmale Kästen in einer Reihe — sie sind
   Nebensache und dürfen die Aufstellung nicht aus dem Bild schieben. Eigene
   Klasse statt eines style-Attributs an der Reihe: das Attribut schlüge die
   Umbrüche.

   „Ohne Rolle" ist der einzige davon, in dem jemand zugesagt hat — er steht
   deshalb vorn und bleibt durchgezogen, während die übrigen gestrichelt sind. */
.bucket.ohnerolle { border-color: var(--gold); }
/* Sechs Spalten brauchen Platz: ein Kaertchen ist mit Spezialisierung und
   Itemlevel rund 160 px breit, sechs davon also gut 1050 px. Auf einem halben
   Bildschirm liefe die Reihe sonst rechts aus dem Bild. */
.board.nebenreihe { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1100px) { .board.nebenreihe { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .board.nebenreihe { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.chip {
  display: flex; align-items: center; gap: 0.35rem;
  background: var(--bg); border: 1px solid var(--border);
  border-left-width: 3px; border-radius: 4px;
  padding: 0.22rem 0.4rem; margin-bottom: 0.2rem;
  font-size: 0.75rem; cursor: grab;
}
.chip:active { cursor: grabbing; }
.chip.dragging { opacity: .4; }
.chip .cname { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip .cilvl {
  margin-left: auto; font-size: 0.68rem; color: var(--gold);
  font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.chip .crole { font-size: 0.66rem; color: var(--text-muted); flex-shrink: 0; }

/* Zweite Zeile im Kärtchen: „ab 20:30 · Grund".
   Der Zusatz braucht eine eigene Zeile — neben Name, Spezialisierung und
   Itemlevel ist in einem Kärtchen von rund 160 px kein Platz. Umbrechen darf
   nur, wer auch etwas zu zeigen hat: mit `flex-wrap` an jedem .chip würde in
   den Rollenspalten ein langer Name das Itemlevel in eine zweite Zeile
   schieben, statt gekürzt zu werden. */
.chip.mitgrund { flex-wrap: wrap; }
/* Und auch hier soll der Name kürzen statt umbrechen: ohne min-width bleibt ein
   Flex-Element mindestens so breit wie sein längstes Wort, und ein langer Name
   schöbe das Itemlevel in eine eigene Zeile — das Kärtchen wäre dreizeilig.
   Nur min-width, kein flex-grow: sonst frisst der Name den freien Platz, und
   `margin-left: auto` am Itemlevel hätte nichts mehr zu verteilen — es stände
   in Kärtchen mit Grund anders als in denen ohne. */
.chip.mitgrund .cname { min-width: 0; }
.chip .czeile {
  flex: 0 0 100%; display: flex; align-items: baseline; gap: 0.25rem;
  font-size: 0.66rem; color: var(--text-muted); overflow: hidden;
}
.chip .czeit { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.chip .cgrund { font-style: italic; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip .czeit + .cgrund::before { content: '\00b7 '; }

.chip.empty-hint {
  border: none; background: none; color: var(--text-muted);
  font-size: 0.72rem; cursor: default; justify-content: center;
}

/* Player pool below the board */
.pool-wrap {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 6px; padding: 0.5rem;
}
.pool-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.25rem;
}

/* Class colour strips on chips */
.c-deathknight { border-left-color: #C41E3A; }
.c-demonhunter { border-left-color: #A330C9; }
.c-druid       { border-left-color: #FF7C0A; }
.c-evoker      { border-left-color: #33937F; }
.c-hunter      { border-left-color: #AAD372; }
.c-mage        { border-left-color: #3FC7EB; }
.c-monk        { border-left-color: #00FF98; }
.c-paladin     { border-left-color: #F48CBA; }
.c-priest      { border-left-color: #FFFFFF; }
.c-rogue       { border-left-color: #FFF468; }
.c-shaman      { border-left-color: #0070DD; }
.c-warlock     { border-left-color: #8788EE; }
.c-warrior     { border-left-color: #C69B3A; }

/* ══════════════════════════════════════════════════════════
   Gear overview
   ══════════════════════════════════════════════════════════ */
.gear-layout { display: grid; grid-template-columns: 230px 1fr; gap: 0.75rem; }
@media (max-width: 780px) { .gear-layout { grid-template-columns: 1fr; } }

.gear-list { max-height: 640px; overflow-y: auto; }
.gear-person {
  display: flex; align-items: center; gap: 0.45rem;
  padding: 0.35rem 0.5rem; border-radius: 5px; cursor: pointer;
  border: 1px solid transparent; border-left: 3px solid var(--border);
  font-size: 0.78rem;
}
.gear-person:hover { background: rgba(255,255,255,.04); }
.gear-person.active { background: rgba(154,124,242,.14); border-color: var(--border-accent); }
.gear-person .gp-name { font-weight: 600; }
.gear-person .gp-ilvl { margin-left: auto; color: var(--gold); font-variant-numeric: tabular-nums; }

.slot-row {
  display: grid; grid-template-columns: 96px 1fr auto;
  gap: 0.5rem; align-items: center;
  padding: 0.3rem 0.5rem; border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
}
.slot-row:last-child { border-bottom: none; }
.slot-row .sl-slot { color: var(--text-muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: .03em; }
.slot-row .sl-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slot-row .sl-ilvl { font-variant-numeric: tabular-nums; font-weight: 700; }
.slot-row.missing .sl-name { color: var(--danger); }
.slot-row .sl-sub { display: block; font-size: 0.68rem; color: var(--text-muted); }

.q-legendary { color: #ff8000; }
.q-epic      { color: #a335ee; }
.q-rare      { color: #0070dd; }
.q-uncommon  { color: #1eff00; }
.q-common    { color: #ffffff; }

/* ══════════════════════════════════════════════════════════
   Boss guides
   ══════════════════════════════════════════════════════════ */
.boss-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0.6rem; }
.embed-16x9 { position: relative; width: 100%; padding-top: 56.25%; border-radius: 6px; overflow: hidden; background: #000; }
.embed-16x9 iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ── Guide-Videos: klein in der Übersicht, groß auf Wunsch ──────────
   Mehrere Guides je Boss sind der Normalfall. In voller Breite schiebt schon
   der zweite die Kommentare und Raidpläne aus dem Bild — deshalb Kacheln in
   Vorschaugröße und eine Vergrößerung für das, was gerade angesehen wird. */
/* Doppelte Vorschaugröße: 240 px war zwar aufgeräumt, aber zum Hineinsehen zu
   klein — bei einem Guide erkennt man auf einer Briefmarke nicht, ob es der
   richtige ist. Zwei passen weiterhin nebeneinander, sofern die Spalte es
   hergibt; darunter bricht das Raster von selbst auf eines um. */
/* 680 statt 480: 200 px mehr als die Raidplan-Kachel daneben. Ein Video wird
   angeschaut, ein Raidplan überflogen. */
.vid-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(680px, 1fr));
  gap: 0.7rem; margin-bottom: 0.7rem;
}
@media (max-width: 560px) { .vid-grid { grid-template-columns: minmax(0, 1fr); } }
.vid-card { min-width: 0; }
.vid-foot { display: flex; align-items: center; gap: 0.3rem; font-size: 0.76rem; padding: 0.25rem 0 0; }
.vid-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vid-by { font-size: 0.7rem; }
.vid-zoom { font-size: 0.85rem; line-height: 1; }

/*
 * Vergrößern heißt hier: dieselbe Kachel wird per CSS nach vorn geholt — sie
 * wird *nicht* in ein Modal umgehängt. Ein iframe, das im DOM verschoben wird,
 * lädt neu: das Video begänne von vorn und die gezählte Sehdauer wäre dahin.
 * So läuft es einfach weiter, nur größer.
 */
.vid-backdrop {
  position: fixed; inset: 0; z-index: 1000; display: none;
  background: rgba(0, 0, 0, .82);
}
body.vid-zoomed .vid-backdrop { display: block; }
.vid-card.zoomed {
  position: fixed; z-index: 1001; top: 50%; left: 50%; transform: translate(-50%, -50%);
  /* Breite so begrenzen, dass 16:9 auch in der Höhe passt — sonst rutschen
     Titelzeile und Knöpfe unter den Bildschirmrand. */
  width: min(94vw, 1500px, (88vh - 3.5rem) * 16 / 9);
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 10px; padding: 0.5rem; box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
}
.vid-card.zoomed .vid-title { font-size: 0.92rem; font-weight: 700; }
/* Platzhalter hält die Lücke im Raster, solange die Kachel vorn schwebt —
   sonst springt die Seite beim Vergrößern und beim Schließen. */
.vid-hole { visibility: hidden; }
/* Im echten Vollbild traegt die Kachel selbst den Bildschirm: die feste
   Breite von oben wuerde sie sonst mittig klein stehen lassen. */
.vid-card.zoomed:fullscreen {
  position: static; transform: none; width: 100vw; height: 100vh;
  max-width: none; border: none; border-radius: 0; padding: 0;
  background: #000; display: flex; flex-direction: column; justify-content: center;
}
.vid-card.zoomed:fullscreen .embed-16x9 { width: min(100vw, calc((100vh - 3rem) * 16 / 9)); margin: 0 auto; }
.vid-card.zoomed:fullscreen .vid-foot { padding: .3rem .6rem; }
.vid-card.zoomed:fullscreen .vid-by { display: none; }

.link-row { display: flex; align-items: center; gap: 0.4rem; font-size: 0.78rem; padding: 0.2rem 0; }
.comment {
  border-left: 2px solid var(--border); padding: 0.3rem 0 0.3rem 0.6rem;
  margin-bottom: 0.4rem; font-size: 0.8rem;
}
.comment .cm-meta { font-size: 0.7rem; color: var(--text-muted); }

/* ══════════════════════════════════════════════════════════
   Wipe analysis
   ══════════════════════════════════════════════════════════ */
.death-row {
  display: grid; grid-template-columns: 54px 1fr 1fr;
  gap: 0.5rem; padding: 0.25rem 0.5rem;
  border-bottom: 1px solid var(--border); font-size: 0.76rem;
}
.death-row .dt { font-variant-numeric: tabular-nums; color: var(--danger); font-weight: 700; }
.hp-bar { height: 6px; border-radius: 3px; background: var(--bg); overflow: hidden; }
.hp-bar > div { height: 100%; background: linear-gradient(90deg, var(--danger), var(--gold)); }

/* Status chip, used by the gear overview, the dashboard and the activity table */
.gp-chip {
  display: inline-block; font-size: 0.66rem; font-weight: 700;
  border-radius: 3px; padding: 0 0.3rem;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
}
.gp-chip.ok   { color: var(--success); border-color: rgba(79,179,92,.5);   background: rgba(79,179,92,.12); }
.gp-chip.warn { color: var(--warn);    border-color: rgba(217,164,65,.5);  background: rgba(217,164,65,.12); }
.gp-chip.bad  { color: var(--danger);  border-color: rgba(209,84,76,.5);   background: rgba(209,84,76,.14); }

/* Small helpers */
.muted-sm { font-size: 0.74rem; color: var(--text-muted); }
.empty-state { padding: 1.5rem; text-align: center; color: var(--text-muted); font-size: 0.82rem; }
.inline-form { display: flex; gap: 0.35rem; flex-wrap: wrap; align-items: center; }
.inline-form input, .inline-form select, .inline-form textarea {
  background: var(--bg); border: 1px solid var(--border); border-radius: 4px;
  color: var(--text); padding: 0.25rem 0.45rem; font-size: 0.78rem; font-family: inherit;
}

/* ══════════════════════════════════════════════════════════
   Compact label/input rows — shared by admin and season forms
   ══════════════════════════════════════════════════════════ */
.field-row {
  display: flex; align-items: center; gap: 0.5rem;
  margin-bottom: 0.35rem; flex-wrap: wrap;
}
.field-row > label {
  flex: 0 0 78px; font-size: 0.72rem; color: var(--text-muted);
  font-weight: 600; text-align: right;
}
.field-row input[type=text], .field-row input[type=number],
.field-row input[type=time], .field-row select {
  background: var(--bg); border: 1px solid var(--border); border-radius: 4px;
  color: var(--text); padding: 0.22rem 0.42rem; font-size: 0.78rem;
  font-family: inherit; min-width: 0;
}
/* A lone control fills the row; several share it */
.field-row > input:only-of-type, .field-row > select:only-of-type { flex: 1; }

/* ══════════════════════════════════════════════════════════
   Lineup builder and coverage
   ══════════════════════════════════════════════════════════ */
.row-keep > td { background: rgba(152, 251, 152, .10); }
.row-keep > td:first-child { box-shadow: inset 3px 0 0 #98fb98; }

.lineup-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; align-items: start; }
@media (max-width: 820px) { .lineup-cols { grid-template-columns: 1fr; } }

.lu-row {
  display: grid; grid-template-columns: 1fr auto 34px 22px;
  gap: 0.4rem; align-items: center;
  background: var(--bg); border: 1px solid var(--border);
  border-left-width: 3px; border-radius: 4px;
  padding: 0.16rem 0.4rem; margin-bottom: 0.15rem; font-size: 0.76rem;
}
.lu-row .lu-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lu-row .lu-ilvl { color: var(--gold); font-variant-numeric: tabular-nums; text-align: right; }
.lu-row button { padding: 0 0.25rem; }

.cov-wrap {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 5px; padding: 0.5rem 0.6rem;
}
.cov-head { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; margin-bottom: 0.4rem; }
.cov-badge {
  font-size: 0.66rem; font-weight: 700; border-radius: 999px;
  padding: 0.05rem 0.45rem; text-transform: uppercase; letter-spacing: .03em;
}
.cov-badge.bad  { background: rgba(239,68,68,.18);  color: var(--danger); }
.cov-badge.warn { background: rgba(200,155,60,.18); color: var(--gold); }
.cov-badge.good { background: rgba(34,197,94,.18);  color: var(--success); }

.cov-roles, .cov-grid { display: flex; flex-wrap: wrap; gap: 0.2rem; margin-bottom: 0.3rem; }
.cov-chip {
  font-size: 0.7rem; border-radius: 3px; padding: 0.08rem 0.4rem;
  border: 1px solid var(--border); background: var(--bg-card);
  color: var(--text-muted); cursor: help; white-space: nowrap;
}
.cov-chip b { color: var(--text); font-variant-numeric: tabular-nums; }
.cov-chip.ok      { border-color: rgba(34,197,94,.45);  color: var(--success); }
.cov-chip.thin    { border-color: var(--gold);          color: var(--gold); }
.cov-chip.missing { border-color: var(--danger);        color: var(--danger); background: rgba(239,68,68,.10); }
.cov-chip.over    { border-color: rgba(129,140,248,.5); color: var(--accent); }

.cov-warn {
  margin-top: 0.35rem; padding-top: 0.35rem;
  border-top: 1px solid var(--border);
  font-size: 0.74rem; line-height: 1.6; color: var(--text-muted);
}
.cov-warn strong { color: var(--danger); }

/* ── Kader: Zusammensetzung nach Rolle und Klasse ──
   Die Zahl steht immer in Textfarbe, die Klassenfarbe trägt Rahmen und
   Fläche. Dunkle Klassenfarben (Todesritter, Schamane) wären als Schrift auf
   dem dunklen Grund kaum zu lesen. */
.kz {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.4rem;
  padding: 0.6rem 1rem; margin-bottom: 0.6rem;
}
.kz-titel {
  flex-basis: 100%; font-size: 0.72rem; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .05em;
}
.kz-rollen, .kz-klassen { display: flex; flex-wrap: wrap; gap: 0.35rem; min-width: 0; }
.kz-rolle, .kz-klasse { font: inherit; line-height: 1; }
.kz-rolle {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.35rem 0.7rem; border-radius: var(--radius); cursor: pointer;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.kz-rolle .kz-zeichen { font-size: 0.95rem; }
.kz-rolle .kz-zahl { font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.kz-rolle .kz-name {
  font-size: 0.68rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em;
}
.kz-rolle.ist-leer .kz-zahl { color: var(--danger); }
.kz-rolle.ist-ohne { border-color: var(--warn); }
.kz-rolle.ist-ohne .kz-zahl { color: var(--warn); }
.kz-rolle:hover { border-color: var(--border-accent); }

.kz-klasse {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.15rem 0.55rem 0.15rem 0.15rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border);
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  background: color-mix(in srgb, currentColor 12%, transparent);
}
/* Die Klassenfarbe hinter dem Symbol: lädt das Bild nicht, bleibt ein Punkt
   in der richtigen Farbe, und der Name steht weiter im Tooltip. */
.kz-klasse img {
  display: block; width: 22px; height: 22px; border-radius: 50%; background: currentColor;
}
.kz-klasse .kz-zahl {
  min-width: 0.75em; text-align: center; color: var(--text);
  font-size: 0.82rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.kz-klasse:hover { background: color-mix(in srgb, currentColor 22%, transparent); }
.kz-klasse.ist-leer { opacity: .38; cursor: default; }
.kz-klasse.ist-leer:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.kz-klasse.ist-leer img { filter: grayscale(1); }
.kz-klasse.ist-ohne { color: var(--warn); cursor: default; }
.kz-ohne-zeichen {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  border: 1px dashed currentColor; font-weight: 700; font-size: 0.75rem;
}

.kz-rolle[aria-pressed="true"], .kz-klasse[aria-pressed="true"] {
  border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold);
}
.kz-rolle[aria-pressed="true"] { background: rgba(212,168,80,.14); }
.kz-rolle:focus-visible, .kz-klasse:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.kz-fuss { flex-basis: 100%; font-size: 0.72rem; color: var(--text-muted); }
/* Schmal: Rollen als gleich breites Raster statt unterschiedlich langer Reihen */
@media (max-width: 560px) {
  .kz-rollen { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
}

/* ══════════════════════════════════════════════════════════
   Sortable tables
   ══════════════════════════════════════════════════════════ */
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.sortable::after { content: ' ⇅'; opacity: .3; font-size: 0.8em; }
th.sortable.asc::after  { content: ' ↑'; opacity: 1; }
th.sortable.desc::after { content: ' ↓'; opacity: 1; }

/* M+ runs share the raid calendar but read differently */
.cal-ev.st-mplus { background: var(--teal); }
.cal-key { display:inline-block; width:9px; height:9px; border-radius:2px; vertical-align:middle; margin-right:3px; }
.badge-mplus { background: rgba(124,58,237,.18); color: #a78bfa; }
.upcoming-item.is-mplus .up-time { color: #a78bfa; }


/* ── Bossreiter ziehen ───────────────────────────────────────────
   Kein Sortiermodus: die Reiter sind fuer Offiziere immer ziehbar.

   Die Pfeile standen frueher auf `width: 0` und klappten beim Ueberfahren
   auf. Der Reiter wurde dadurch unter dem Zeiger breiter und beim Weggehen
   wieder schmaler - die ganze Leiste rutschte bei jeder Mausbewegung. Jetzt
   haben sie ihren Platz dauerhaft und werden nur heller: Helligkeit aendert
   nichts am Layout, Breite schon. Zurueckhaltend bleiben sie trotzdem, denn
   im Alltag ist die Leiste eine Navigation und kein Formular. */
.boss-tabs.bt-ziehbar .boss-tab { cursor: grab; }
.boss-tabs.bt-ziehbar .boss-tab:active { cursor: grabbing; }
.bt-pfeil {
  background: none; border: none; cursor: pointer; padding: 0 .15rem;
  color: var(--text-muted); font-size: .7rem; line-height: 1;
  opacity: .3; transition: opacity .12s, color .12s;
}
.boss-tabs.bt-ziehbar .boss-tab:hover .bt-pfeil,
.boss-tabs.bt-ziehbar .boss-tab:focus-within .bt-pfeil { opacity: .75; }
.bt-pfeil:hover { color: var(--gold); opacity: 1; }

.boss-tab.bt-zieht { opacity: .4; }
/* Waehrend eines Zuges nicht die Zielreiter aufleuchten lassen — das liest
   sich sonst wie ein Klickziel. */
.boss-tabs.bt-zieht-gerade .boss-tab:hover { background: inherit; }
.boss-tabs.bt-speichert { opacity: .75; }
.bt-stand { align-self: center; margin-left: .4rem; }

/* Aufnahmeklient zum Herunterladen, ueber dem Hochladefeld der Videos. */
.rec-dl {
  display: flex; align-items: center; gap: 1rem;
  flex-wrap: wrap; margin-bottom: .75rem;
}
.rec-dl-text { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-width: 220px; }

/* Befehle zum Kopieren auf der Einrichtungsseite. Der PowerShell-Aufruf ist
   lang; er darf umbrechen, aber die Seite nicht seitlich schieben. */
.befehl { display: flex; align-items: flex-start; gap: .5rem; margin: .4rem 0 .9rem; }
.befehl pre {
  flex: 1; margin: 0; padding: .6rem .7rem; border-radius: 6px;
  background: rgba(0,0,0,.28); border: 1px solid rgba(255,255,255,.08);
  font-size: .78rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere;
}
.befehl button { flex: none; }

/* Einwurffeld fuer Ausgaben vom Windows-Rechner. */
.einwurf {
  width: 100%; margin: .3rem 0 .5rem; padding: .6rem .7rem; border-radius: 6px;
  background: rgba(0,0,0,.28); border: 1px solid rgba(255,255,255,.08);
  color: inherit; font-family: ui-monospace, Consolas, monospace;
  font-size: .78rem; line-height: 1.5; resize: vertical;
}
.einwurf-zeile { display: flex; align-items: center; gap: .7rem; margin-bottom: .9rem; }


/* ── Aufstellung je Boss ─────────────────────────────────────────
   Die Rollenfarbe steht als schmaler Strich vor dem Namen: in einer Liste von
   zwanzig Leuten sieht man so auf einen Blick, ob die Verteilung stimmt. */
.lu-kopf { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.lu-zahl { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Ist gegen Soll in der ueblichen Kurzform „2-4-14": die eine Zeile, die eine
   Aufstellung beantwortet, bevor man Namen liest. */
.lu-kurz { font-variant-numeric: tabular-nums; white-space: nowrap; }
.lu-kurz b { font-weight: 800; }
.lu-kurz.weicht-ab b { color: var(--gold); }
.lu-hinweise { display: flex; flex-wrap: wrap; gap: .25rem; margin: .3rem 0; }
.lu-hinweise:empty { display: none; }
.lu-hinweis {
  font-size: .68rem; padding: .08rem .35rem; border-radius: 3px;
  background: rgba(212,168,80,.12); border: 1px solid rgba(212,168,80,.35); color: var(--gold);
}
.lu-liste { display: flex; flex-direction: column; gap: 1px; }
.lu-zeile {
  display: grid; grid-template-columns: 3px 1fr auto auto auto;
  align-items: center; gap: .4rem; padding: .18rem .25rem; font-size: .78rem; border-radius: 3px;
}
.lu-zeile:hover { background: var(--bg); }
.lu-rolle { width: 3px; height: 1.1em; border-radius: 2px; background: var(--border); }
.lu-tank { background: #4a90d9; }
.lu-healer { background: #4caf72; }
.lu-melee { background: #d98b4a; }
.lu-ranged { background: #a97ad9; }
.lu-offen { background: var(--danger); }
.lu-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lu-ilvl { font-variant-numeric: tabular-nums; }
.lu-leer { padding: .3rem .25rem; }
/* Auswechselspieler stehen unter der Aufstellung, nicht mittendrin: sie
   gehoeren zum Boss, spielen ihn aber erst einmal nicht. */
.lu-ersatz { margin-top: .5rem; }
.lu-ersatz:empty { display: none; }
.lu-fuss { margin-top: .5rem; }

/* ── Aufstellung bauen ──
   Zwei Felder nebeneinander: was nicht im Raid steht, steht auf der Bank.
   Eine dritte Liste gibt es nicht, also kann man auch nichts vergessen. */
.lu-modal {
  position: fixed; inset: 0; z-index: 1100; background: rgba(0,0,0,.72);
  display: flex; align-items: center; justify-content: center; padding: 1.5rem 1rem;
}
.lu-modal[hidden] { display: none; }
.lu-fenster {
  width: min(1400px, 100%); max-height: 88vh; display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 24px 60px rgba(0,0,0,.6);
}
.lu-mkopf {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: .6rem .8rem; border-bottom: 1px solid var(--border);
}
.lu-mkopf .btn { margin-left: auto; }
.lu-mhinweise { display: flex; flex-wrap: wrap; gap: .25rem; padding: .4rem .8rem 0; }
.lu-mhinweise:empty { display: none; }
/* Vier Spalten: Bank, Auswechsel, Rollen, Gruppen & Mechaniken.
   Die beiden rechten sind zwei Fragen an dieselben Leute - welche Rolle
   jemand spielt und wo er steht -, und beide will man beim Bauen sehen.
   Als Umschalter verlor man die eine jedes Mal aus den Augen. */
.lu-spalten {
  display: grid; grid-template-columns: .85fr .7fr 1.2fr 1.45fr;
  gap: .6rem; padding: .6rem .8rem; overflow: hidden;
}
/* Unter 1250 px wird aus einer Reihe ein Karree: vier Spalten waeren dort
   vier Streifen, in denen kein Name mehr ganz steht. */
@media (max-width: 1250px) {
  .lu-spalten { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .lu-spalten { grid-template-columns: 1fr; }
}
.lu-spalte {
  display: flex; flex-direction: column; min-height: 0;
  border: 1px dashed var(--border); border-radius: 8px; padding: .4rem;
}
.lu-spalte.drueber { border-color: var(--gold); background: rgba(212,168,80,.06); }
.lu-stitel {
  font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); margin-bottom: .35rem; display: flex; gap: .35rem;
}
.lu-feld { overflow-y: auto; max-height: 58vh; display: flex; flex-direction: column; gap: 1px; }
/* Jede Rolle ein eigenes Abwurffeld: nur so laesst sich jemand gezielt zum
   Tank machen. Leere Gruppen bleiben stehen - ohne sie gaebe es kein Ziel. */
.lu-rollenfeld { border-radius: 6px; padding: 1px 2px; border: 1px solid transparent; }
.lu-rollenfeld.drueber { border-color: var(--gold); background: rgba(212,168,80,.09); }

/* ── Raidgruppen ──
   Vier Gruppen wie im Spiel. Sie stehen neben den Rollen, nicht an ihrer
   Stelle: im Raid ist beides gleichzeitig wahr. */
.lu-gnummer {
  font-size: .6rem; font-weight: 800; border-radius: 3px; padding: 0 .22rem;
  border: 1px solid var(--border); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.lu-person.hat-gruppe .lu-gnummer { color: var(--accent); border-color: var(--border-accent); }

/* ── Zwei nebeneinander, dann Umbruch ──
   Gruppe 1 und 2 in einer Reihe, 3 und 4 darunter - so stehen sie im Spiel
   im Raidfenster, und so sucht man sie auch hier. Untereinander waren es
   vier Bloecke, durch die man scrollen musste. */
.lu-gitter {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .3rem;
  /* Kein `align-items: start`: damit waren die Felder einer Reihe
     unterschiedlich hoch, und neben dem kuerzeren lag toter Raum, der zum
     Raster gehoert und nicht zum Feld. Ein Zug dorthin traf kein Ziel - der
     Spieler sprang zurueck, weil nichts gesetzt wurde. */
  align-items: stretch;
}
/* Was keine Gruppe ist, nimmt die ganze Breite: „noch ohne Gruppe" ist keine
   fuenfte Gruppe und soll auch nicht wie eine aussehen. */
.lu-gitter > .lu-breit { grid-column: 1 / -1; }
/* Auf halber Spaltenbreite ist die Spezialisierung das erste, was weichen
   kann - Rolle, Name und Anmeldung stehen weiter. */
.lu-gitter .lu-spec { display: none; }
.lu-gitter[data-sicht="gruppen"] .lu-gnummer { display: none; }
.lu-gitter .lu-rollenfeld {
  border: 1px solid var(--border); border-radius: 6px; padding: .3rem;
  background: rgba(0,0,0,.12);
  /* Eine leere Gruppe muss man treffen koennen. Ohne Mindesthoehe ist sie
     zwei Zeilen hoch, und man zielt daneben. */
  min-height: 4.2rem;
}
/* „hierher ziehen" fuellt den Rest des Feldes aus, statt als schmale Zeile
   obenan zu stehen - die ganze Kachel ist das Ziel, also soll sie sich auch
   so anfuehlen. */
.lu-gitter .lu-rollenfeld .lu-keiner { display: block; padding: .5rem .3rem; }
@media (max-width: 860px) { .lu-gitter { grid-template-columns: 1fr; } }

/* ── Spezialmechaniken ──
   Die dritte Frage an eine Aufstellung: wer mitgeht, wo er steht, was er tut.
   Auf der Karte zum Nachsehen, im Fenster zum Einteilen. */
.lu-mechanik { margin-top: .5rem; }
.lu-mechanik:empty { display: none; }
.lu-mzeile {
  display: grid; grid-template-columns: minmax(80px, 30%) 1fr; gap: .4rem;
  align-items: baseline; padding: .12rem 0;
}
.lu-mname { font-size: .74rem; font-weight: 700; }
.lu-mleute { display: flex; flex-wrap: wrap; gap: .2rem .3rem; }
.lu-mchip {
  display: inline-flex; align-items: center; gap: .18rem;
  font-size: .72rem; border-radius: 3px; padding: 0 .2rem;
  border: 1px solid var(--border);
}
/* Aus der Aufstellung genommen, aber noch eingeteilt: das ist der Fall, den
   man am Raidabend finden will, nicht der, den man uebersehen soll. */
.lu-mchip.nicht-dabei { border-color: rgba(200,80,80,.5); opacity: .7; text-decoration: line-through; }
.lu-mchip .lu-zeichen { font-size: .66rem; }

/* Im Fenster stehen sie unter den Raidgruppen, nicht neben ihnen: man teilt
   sie genau den Leuten zu, die man dort gerade vor sich hat. Der Strich
   darueber trennt die beiden Fragen - wo jemand steht und was er tut. */
.lu-mechteil { margin-top: .5rem; padding-top: .45rem; border-top: 1px solid var(--border); }
.lu-mechkante { display: flex; align-items: center; gap: .5rem; margin-bottom: .35rem; }
.lu-mechmarke {
  font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); white-space: nowrap;
}
.lu-mechneu { display: flex; gap: .3rem; flex: 1; min-width: 0; }
.lu-mechneu input {
  flex: 1; min-width: 0; font: inherit; font-size: .74rem; padding: .18rem .35rem;
  background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 4px;
}
/* Solange eine Mechanik gewaehlt ist, bedeutet ein Klick auf einen Spieler
   etwas anderes als sonst. Das gehoert hingeschrieben, nicht in eine
   Rahmenfarbe. */
.lu-mechband {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  font-size: .7rem; margin-bottom: .35rem; padding: .2rem .4rem; border-radius: 4px;
  border: 1px solid var(--border-accent); background: rgba(212,168,80,.1); color: var(--text);
}
.lu-mechband .btn { margin-left: auto; }
.lu-mechkopf { display: flex; align-items: center; gap: .3rem; }
.lu-mechkopf .lu-mechtitel { flex: 1; min-width: 0; text-align: left; font: inherit;
  font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); background: none; border: none; cursor: pointer; padding: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lu-rollenfeld.gewaehlt { border-color: var(--gold); background: rgba(212,168,80,.09); }
.lu-rollenfeld.gewaehlt .lu-mechtitel { color: var(--accent); }
.lu-mechknopf {
  background: none; border: none; color: var(--text-muted); cursor: pointer;
  font: inherit; font-size: .7rem; padding: 0 .15rem; line-height: 1;
}
.lu-mechknopf:hover { color: var(--danger); }
.lu-mechhinweis { font-size: .68rem; color: var(--text-muted); margin: .1rem 0 .2rem; }
/* Wer eingeteilt ist, aber nicht mehr mitgeht - dasselbe Zeichen wie auf der
   Karte, damit man es nicht zweimal lernen muss. */
.lu-person.nicht-dabei { opacity: .6; border-color: rgba(200,80,80,.45); }
.lu-person.nicht-dabei .lu-name { text-decoration: line-through; }
.lu-mechhilfe { font-size: .68rem; color: var(--text-muted); margin-bottom: .3rem; }
.lu-person {
  display: grid; grid-template-columns: 3px 1fr auto auto; align-items: center; gap: .4rem;
  padding: .22rem .3rem; font-size: .78rem; border-radius: 4px; cursor: grab;
  background: var(--bg); border: 1px solid transparent;
}
.lu-person:hover { border-color: var(--border-accent); }
.lu-person:active { cursor: grabbing; }
.lu-person.zieht { opacity: .4; }

/* Anmeldestand: Farbe sagt genug, das Kuerzel steht fuer den Fall daneben,
   dass jemand Farben nicht unterscheidet. */
.lu-an {
  font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  padding: .05rem .3rem; border-radius: 3px; white-space: nowrap;
  border: 1px solid transparent;
}
.lu-an-confirmed { color: #4caf72; border-color: rgba(76,175,114,.45); background: rgba(76,175,114,.1); }
.lu-an-late      { color: var(--gold); border-color: rgba(212,168,80,.45); background: rgba(212,168,80,.1); }
.lu-an-absent    { color: var(--danger); border-color: rgba(200,80,80,.45); background: rgba(200,80,80,.1); }
.lu-an-unknown,
.lu-an-ohne      { color: var(--text-muted); border-color: var(--border); }
.lu-zeile { grid-template-columns: 3px 1fr auto auto auto; }
.lu-person { grid-template-columns: 3px 14px 1fr auto auto auto; }
/* Das Rollenzeichen: klein, aber sofort zu erkennen. */
.lu-zeichen { font-size: .78rem; line-height: 1; text-align: center; }
.lu-voll { color: var(--gold); font-weight: 700; }
.lu-mfuss { padding: 0 .8rem .7rem; display: flex; flex-wrap: wrap;
            align-items: center; gap: .5rem; }
.lu-mfuss > div { flex-basis: 100%; }

/* Sollaufstellung: wie der Boss gespielt wird. Vier Zahlen, kein Formular -
   leer heisst „keine Vorgabe", und dann gibt es dazu auch keine Hinweise. */
.lu-soll {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem;
  padding: .55rem .8rem; border-top: 1px solid var(--border);
}
.lu-soll-titel {
  font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); align-self: center; margin-right: .2rem;
}
.lu-soll label { display: flex; flex-direction: column; gap: .15rem; font-size: .66rem;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.lu-soll input {
  width: 3.2rem; padding: .22rem .35rem; border-radius: 4px;
  background: var(--bg); border: 1px solid var(--border); color: inherit;
  font-size: .8rem; font-variant-numeric: tabular-nums; text-align: center;
}
.lu-soll .lu-sollstand { font-size: .72rem; color: var(--text-muted); margin-left: auto; }

@media (max-width: 900px) { .lu-spalten { grid-template-columns: 1fr 1fr; } }
@media (max-width: 700px) { .lu-spalten { grid-template-columns: 1fr; } }


/* ── Testspieler ──
   Auffaellig genug, um beim Ueberfliegen der Kaderliste haengenzubleiben,
   aber nicht so laut wie eine Warnung: ein Trial ist kein Problem. */
.trial-badge {
  font-size: .62rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  padding: .05rem .32rem; border-radius: 3px; margin-left: .3rem; white-space: nowrap;
  color: #6ba7d9; border: 1px solid rgba(107,167,217,.45); background: rgba(107,167,217,.1);
}
.trial-badge.ist-bald { color: var(--gold); border-color: rgba(212,168,80,.5); background: rgba(212,168,80,.1); }
.trial-badge.ist-weg  { color: var(--danger); border-color: rgba(200,80,80,.5); background: rgba(200,80,80,.12); }
.tr-frist { font-size: .76rem; }
.tr-frist.ist-bald { color: var(--gold); }
.tr-frist.ist-weg { color: var(--danger); font-weight: 700; }
tr.row-warn > td { background: rgba(200,80,80,.06); }


/* ── Aufstellung nach Plaetzen ── */
.lu-gruppe {
  display: flex; align-items: center; gap: .35rem;
  font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); margin: .45rem 0 .15rem; padding-top: .3rem;
  border-top: 1px solid var(--border);
}
.lu-gruppe:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.lu-keiner { padding: .1rem .3rem .1rem 1rem; font-style: italic; }

/* ── Raidbuffs ──
   Grün heisst da, matt heisst fehlt. Das Kuerzel steht dabei, weil eine Reihe
   gleich grosser Punkte niemandem sagt, welcher Buff fehlt. */
.lu-buffs { display: flex; flex-wrap: wrap; gap: .22rem; margin-top: .5rem; }
.lu-buffs:empty { display: none; }
.lu-mbuffs { padding: .4rem .8rem 0; margin-top: 0; }
.lu-buff {
  font-size: .62rem; font-weight: 700; padding: .06rem .32rem; border-radius: 3px;
  border: 1px solid transparent; white-space: nowrap; cursor: default;
}
.lu-buff.ist-da  { color: #4caf72; border-color: rgba(76,175,114,.4); background: rgba(76,175,114,.1); }
.lu-buff.ist-weg { color: var(--text-muted); border-color: var(--border);
                   background: transparent; text-decoration: line-through; opacity: .75; }

/* ══ Bosse: ein Boss, eine Seite, fuenf Unterseiten ══
   Vorher lag alles auf der Season-Seite: ein Reiter, darin eine Bossleiste,
   darin vier Klappleisten am rechten Rand. Drei Ebenen bis zur Aufstellung,
   und nichts davon liess sich verlinken. */
.boss-kopf {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  margin: .8rem 0 .4rem;
}
.boss-kopf h2 { margin: 0; font-size: 1.15rem; }

/* Die Unterseiten. Keine Reiter im Browser, sondern Links - die Adresse
   traegt, was man sieht. */
.boss-unter {
  display: flex; gap: .2rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--border); margin-bottom: .8rem;
}
.bu-knopf {
  padding: .35rem .8rem; font-size: .82rem; font-weight: 600;
  color: var(--text-muted); text-decoration: none;
  border: 1px solid transparent; border-bottom: none;
  border-radius: 6px 6px 0 0; margin-bottom: -1px;
}
.bu-knopf:hover { color: var(--text); background: var(--bg-card); }
.bu-knopf.is-on {
  color: var(--accent); background: var(--bg-card);
  border-color: var(--border); border-bottom-color: var(--bg-card);
}

/* Die Unterseiten nehmen die ganze Breite. Genau das war der Zweck: eine
   Taktiktafel in einer 280 Pixel breiten Klappleiste war keine. */
.boss-inhalt { display: block; }

/* Video links, Raidplan rechts, Kommentare darunter.
   `auto-fit` statt zweier fester Spalten: gibt es keinen Raidplan, nimmt die
   Videokarte die ganze Breite, statt eine Luecke neben sich zu lassen. */
.boss-lesen {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
  gap: .75rem; align-items: start;
}
.boss-raidplan .rp-grid { grid-template-columns: 1fr; }

/* Die Aufstellungsseite: zwei Karten nebeneinander, weil es zwei Fragen an
   dieselben Leute sind - welche Rolle jemand spielt und wo er steht.
   Untereinander musste man zum Vergleichen scrollen. */
.boss-aufstellung {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: .75rem; align-items: start;
}
/* Officer-Kleinkram nimmt die ganze Breite - er gehoert zu keiner der
   beiden Karten. */
.boss-aufstellung > details,
.boss-aufstellung > form { grid-column: 1 / -1; }
@media (max-width: 1000px) { .boss-aufstellung { grid-template-columns: 1fr; } }

/* Die Gruppenschau ist zum Lesen, nicht zum Ziehen: schmalere Kacheln, und
   die Mindesthoehe eines Abwurfziels braucht sie nicht. */
.lu-gruppenschau .lu-rollenfeld { min-height: 0; }
.lu-gruppenschau .lu-zeile {
  display: flex; align-items: center; gap: .3rem; padding: .1rem .2rem;
  font-size: .78rem;
}
.lu-gruppenkarte .lu-mechanik { margin-top: .7rem; padding-top: .55rem;
  border-top: 1px solid var(--border); }
.boss-kommentare { margin-top: .75rem; }
.tf-karte { padding: .6rem; }

/* Die Kommentare stehen unter beidem und nehmen die ganze Breite: sie
   gehoeren zu dem, was man darueber gelesen hat, und eine schmale Spalte
   daneben macht aus jedem Satz drei Zeilen. */


/* ══ Bosse: Taktiktafel, Raidplan, Pull-Verlauf, Bossleiste ══
   Lag im Kopf der Season-Seite, solange die Bosse ein Reiter dort waren.
   Seit sie einen eigenen Bereich haben, brauchen es beide Seiten - die
   Bossseiten fuer alles, die Season-Seite noch fuer die Untertabs der
   Gearuebersicht und das BiS-Fenster, die dieselben Formen benutzen. */
/* ── Raidplan-Einbettung ──────────────────────────────────────────
 *
 * Gleiche Kachel wie ein Video: gleiches Raster, gleicher 16:9-Rahmen, dieselbe
 * Fusszeile. Vorher lag der Raidplan über die volle Breite und 560 px hoch,
 * daneben standen die Videos als Kacheln — zwei Einbettungen in zwei Formaten
 * lesen sich wie zwei verschiedene Seiten.
 *
 * Die Videokachel ist 200 px breiter (680 statt 480). Ein Video wird
 * angeschaut, ein Raidplan überflogen — und wer ihn wirklich braucht, öffnet
 * ihn mit dem ↗ bei raidplan.io.
 */
.rp-grid {
  /* 570 statt 480: knapp ein Fünftel größer. Ein Plan trägt Beschriftungen in
     Schriftgröße 10 auf einer Fläche von 1200 px — jede Verkleinerung schlägt
     dort zuerst durch. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(570px, 1fr));
  gap: 0.7rem; margin-bottom: 0.7rem;
}
@media (max-width: 660px) { .rp-grid { grid-template-columns: minmax(0, 1fr); } }
.rp-card { min-width: 0; }
/*
 * Die Bühne trägt jetzt ein SVG und keinen fremden Rahmen mehr. 16:9, weil die
 * Fläche, auf der raidplan zeichnet, 1200 × 675 ist — dieselbe Form, also kein
 * Leerrand und kein Beschneiden.
 */
.rp-buehne { position: relative; width: 100%; aspect-ratio: 1200 / 675;
  overflow: hidden; border-radius: 6px; background: #14161a;
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; }
.rp-svg { display: block; width: 100%; height: 100%; }
.rp-laedt { padding: 1rem; text-align: center; }
.rp-fehler { padding: 1rem; text-align: center; font-size: 0.78rem; line-height: 1.4; }

/* Die Schrittleiste. Ein Plan ist eine Abfolge; im iframe musste man dafür in
   einer fremden Oberfläche klicken, die man nicht sah. */
.rp-schritte { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.4rem; }
.rp-schritt {
  border: 1px solid var(--border); background: transparent; color: inherit;
  border-radius: 999px; padding: 0.1rem 0.5rem; font-size: 0.72rem; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.rp-schritt:hover { border-color: var(--gold); }
.rp-schritt.an { background: var(--gold); border-color: var(--gold); color: #1a1a1a; font-weight: 700; }
.rp-notiz {
  margin-top: 0.35rem; padding: 0.35rem 0.5rem; border-left: 2px solid var(--gold);
  background: rgba(212,168,80,.07); border-radius: 0 5px 5px 0;
  white-space: pre-wrap; font-size: 0.76rem; line-height: 1.4;
}

/* Groß ansehen: derselbe Plan, nur ohne Spalte drumherum. */
.rp-lupe {
  position: fixed; inset: 0; z-index: 90; background: rgba(0,0,0,.85);
  display: flex; align-items: center; justify-content: center; padding: 1rem;
}
.rp-lupe[hidden] { display: none; }
.rp-lupe-inhalt { width: 100%; max-width: 1400px; }
.rp-lupe .rp-buehne { border-color: rgba(255,255,255,.15); }
.rp-lupe-zu { position: absolute; top: 0.6rem; right: 0.9rem; font-size: 1.4rem;
  background: none; border: none; color: #fff; cursor: pointer; opacity: .7; }
.rp-lupe-zu:hover { opacity: 1; }
/* Im Vollbild faellt die Begrenzung weg: der Plan nimmt so viel Flaeche, wie
   sein Seitenverhaeltnis auf diesem Bildschirm zulaesst. */
.rp-lupe:fullscreen { padding: 0; background: #000; }
.rp-lupe:fullscreen .rp-lupe-inhalt {
  max-width: none; width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem;
}
.rp-lupe:fullscreen .rp-buehne {
  width: min(100vw, calc((100vh - 5rem) * 1200 / 675));
  border-radius: 0;
}

/* Ein Link ohne Titel: Gastgeber fett, Rest daneben — besser als die nackte
   Adresse, die über die halbe Zeile läuft. */
.link-titel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link-host { font-weight: 600; }
.link-pfad { color: var(--text-muted); }

/* ── Taktik-Board ── */
.tb-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 0.5rem;
}
.tb-card {
  background: var(--bg); border: 1px solid var(--border);
  border-left: 3px solid var(--border); border-radius: 6px; padding: 0.5rem 0.65rem;
}
.tb-head { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.3rem; }
.tb-tag {
  font-size: 0.62rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  padding: 0 0.3rem; border-radius: 3px; background: var(--bg-card); white-space: nowrap;
}
.tb-title { font-size: 0.86rem; }
.tb-actions { margin-left: auto; display: flex; gap: 0.15rem; }
.tb-body { font-size: 0.82rem; line-height: 1.5; }
.tb-body p { margin: 0 0 0.35rem; }
.tb-body ul, .tb-body ol { margin: 0 0 0.35rem 1.1rem; }
.tb-body h3, .tb-body h4 { font-size: 0.84rem; margin: 0.3rem 0 0.2rem; }

/* Colour per target group, so a raider spots their own block at a glance */
.tb-card.tg-all    { border-left-color: var(--text-muted); }
.tb-card.tg-tank   { border-left-color: #5b8dd6; }
.tb-card.tg-tank   .tb-tag { color: #5b8dd6; }
.tb-card.tg-healer { border-left-color: #4fb35c; }
.tb-card.tg-healer .tb-tag { color: #4fb35c; }
.tb-card.tg-melee  { border-left-color: #d1544c; }
.tb-card.tg-melee  .tb-tag { color: #d1544c; }
.tb-card.tg-ranged { border-left-color: var(--teal); }
.tb-card.tg-ranged .tb-tag { color: var(--teal); }
.tb-card.tg-class  { border-left-color: var(--gold); }
.tb-card.tg-class  .tb-tag { color: var(--gold); }

/* Highlight colours available in the editor */
.hl-red { color: #e57373; } .hl-gold { color: var(--gold); }
.hl-teal { color: var(--teal); } .hl-green { color: #7ec93f; }
.hl-purple { color: #b98cd8; }

.tb-toolbar {
  display: flex; gap: 0.2rem; flex-wrap: wrap; align-items: center;
  padding: 0.3rem; border: 1px solid var(--border); border-radius: 5px 5px 0 0;
  background: var(--bg); border-bottom: none;
}
.tb-toolbar button {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 3px;
  color: var(--text); font-family: inherit; font-size: 0.76rem;
  padding: 0.15rem 0.45rem; cursor: pointer; min-width: 26px;
}
.tb-toolbar button:hover { border-color: var(--accent); }
.tb-toolbar button.hl { font-weight: 800; }
.tb-sep { width: 1px; height: 18px; background: var(--border); margin: 0 0.15rem; }
.tb-block { margin-top: .5rem; }
.tb-block[hidden], .gd-block[hidden] { display: none; }
.gd-block { margin-bottom: .6rem; }
.tb-blockkopf { display: flex; align-items: baseline; gap: .4rem; margin-bottom: .25rem; }
.tb-blocklabel {
  font-size: .64rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 700;
  padding: .05rem .35rem; border-radius: 3px;
  background: rgba(255,255,255,.05); color: var(--text-muted);
}
.tb-blocklabel.ist-myth { background: rgba(212,168,80,.18); color: var(--gold); }
.tb-blocklabel.ist-nhc { background: rgba(154,124,242,.16); color: var(--teal); }

.tb-editor {
  min-height: 220px; max-height: 45vh; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 0 0 5px 5px;
  background: var(--bg); padding: 0.6rem 0.7rem; font-size: 0.85rem; line-height: 1.55;
}
.tb-editor:focus { outline: none; border-color: var(--accent); }

/* ── Pull history modal ── */
.pv-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0,0,0,.66); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; padding: 1rem;
}
.pv-backdrop[hidden] { display: none; }
.pv-dialog {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
  width: min(760px, 100%); max-height: 86vh; display: flex; flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,.6);
}
.pv-head {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--border);
}
.pv-head strong { font-size: 0.95rem; }
.pv-head .btn { margin-left: auto; }
.pv-body { padding: 0.8rem 0.9rem; overflow-y: auto; }

.pv-stats { display: flex; gap: 1.4rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.pv-stats div { display: flex; flex-direction: column; }
.pv-stats b { font-size: 1.25rem; color: var(--gold, #d8a12a); font-variant-numeric: tabular-nums; }
.pv-stats span { font-size: 0.66rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }

.pv-night {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.3rem 0; border-bottom: 1px solid var(--border); font-size: 0.8rem;
}
.pv-night:last-child { border-bottom: none; }
.pv-date { min-width: 92px; font-variant-numeric: tabular-nums; }
.pv-meter { flex: 1; height: 7px; border-radius: 999px; background: rgba(0,0,0,.35); overflow: hidden; }
.pv-meter span { display: block; height: 100%; background: linear-gradient(90deg,var(--teal-deep),var(--venom)); }
.pv-night.killed .pv-meter span { background: linear-gradient(90deg,#16a34a,#d8a12a); }
.pv-best { min-width: 74px; text-align: right; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.pv-roster { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 0.25rem; }
.pv-mem {
  display: flex; align-items: baseline; gap: 0.35rem; font-size: 0.76rem;
  padding: 0.15rem 0.35rem; background: var(--bg);
  border: 1px solid var(--border); border-radius: 4px;
}
.pv-mem .pm-ilvl { margin-left: auto; color: var(--text-muted); font-size: 0.68rem; }
.pv-section {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); font-weight: 700; margin: 0.9rem 0 0.4rem;
}

/* ── Boss sub-tabs ── */
.boss-tabs {
  display: flex; gap: 0.25rem; overflow-x: auto; padding-bottom: 0.4rem;
  margin-bottom: 0.6rem; border-bottom: 1px solid var(--border);
  scrollbar-width: thin;
}
.boss-tab {
  display: inline-flex; align-items: center; gap: 0.35rem; flex-shrink: 0;
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px 6px 0 0;
  color: var(--text-muted); font-family: inherit; font-size: 0.78rem; font-weight: 600;
  padding: 0.35rem 0.7rem; cursor: pointer; white-space: nowrap;
}
.boss-tab:hover { color: var(--text); }
.boss-tab.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.bt-idx {
  font-size: 0.66rem; opacity: .7; font-variant-numeric: tabular-nums;
}
.bt-badge {
  background: rgba(0,0,0,.25); border-radius: 999px; font-size: 0.62rem;
  padding: 0 0.32rem; line-height: 1.5;
}
.boss-panel { display: none; }
.boss-panel.active { display: block; }

/* ── Boss layout with comment rail ── */
/* Zwei Spalten und zwei Panels: Videos links, Aufstellung und Vorbereitung
   daneben, Taktiktafel und Kommentare rechts zum Aufklappen.

   Die Tafel als stehende Spalte hat nicht funktioniert: sie ist der laengste
   Kasten der Seite, und sechs Notizen untereinander haben alles andere nach
   unten gedrueckt. Als Panel kostet sie eingeklappt 48 Pixel und aufgeklappt
   keine Seitenlaenge - sie scrollt in sich selbst. */
.boss-layout { display: flex; gap: 0.6rem; align-items: flex-start; }
.boss-main { flex: 6 1 0; min-width: 0; }
.boss-neben {
  flex: 4 1 0; min-width: 0; max-width: 560px;
  display: flex; flex-direction: column; gap: 0.6rem;
}
/* Die Karten in der Nebenspalte tragen ihren Abstand ueber `gap` — der
   Aussenabstand von frueher wuerde ihn verdoppeln. */
.boss-neben > .card { margin-top: 0 !important; }
/* Im Panel steht die Tafel einspaltig - dort ist Breite knapp und Lesbarkeit
   wichtiger als Packdichte. */
.boss-tafel .tb-grid { display: block; }
.boss-tafel .tb-card { margin-bottom: 0.5rem; }
.boss-neben .stats-table { font-size: 0.72rem; }

/* ── „Bosse verwalten" als Fenster ──
   Selten gebraucht, aber breit: als stehende Kachel drueckte sie die Guides
   nach unten. */
.gd-verwalten { margin-left: .5rem; }
.bv-modal {
  position: fixed; inset: 0; z-index: 1100; background: rgba(0,0,0,.72);
  display: flex; align-items: flex-start; justify-content: center; padding: 3rem 1rem 1rem;
  overflow-y: auto;
}
.bv-modal[hidden] { display: none; }
.bv-fenster {
  width: min(920px, 100%); background: var(--bg-card);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 24px 60px rgba(0,0,0,.6);
}
.bv-kopf {
  display: flex; align-items: center; gap: .5rem;
  padding: .6rem .8rem; border-bottom: 1px solid var(--border);
}
.bv-kopf .btn { margin-left: auto; }
.bv-inhalt { padding: .8rem; }
/* ── Die beiden Seitenleisten ──
   Eingeklappt ist eine Leiste ein schmaler Reiter, auf dem senkrecht steht,
   was dahinter liegt. Ein Symbol waere kuerzer, aber man muesste es raten -
   und genau daran ist die erste Fassung gescheitert. */
/* Alle Leisten in einer Spalte am rechten Rand, untereinander.
   Rechtsbuendig, damit ein aufgeklapptes Panel nach links waechst und die
   eingeklappten Reiter daneben schmal bleiben. */
.rail-spalte {
  display: flex; flex-direction: column; align-items: flex-end; gap: 0.4rem;
  flex-shrink: 0; align-self: flex-start;
  position: sticky; top: 0.6rem;
}
.rail {
  flex-shrink: 0; background: var(--bg-card);
  border: 1px solid var(--border); border-radius: 8px; overflow: hidden;
}
/* Jede Leiste so breit, wie ihr Inhalt es braucht - eine Tabelle mehr als
   ein paar Saetze. */
.boss-comments { width: 270px; }
.boss-tafel { width: 380px; }
.boss-cd { width: 340px; }
.boss-vorb { width: 440px; }
.rail[data-open="0"] { width: 30px; }

.rail-knopf {
  display: flex; align-items: center; gap: 0.4rem; width: 100%;
  background: var(--bg); border: none; border-bottom: 1px solid var(--border);
  color: var(--text); font-family: inherit; font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  padding: 0.5rem 0.6rem; cursor: pointer; text-align: left;
}
.rail-knopf:hover { color: var(--accent); }
.rail-knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rail-zahl {
  font-variant-numeric: tabular-nums; font-weight: 800; font-size: 0.66rem;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 999px; padding: 0 0.32rem; line-height: 1.5;
}
.rail-pfeil { margin-left: auto; transition: transform .15s; }
.rail[data-open="1"] .rail-pfeil { transform: rotate(90deg); }

/* Eingeklappt kippt der Knopf in die Senkrechte und fuellt den Reiter. */
.rail[data-open="0"] .rail-knopf {
  writing-mode: vertical-rl;
  padding: 0.6rem 0.15rem; gap: 0.5rem;
  border-bottom: none; justify-content: flex-start;
}
.rail[data-open="0"] .rail-pfeil { margin-left: 0; margin-top: auto; }
/* Im Reiter ohne Pille: ein gedrehter Kreis mit Rand sieht nach Fehler aus. */
.rail[data-open="0"] .rail-zahl {
  background: none; border: none; padding: 0; line-height: 1; opacity: .75;
}
.rail[data-open="0"] .rail-inhalt { display: none; }

/* Aufgeklappt scrollt die Leiste in sich - die Seite bleibt so lang, wie sie
   ohne sie waere. Genau das war vorher das Problem. */
.rail-inhalt {
  padding: 0.5rem 0.6rem; overflow-y: auto; overflow-x: auto; max-height: 70vh;
}
.tf-body { max-height: 82vh; }
.comment { padding: 0.4rem 0; border-bottom: 1px solid var(--border); font-size: 0.8rem; }
.comment:last-of-type { border-bottom: none; }
.cm-meta {
  display: flex; align-items: center; gap: 0.3rem; flex-wrap: wrap;
  font-size: 0.7rem; color: var(--text-muted); margin-bottom: 0.2rem;
}

/* Cooldown plan rows reuse the raid list look */
.upcoming-item {
  display: flex; align-items: center; gap: 0.85rem;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px;
  padding: 0.55rem 0.9rem; text-decoration: none; color: var(--text);
}
.upcoming-item:hover { border-color: var(--accent); }
.up-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.up-title { font-weight: 600; font-size: 0.87rem; }
.up-date { font-size: 0.73rem; color: var(--text-muted); }
.up-meta { flex-shrink: 0; }
.up-count { font-size: 0.73rem; color: var(--text-muted); }

/* Ab hier ist Nebeneinander keine Hilfe mehr: zwei schmale Spalten lesen sich
   schlechter als zwei volle Breiten untereinander. */
@media (max-width: 1250px) {
  .boss-layout { flex-wrap: wrap; }
  .boss-main, .boss-neben { flex: 1 1 100%; max-width: none; }
}
@media (max-width: 900px) {
  .boss-layout { flex-direction: column; }
  .rail-spalte { width: 100%; align-items: stretch; position: static; }
  .rail, .rail[data-open="0"] { width: 100%; }
  /* Auf dem Handy gibt es keine schmale Spalte, also auch keinen Reiter:
     der Knopf bleibt waagerecht ueber voller Breite. */
  .rail[data-open="0"] .rail-knopf {
    writing-mode: horizontal-tb; padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border);
  }
  .rail[data-open="0"] .rail-pfeil { margin-left: auto; margin-top: 0; }
  .rail[data-open="0"] .rail-zahl { padding: 0 0.32rem; line-height: 1.5; }
  .tf-body { max-height: none; }
}

/* ══ hidden heisst hidden ══
   Der Browser gibt `[hidden]` ein `display: none` mit - aber jede eigene
   Regel mit `display: flex` oder `display: grid` schlaegt es, weil beide
   gleich spezifisch sind und die eigene spaeter kommt. Das Element bleibt
   dann sichtbar, obwohl `el.hidden = true` gesetzt ist, und niemand sucht
   den Fehler im Stylesheet.

   Genau das ist beim Raidchat passiert: ausgeblendet verschwand er nicht,
   sondern rutschte unter die Bilder und nahm dort die ganze Breite - es sah
   aus, als haette man ihn gross gemacht. Dieselbe Falle lag beim Zeichenfeld
   und beim Knopf zum Wiedereinblenden.

   Nachgesehen: siebenundfuenfzig Elemente tragen `hidden` im Markup, und
   keines davon wird per `style.display` gezeigt. Die Regel kann also
   niemandem in die Quere kommen. */
[hidden] { display: none !important; }

/* Eine Tabelle darf die Seite nicht seitwaerts schieben. */
.tabelle-rollt { overflow-x: auto; }

/* ── Das Klickmenue an einem Namen ──
   Zwei Fragen an dieselbe Anmeldung: wohin sie gehoert und mit welchem
   Charakter. Beides in einem Menue - der Charakterwechsel stand zuerst in
   einem eigenen Kasten und lag damit unter diesem hier. */
.chip-menu { max-height: 340px; overflow-y: auto; }

/* ══════════════════════════════════════════════════════
   Mechanik-Zähler: Zeitstrahl je Spieler
   ══════════════════════════════════════════════════════ */
/* Jede Mechanik ist eine eigene Kachel.
 *
 * Nebeneinander liefen sie ineinander: zwischen der letzten Reihe der einen und
 * dem Kopf der naechsten stand nichts als Luft, und bei drei Spalten sah es aus
 * wie eine einzige lange Tabelle. Ein eigener Grund und eine Haarlinie ringsum
 * reichen — kein Schatten, keine dicke Kante: die Kachel sitzt in einer Karte,
 * und zwei Rahmen uebereinander sehen nach Versehen aus.
 *
 * `--bg-card2` ist der Ton, der im Projekt schon fuer „eine Ebene hoeher" steht;
 * die Kachel hebt sich damit vom Kartengrund ab, ohne eine neue Farbe
 * einzufuehren. */
.mech-block {
  margin-bottom: 0.9rem;
  padding: 0.45rem 0.5rem 0.5rem;
  background: var(--bg-card2);
  border: 1px solid var(--border);
  border-radius: 5px;
}
/* Der Kopf traegt die Haarlinie, damit die Kachel oben einen Anker hat und man
   beim Scrollen sieht, wo eine Mechanik anfaengt. */
.mech-kopf {
  display: flex; align-items: baseline; gap: 0.4rem;
  margin: -0.05rem 0 0.35rem; padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.82rem;
}
.mech-kopf > b { color: var(--gold); }
.mech-kopfweg { margin-left: auto; }
.mech-leer { padding: 0.3rem 0; }

/* Ein Raster fuer alles unter der Kopfzeile: Name, Zeit, Zahl.
 *
 * Die Zeitspalte ist EINE Spalte, und Welle, Achse und jede Spielerreihe
 * liegen darin. Vorher war jede Reihe ein eigener Flexkasten und die Achse
 * fehlte ganz - was man nicht ausrichten kann, kann man auch nicht ablesen.
 * Als Raster koennen die drei gar nicht auseinanderlaufen, und das Lot
 * bekommt mit denselben Variablen genau die Breite der Zeitspalte. */
.mech-raster {
  --mech-name: 102px;
  /* Breiter als frueher, weil hier jetzt ein Balken steht und nicht nur eine
     Zahl: „wer am meisten" war als nackte Ziffer am Rand kein Diagramm. */
  --mech-zahl: 92px;
  --mech-luft: 0.45rem;
  /* Der Abstand zweier Zeitstriche, in Prozent - gesetzt wird er beim
     Zeichnen, weil nur dort die Pulldauer bekannt ist. */
  --mech-tick: 25%;
  --mech-gitter: rgba(255, 255, 255, .085);
  position: relative;
  display: grid;
  grid-template-columns: var(--mech-name) minmax(0, 1fr) var(--mech-zahl);
  column-gap: var(--mech-luft);
  row-gap: 2px;
  align-items: center;
}

/* Die Gitterlinien stehen NICHT als Elemente in jeder Reihe, sondern als
   Verlauf im Hintergrund. Ein Verlauf kann nicht verrutschen, kostet keinen
   Knoten (vorher: Striche x Reihen x Zaehler) und liegt zwangslaeufig genau
   unter den Beschriftungen der Achse - beide rechnen mit --mech-tick. */
.mech-spur, .mech-welle {
  background-image: repeating-linear-gradient(to right,
    var(--mech-gitter) 0 1px, transparent 1px var(--mech-tick));
  /* Bewusst über die ganze Breite und NICHT per background-size gekürzt: die
     Prozentangabe im Verlauf rechnet gegen die Hintergrundfläche, nicht gegen
     das Element. Eine gekürzte Fläche würde die Tickabstände um denselben
     Faktor strecken — und damit genau die Deckungsgleichheit von Gitter und
     Beschriftung aufgeben, für die der Verlauf hier überhaupt steht. Der
     letzte Strich vor dem Rand bleibt deshalb unbeschriftet, wenn die Zahl
     dort nicht mehr hinpasst; er sitzt trotzdem auf einem echten Zeitpunkt. */
}

.mech-welle {
  grid-column: 2; position: relative; height: 40px;
  background-color: rgba(255, 255, 255, .03); border-radius: 3px;
}
.mech-wellebild { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.mech-wellebild path { fill: rgba(217, 164, 65, .42); }


/* Die Oberkante IST „alle Spieler" — deshalb traegt sie den Strich, und nicht
   eine gestrichelte Linie im Inneren, die zwangslaeufig genau dort gelegen
   haette und nie einen Unterschied zeigen konnte. */
.mech-welle { border-top: 1px dashed rgba(255, 255, 255, .22); }
.mech-spitze {
  grid-column: 3; text-align: right; font-size: 0.68rem; line-height: 1.2;
  color: var(--accent); font-variant-numeric: tabular-nums;
}

/* Die Zeitachse - der Teil, der gefehlt hat. Sie steht zwischen Welle und
   Reihen, also direkt an beiden: von der Spitze der Welle senkrecht nach
   unten liest man ab, wen es getroffen hat. */
.mech-achse { grid-column: 2; position: relative; height: 16px; }
.mech-tick { position: absolute; top: 0; bottom: 0; width: 1px;
  background: rgba(255, 255, 255, .16); }
/* `font-style: normal`, weil Strich und Zahl <i> und <b> sind: das Markup
   waehlt die Elemente nach ihrer Groesse, nicht nach ihrer Bedeutung, und ohne
   diese Zeile stehen alle Uhrzeiten der Achse kursiv. */
.mech-tick > b {
  position: absolute; top: 2px; left: 0; transform: translateX(-50%);
  font-size: 0.66rem; font-weight: 400; font-style: normal; line-height: 1;
  color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Die erste und die letzte Zahl ruecken nach innen, sonst haengen sie ueber
   den Rand der Karte hinaus. */
.mech-tick.anf > b { transform: none; }
.mech-tick.ende > b { transform: translateX(-100%); color: var(--text); }
.mech-tick.ende { background: rgba(255, 255, 255, .3); }

.mech-wer { grid-column: 1; font-size: 0.72rem; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mech-wer:hover { color: var(--danger); text-decoration: line-through; }
.mech-spur { grid-column: 2; position: relative; height: 14px; border-radius: 3px;
  background-color: rgba(255, 255, 255, .05); }

/* Die Zahlenspalte ist jetzt ein Rangdiagramm: der Balken liegt HINTER der
   Zahl, in derselben Zeile. Er kostet damit keinen einzigen Pixel Hoehe und
   beantwortet trotzdem die Frage, fuer die man vorher zwanzig Zahlen lesen
   musste — ragt jemand heraus oder hat es alle gleich getroffen. */
.mech-zahl {
  grid-column: 3; position: relative; height: 14px;
  display: flex; align-items: center; justify-content: flex-end;
  font-size: 0.72rem; font-variant-numeric: tabular-nums;
  background-color: rgba(255, 255, 255, .04); border-radius: 3px;
  overflow: hidden;
}
.mech-zahl > i {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: rgba(217, 164, 65, .34);
}
.mech-zahl > b { position: relative; font-weight: 500; font-style: normal;
  padding-right: 4px; display: flex; gap: 4px; align-items: baseline; }
/* Die zweite Zahl in derselben Zeile - der Schaden zu den Treffern. */
.mech-zahl > b > u { text-decoration: none; font-weight: 400; font-size: 0.92em;
  color: var(--text-muted); }

/* „Wer war nie dabei" als EIN Satz statt als neunzehn leere Reihen. */
/* Ohne gemeinsame Uhr: zwei Spalten statt drei, der Balken bekommt den Platz
   der Zeitspalte. Gerechnet wird ueber mehrere Trys nur noch die Summe, und die
   soll man vergleichen koennen. */
.mech-raster.ohne-zeit {
  grid-template-columns: var(--mech-name) minmax(0, 1fr);
}
.mech-raster.ohne-zeit .mech-zahl { grid-column: 2; }

.mech-nie {
  display: flex; gap: 0.4rem; margin-top: 3px; font-size: 0.68rem;
  color: var(--text-muted);
}
.mech-nie > span:first-child { flex-shrink: 0; }
.mech-nie > span:last-child { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; opacity: .8; }

/* Marken: 3px waren im Discord-Call nicht zu treffen. Die Breite kommt jetzt
   aus der Rechnung (mindestens 0,55 % der Spur), die Mindesthoehe von hier. */
.mech-marke { position: absolute; top: 2px; bottom: 2px; min-width: 4px;
  border-radius: 1px; background: var(--warn); cursor: default; }
.mech-marke:hover { background: var(--accent-hover);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .45); }
/* Gebuendelt: mehrere Marken lagen auf denselben vier Pixeln. Heller und mit
   innerer Kante, damit man den Klumpen vom einzelnen Treffer unterscheidet. */
.mech-marke.viele { background: var(--accent-hover);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .4); }
/* Beide Schatten zusammen, sonst nimmt die Buendelmarke dem Hover die einzige
   Rueckmeldung: man faehrt darueber und nichts passiert. */
.mech-marke.viele:hover {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .4), 0 0 0 1px rgba(255, 255, 255, .45); }
.mech-marke.lang:hover { background: rgba(247, 228, 172, .6);
  box-shadow: inset 2px 0 0 var(--warn), 0 0 0 1px rgba(255, 255, 255, .45); }
/* Bei einer Dauerbande markiert ein INNERER Schatten den Anfang. Ein
   border-left waere bei box-sizing:border-box die ganze Bande, sobald sie
   schmal wird - dann sieht man den Rand und nicht mehr die Dauer. */
.mech-marke.lang { background: rgba(217, 164, 65, .5);
  box-shadow: inset 2px 0 0 var(--warn); }
/* Beim Stapel steckt die Hoehe in der Deckkraft: zwanzig Stapel sind satt,
   zwei sind blass. So sieht man den Aufbau, ohne zu hovern. */
.mech-marke.stapel {
  background: rgba(217, 164, 65, calc(var(--mech-stapel, .3) * 0.75 + 0.12));
  box-shadow: none;
}
.mech-marke.stapel:hover { box-shadow: 0 0 0 1px rgba(255, 255, 255, .45); }

/* Das Lot: eine senkrechte Linie unter dem Zeiger, durch Welle und alle
   Reihen, mit der Zeit obendran. Bei zwanzig Reihen schaut sonst niemand mehr
   zur Achse hoch. Es liegt im Raster, also genau auf der Zeitspalte, und
   nimmt keine Mausereignisse - sonst fiele der Hinweis an den Marken aus. */
.mech-lot {
  position: absolute; top: 0; bottom: 0;
  left: calc(var(--mech-name) + var(--mech-luft));
  right: calc(var(--mech-zahl) + var(--mech-luft));
  pointer-events: none; display: none;
}
.mech-raster.zeigt .mech-lot { display: block; }
.mech-lot > i { position: absolute; top: 0; bottom: 0; width: 1px; margin-left: -0.5px;
  background: var(--accent); opacity: .75; }
.mech-lot > b {
  position: absolute; top: -1px; padding: 0 3px; border-radius: 3px;
  transform: translateX(-50%); font-size: 0.66rem; font-weight: 600;
  font-style: normal;
  background: var(--accent); color: #17100a;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Die kleine Karte unter einem Ort-Zaehler: wo es passiert ist, zueinander.
   Quadratisch und klein - sie beantwortet „lagen sie beieinander", nicht
   „welche Koordinate". */
.mech-feld { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.45rem; }
.mech-feld > svg { width: 116px; height: 116px; flex-shrink: 0; display: block; }
.mech-feldrand { fill: rgba(255, 255, 255, .035); stroke: var(--border); stroke-width: 1;
  vector-effect: non-scaling-stroke; }
.mech-punkt { fill: var(--warn); stroke: rgba(0, 0, 0, .45); stroke-width: 0.8; }
.mech-punkt:hover { fill: var(--accent-hover); }

/* Das Register: alle Spieler gegen alle Mechaniken.
 *
 * Die Bloecke darunter sagen je Mechanik, wer wann. Die Frage des Raidleiters
 * geht aber quer dazu — wer steckt ueberall drin —, und dafuer musste er acht
 * Zahlenspalten ueber zweieinhalb Bildschirme zusammenlesen. Hier steht es in
 * einer Tabelle von 20 Zeilen. */
/* Das Wellendiagramm ueber dem Register.
 *
 * Das Register sagt, WER in wie vielem drinsteckt — was dort fehlte, ist das
 * WANN, und zwar ueber alle Mechaniken auf einmal. Jede Kurve ist auf ihr
 * eigenes Maximum normiert: verglichen wird die Form, nicht die Hoehe.
 * Sekunden, Stapel und Treffer haben keinen gemeinsamen Massstab. */
.mech-kurven {
  margin-bottom: 0.9rem; padding: 0.45rem 0.5rem 0.4rem;
  background: var(--bg-card2);
  border: 1px solid var(--border);
  border-radius: 5px;
}
.mech-klegende {
  display: flex; flex-wrap: wrap; gap: 0.2rem 0.9rem;
  font-size: 0.7rem; margin-bottom: 0.35rem;
}
.mech-kname { display: inline-flex; align-items: center; gap: 0.3rem; }
.mech-kname > i { width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0; }
.mech-kname > b { font-weight: 400; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.mech-kbild {
  position: relative; height: 92px; border-radius: 3px;
  background-color: rgba(255, 255, 255, .03);
  /* Die senkrechten Linien stehen auf denselben Minuten wie die Achse darunter
     - `--mech-tick` kommt aus derselben Rechnung. Ein Raster alle zehn Prozent
     sah neben einer Minutenachse nach Zufall aus, weil es Zufall war. */
  background-image:
    repeating-linear-gradient(to right,
      rgba(255,255,255,.07) 0 1px, transparent 1px var(--mech-tick, 25%)),
    repeating-linear-gradient(to top,
      rgba(255,255,255,.055) 0 1px, transparent 1px 25%);
}
.mech-kbild > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Die Flaeche traegt die Farbe nur angedeutet, die Linie obendrauf macht die
   Form lesbar — auch da, wo sich zwei Kurven ueberlagern. */
.mech-kflaeche { fill-opacity: .16; stroke: none; }
.mech-klinie { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke;
  stroke-linejoin: round; stroke-linecap: round; }
.mech-kachse { margin-top: 1px; }

/* Das Lot in der Kurve und die Namen darunter.
 *
 * Die Kurve sagt, dass um 4:12 viel los war — die Frage danach ist immer
 * dieselbe: wer. Deshalb steht unter dem Diagramm, wer zu dem Zeitpunkt
 * dahintersteckt, je Mechanik in ihrer Farbe. */
.mech-klot {
  position: absolute; top: 0; bottom: 0; width: 1px; left: 0;
  background: var(--accent); opacity: .8; display: none; pointer-events: none;
}
.mech-kurven.zeigt .mech-klot { display: block; }
.mech-kwer {
  margin-top: 0.3rem; min-height: 2.6em; font-size: 0.7rem;
  display: flex; flex-direction: column; gap: 1px;
}
.mech-kzeile { display: flex; align-items: baseline; gap: 0.35rem; }
.mech-kzeile > i { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0;
  align-self: center; }
.mech-kzeile > em { font-style: normal; color: var(--text-muted); flex-shrink: 0; }
.mech-kzeile > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mech-kzeit { font-weight: 600; color: var(--accent);
  font-variant-numeric: tabular-nums; }

.mech-register {
  --mech-regname: 104px;
  --mech-regrang: 76px;
  /* Derselbe Grund wie die Kacheln: das Register ist eine davon, nur quer. */
  margin-bottom: 0.9rem; padding: 0.45rem 0.5rem 0.5rem;
  background: var(--bg-card2);
  border: 1px solid var(--border);
  border-radius: 5px;
}
.mech-register[open] > summary {
  margin-bottom: 0.35rem; padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--border);
}
.mech-regzeile {
  display: grid;
  /* Die mittleren Spalten kommen als FERTIGES repeat() aus dem Markup, nicht
     als repeat(var(--zahl), …): die Ersetzung einer Variablen passiert auf
     Zeichenebene, und eine Variable als Wiederholungszahl ist genau die Stelle,
     an der Browser auseinandergehen. So steht dort am Ende buchstaeblich
     `repeat(8, minmax(0, 1fr))`, und daran gibt es nichts zu deuten. */
  grid-template-columns:
    var(--mech-regname)
    var(--mech-regmitte, repeat(4, minmax(0, 1fr)))
    var(--mech-regrang);
  gap: 2px; align-items: stretch;
}
.mech-regzeile + .mech-regzeile { margin-top: 2px; }
.mech-regname {
  font-size: 0.72rem; font-style: normal; line-height: 16px; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mech-regname:hover { color: var(--danger); text-decoration: line-through; }
.mech-regkopf {
  font-size: 0.6rem; font-style: normal; line-height: 1.1; color: var(--text-muted);
  align-self: end; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding-bottom: 2px;
}
.mech-regzelle {
  font-style: normal; font-size: 0.66rem; line-height: 16px; text-align: center;
  border-radius: 2px; font-variant-numeric: tabular-nums;
  /* Eingefaerbt nach dem Anteil am groessten Wert DIESER Mechanik - Sekunden
     und Treffer duerfen keinen gemeinsamen Massstab haben. */
  background: rgba(217, 164, 65, calc(var(--a, 0) * 0.55 + 0.06));
}
/* Leer heisst „nie drin", und das ist eine Aussage - kein fehlender Wert. */
.mech-regzelle.leer { background: rgba(255, 255, 255, .03); }
.mech-regrang {
  position: relative; font-style: normal; font-size: 0.66rem; line-height: 16px;
  display: flex; align-items: center; justify-content: flex-end;
  background: rgba(255, 255, 255, .04); border-radius: 2px; overflow: hidden;
  color: var(--text-muted);
}
.mech-regzeile.kopf .mech-regrang { background: none; padding-bottom: 2px;
  align-items: flex-end; font-size: 0.6rem; }
.mech-regrang > b { position: absolute; left: 0; top: 0; bottom: 0;
  background: rgba(217, 164, 65, .34); }
.mech-regrang > u { position: relative; text-decoration: none; padding-right: 4px;
  font-variant-numeric: tabular-nums; }

/* ── Zeitstrahl der Tode ──
 *
 * Eine Zeile je Todes-GRUPPE, nicht je Tod: im eigenen Wipe sind 21 Tode, aber
 * neun fallen in dieselbe Sekunde an dieselbe Faehigkeit. Als eine Zeile
 * „9x Noxious Blast um 6:29" ist das ein Satz, als neun Zeilen ist es Rauschen
 * — und beim Wipe wird die Anzeige dadurch kuerzer statt laenger. */
.tod-strahl { margin: 0 0.75rem 0.6rem; }
.tod-satz { font-size: 0.82rem; margin-bottom: 0.4rem; }
.tod-satz b { color: var(--gold); }
.tod-raster {
  --tod-zeit: 72px;
  --tod-wer: 150px;
  --mech-tick: 25%;
  position: relative;
  display: grid;
  grid-template-columns: var(--tod-zeit) minmax(0, 1fr) var(--tod-wer);
  column-gap: 0.45rem; row-gap: 2px; align-items: center;
}
.tod-welle { grid-column: 2; position: relative; height: 34px; border-radius: 3px;
  background-color: rgba(255, 255, 255, .03); }
.tod-welle .mech-wellebild path { fill: rgba(209, 84, 76, .34); }
.tod-spitze { grid-column: 3; font-size: 0.7rem; color: var(--danger);
  font-variant-numeric: tabular-nums; }
.tod-achse { grid-column: 2; }
.tod-zeit { grid-column: 1; font-size: 0.72rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.tod-spur {
  grid-column: 2; position: relative; height: 14px; border-radius: 3px;
  background-color: rgba(255, 255, 255, .05);
  background-image: repeating-linear-gradient(to right,
    rgba(255, 255, 255, .085) 0 1px, transparent 1px var(--mech-tick));
}
/* Vor dem Kipppunkt gedaempft: „wie viele danach" ist damit die Hoehe eines
   Blocks und keine Rechnung. */
.tod-spur.vorher { opacity: .45; }
.tod-marke {
  position: absolute; top: 1px; bottom: 1px; min-width: 14px;
  border-radius: 2px; background: var(--danger); color: #140b0a;
  font-size: 0.62rem; font-weight: 700; line-height: 12px; text-align: center;
  cursor: default;
}
.tod-marke:hover { background: #e8736a; box-shadow: 0 0 0 1px rgba(255,255,255,.45); }
.tod-marke.high { background: #e8554c; }
.tod-marke.warn { background: #d9a441; color: #171009; }
.tod-wer { grid-column: 3; font-size: 0.7rem; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der Kipppunkt als feste Linie — ohne Maus, damit er auf dem geteilten
   Bildschirm einfach dasteht. */
.tod-kipp {
  position: absolute; top: 0; bottom: 0; width: 2px;
  margin-left: calc(var(--tod-zeit) + 0.45rem);
  background: var(--danger); opacity: .55; pointer-events: none;
}

.mech-legende { display: flex; flex-wrap: wrap; gap: 3px; margin-bottom: 0.6rem; }
.mech-chip { font-size: 0.7rem; padding: 1px 6px; border-radius: 999px; cursor: pointer;
  background: transparent; color: var(--text); border: 1px solid var(--border); }
.mech-chip:hover { border-color: var(--accent); }
.mech-chip.aus { opacity: .4; text-decoration: line-through; }
.mech-chip.alle { border-color: var(--accent); color: var(--accent); }

/* Schmal: die Namensspalte schrumpft, die Zeitspalte bleibt fluide. Die
   Schrittweite der Achse rechnet sich aus der gemessenen Breite selbst neu,
   hier ist also nichts nachzuziehen. */
@media (max-width: 620px) {
  .mech-raster { --mech-name: 72px; --mech-zahl: 64px; --mech-luft: 0.3rem; }
  .mech-wer, .mech-zahl { font-size: 0.66rem; }
}

/* Ab einer breiten Karte stehen die Zaehler nebeneinander.
 *
 * Mit allen zwanzig Spielern sind es neunundachtzig Reihen, und die standen
 * untereinander auf ueber zweitausend Pixeln — im geteilten Bildschirm scrollt
 * man dann waehrend alle zuschauen. Zwei Spalten halbieren das, ohne dass
 * etwas verschwindet. Mehrspaltig statt Raster, weil die Bloecke
 * unterschiedlich hoch sind und in einem Raster jede Zeile so hoch waere wie
 * ihr groesster Block. `break-inside` haelt einen Zaehler zusammen; ein
 * Zeitstrahl, der mitten in der Spalte abreisst, waere schlimmer als Scrollen.
 * Die Zeitspalte wird dabei schmaler — die Schrittweite der Achse rechnet sich
 * daraus selbst neu. */
/* Die Kacheln nebeneinander — zwei, drei oder vier, je nach Platz.
 *
 * Gemessen wird die KARTE, nicht das Fenster: die Karte sitzt neben der
 * Pullliste und ist rund 358 px schmaler, und eine Fensterabfrage liess die
 * Spalten deshalb an der falschen Stelle umschlagen.
 *
 * Der Container sitzt auf der KARTE, nicht auf dem Inhalt. Eine
 * Containerabfrage gilt nur fuer Nachfahren — ein Element ist nicht sein
 * eigener Container. Stand `container-type` auf #mech-inhalt und die Regel
 * setzte `column-count` ebenfalls auf #mech-inhalt, traf sie nie zu, und es
 * gab die zweite Spalte schlicht nicht.
 *
 * Die Schwellen wachsen mit der Spaltenzahl, damit eine Kachel immer etwa
 * 360 bis 375 px breit bleibt: darunter traegt die Zeitspalte keine drei
 * Beschriftungen mehr, und ein Zeitstrahl ohne Achse war der Anfang dieser
 * ganzen Geschichte. */
#mech-karte { container-type: inline-size; container-name: mechkarte; }
#mech-inhalt { column-gap: 1.2rem; }
#mech-inhalt > .mech-block { break-inside: avoid; }
#mech-inhalt > .mech-legende,
#mech-inhalt > .mech-kurven,
#mech-inhalt > .mech-register { column-span: all; }

@container mechkarte (min-width: 760px) {
  #mech-inhalt { column-count: 2; }
  /* Schmalere Kachel, also schmalere Randspalten — die Zeit bekommt den Platz.
     Das Polster der Kachel kostet 16 px, die hier wieder hereinkommen. */
  .mech-raster { --mech-name: 82px; --mech-zahl: 70px; --mech-luft: 0.35rem; }
  .mech-wer, .mech-zahl { font-size: 0.69rem; }
}
@container mechkarte (min-width: 1180px) { #mech-inhalt { column-count: 3; } }
@container mechkarte (min-width: 1580px) { #mech-inhalt { column-count: 4; } }

/* Einspaltig ist das Register zugeklappt: aufgeklappt legt es 430 px oben
   drauf, und damit wuerde die Karte durch den Umbau LAENGER statt kuerzer.
   Zweispaltig ist der Platz da, dort steht es offen. */
.mech-register > summary {
  cursor: pointer; list-style: none; font-size: 0.8rem; font-weight: 600;
  display: flex; align-items: baseline; gap: 0.5rem; padding: 0.1rem 0;
}
.mech-register > summary::-webkit-details-marker { display: none; }
.mech-register > summary::before {
  content: '▸'; color: var(--text-muted); font-size: 0.7rem;
}
.mech-register[open] > summary::before { content: '▾'; }
@media (max-width: 620px) {
  .mech-register { --mech-regname: 70px; --mech-regrang: 54px; }
  .mech-regkopf { font-size: 0.52rem; }
}

/* Main beim ersten Mal wählen */
.main-wahl-kopf { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); margin: 0.2rem 0 0.35rem; }
.main-wahl {
  display: grid; grid-template-columns: auto minmax(0, 9rem) minmax(0, 1fr) auto; align-items: center; gap: 0.6rem;
  padding: 0.45rem 0.6rem; margin-bottom: 0.3rem; cursor: pointer;
  background: var(--bg-card2, var(--bg)); border: 1px solid var(--border); border-left-width: 3px; border-radius: 5px;
}
.main-wahl:has(input:checked) { border-top-color: var(--gold); border-right-color: var(--gold); border-bottom-color: var(--gold); background: var(--bg); }
.main-wahl-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.main-wahl-ilvl { font-variant-numeric: tabular-nums; font-size: 0.8rem; color: var(--text-muted); }
@media (max-width: 520px) { .main-wahl { grid-template-columns: auto 1fr auto; } .main-wahl > .muted-sm { display: none; } }
