/* ==========================================================================
   CC Supervisor — Stylesheet
   Aus dem Single-File-MVP herausgelöst. Alle früheren style="..."-Attribute
   sind hier als Utility-Klassen abgebildet, damit eine strikte CSP ohne
   'unsafe-inline' funktioniert.
   ========================================================================== */

:root {
  --bg: #0B0E13;
  --panel: #171D26;
  --panel-2: #1E2530;
  --line: #2A323F;
  --text: #EDEFF4;
  --muted: #838C9E;
  /* Drei Zustandsfarben, klar getrennt von der
     Akzentfarbe. --accent bleibt ausschließlich für Interaktion (Knöpfe,
     Auswahl, Marke, Hervorhebung) — keine Zustandsanzeige mehr. Kontrast
     gegen --panel/--bg per hygiene.test.mjs geprüft (WCAG >= 4.5:1). */
  --accent: #f5ab3d;
  --state-ok: #2FBF71;
  --state-danger: #F0555A;
  --state-caution: #F2C94C;
  --neutral-progress: #4B5566;
  --gray: #c9c9c9;
  --octopus-blue: #4A6CF7;
  /* Drei Skill-Farben für Icon/Chip-Streifen und Hervorhebung — eigene
     Tokens, getrennt von den Zustandsfarben und den Avatar-Farben. Rein
     dekorativ, keine Status-Bedeutung. Verkauf ist Pink statt Türkis, das alte Türkis lag zu nah am Frei-Grün. */
  --topic-billing: #5B8DEF;
  --topic-tech: #A78BFA;
  --topic-sales: #F472B6;
  /* Höhe der Fußleiste. Wird unten von .screen abgezogen, damit die Leiste
     bei kurzen Bildschirminhalten genau am unteren Rand sitzt statt darunter. */
  --footer-h: 34px;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html, body { height: 100%; }

body {
  margin: 0;
  background: radial-gradient(1200px 800px at 50% -10%, #151B24 0%, var(--bg) 60%);
  color: var(--text);
  font-family: 'Ubuntu', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  display: flex;
  justify-content: center;
  overscroll-behavior: none;
  user-select: none;
  -webkit-user-select: none;
}

#shell {
  width: 100%;
  max-width: 480px;
  min-height: 100vh;
  min-height: 100dvh;
}

.screen {
  display: none;
  flex-direction: column;
  padding: 12px 12px 20px;
  min-height: calc(100vh - var(--footer-h));
  min-height: calc(100dvh - var(--footer-h));
}
.screen.active { display: flex; }

/* --------------------------------------------------------------------------
   Fußleiste mit dem Nutzungshinweis
   Bewusst auf allen Bildschirmen sichtbar. Der kurze Satz ist anklickbar und
   öffnet den vollständigen Hinweis im vorhandenen Dialog.
   -------------------------------------------------------------------------- */
#app-footer {
  min-height: var(--footer-h);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 12px calc(env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: rgba(11, 14, 19, .85);
  flex-wrap: wrap;
}
.disclaimer-btn {
  background: none;
  border: none;
  padding: 8px 4px;
  margin: 0;
  color: var(--muted);
  font-family: inherit;
  font-size: 10px;
  line-height: 1.3;
  letter-spacing: .02em;
  text-align: center;
  cursor: pointer;
  text-decoration: underline dotted var(--line);
  text-underline-offset: 3px;
}
.disclaimer-btn:hover { color: var(--text); }

/* Impressum-Link im Footer, teilt sich die Optik mit dem Disclaimer-Knopf.
   Als <a> statt <button>, deshalb display:inline-block für Padding/Klickflaeche. */
.footer-sep {
  color: var(--line);
  font-size: 10px;
  padding: 0 2px;
}
a.footer-link {
  display: inline-block;
  text-decoration-style: dotted;
}
a.footer-link:visited { color: var(--muted); }

h1 {
  font-size: 13px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 4px 4px 10px;
  font-weight: 500;
}

/* --------------------------------------------------------------------------
   Fokus-Sichtbarkeit (Tastaturbedienung)
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Utilities (ersetzen die früheren Inline-Styles)
   -------------------------------------------------------------------------- */
/* ACHTUNG bei diesen Utilities: Sie stehen im Stylesheet VOR den
   Komponenten-Klassen. Bei gleicher Spezifität gewinnt die spätere Regel —
   deshalb sind die drei Utilities, die eine Komponenten-Eigenschaft
   überschreiben müssen (.inline-btn, .round-btn, .clickable), bewusst als
   Kombi-Selektor geschrieben. Sonst greifen sie nicht. */
.hidden { display: none !important; }
.mt-18 { margin-top: 18px; }
.mb-4 { margin-bottom: 4px; }
.mb-6 { margin-bottom: 6px; }
.no-top-margin { margin-top: 0 !important; }
.d-badge.clickable { cursor: pointer; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Sekundär-Knopf, der sich an seinen Inhalt anpasst statt die volle Breite
   zu nehmen (z. B. der Diabolo-Store-Knopf in der Budget-Zeile). */
.secondary-btn.inline-btn {
  width: auto;
  flex: 0 0 auto;
  padding: 10px 14px;
  margin-top: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.primary-btn {
  width: 100%;
  padding: 14px;
  border: none;
  border-radius: 10px;
  background: var(--accent);
  color: #2A1600;
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  font-family: inherit;
}
.primary-btn:disabled { opacity: .4; cursor: not-allowed; }

.secondary-btn {
  width: 100%;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--text);
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  margin-top: 8px;
  font-family: inherit;
}

.link-btn {
  width: 100%;
  margin-top: 10px;
  padding: 8px;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 12px;
  text-decoration: underline;
  cursor: pointer;
  font-family: inherit;
}

/* Jetzt 5 Sprachknöpfe (DE/EN/FR/ES/PT) statt 3 — flex-wrap verhindert ein
   Überlaufen auf sehr schmalen Bildschirmen, kleineres Padding/Gap sorgt
   dafür, dass alle fünf normalerweise trotzdem in einer Zeile bleiben. */
.lang-switch { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
/* Sprachleiste im Zahnrad-Menue: linksbündig und mit etwas Luft nach unten,
   damit sie sich von den Menue-Einträgen darunter absetzt. */
.popover-lang { justify-content: flex-start; padding: 4px 12px 8px; }
.popover-label {
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 6px 12px 4px;
}
.lang-btn {
  padding: 4px 7px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
}
.lang-btn.active { border-color: var(--accent); color: var(--accent); }

/* --------------------------------------------------------------------------
   Name-Screen
   -------------------------------------------------------------------------- */
.name-card {
  margin: auto;
  width: 100%;
  max-width: 340px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 26px;
  text-align: center;
}
.name-card .lang-switch { margin-bottom: 14px; }
.name-card h1 {
  margin: 0 0 6px;
  font-size: 20px;
  color: var(--text);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 700;
}
.name-card .lead { color: var(--muted); font-size: 13px; margin: 0 0 18px; }

#name-input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  font-size: 16px; /* 16px verhindert den Auto-Zoom auf iOS */
  margin-bottom: 14px;
  font-family: inherit;
}
#name-input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }

/* --------------------------------------------------------------------------
   Start-Screen
   -------------------------------------------------------------------------- */
.start-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 12px;
}
.player-name { font-size: 18px; font-weight: 700; }
.player-name-row { display: flex; align-items: center; gap: 8px; position: relative; }
.player-name-btn {
  font-size: 18px;
  font-weight: 700;
  background: none;
  border: none;
  color: var(--text);
  padding: 0;
  cursor: pointer;
  text-decoration: underline dotted var(--muted);
  text-underline-offset: 3px;
  font-family: inherit;
}
.gear-btn {
  background: none;
  border: none;
  font-size: 18px;
  cursor: pointer;
  padding: 2px;
  min-width: 44px;
  min-height: 44px;
  line-height: 1;
  opacity: .8;
}
.settings-popover {
  display: none;
  position: absolute;
  z-index: 15;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 6px;
  margin: -6px 0 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
}
.settings-popover.show { display: block; }
.popover-item {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  font-size: 13px;
  padding: 9px 12px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  font-family: inherit;
}
.popover-item:hover { background: var(--panel-2); }
.popover-item.danger { color: var(--state-danger); }
.popover-sep { height: 1px; background: var(--line); margin: 6px 4px; }
#confirm-yes-btn.danger { background: var(--state-danger); border-color: var(--state-danger); color: #fff; }

.start-best { text-align: right; }
.trained-badge { font-size: 10px; margin-left: 4px; flex-shrink: 0; white-space: nowrap; }
.stat-label {
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
  font-weight: 500;
}
.stat-value {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}
.budget-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 16px;
}
/* Betrag und Währungskürzel dürfen nie umbrechen ("0" / "ST" untereinander). */
.budget-row .stat-value { color: var(--accent); white-space: nowrap; }
.start-best .stat-value, #store-budget-display { white-space: nowrap; }
/* "Weiter mit": der nächste sinnvolle Auftrag, groß und mit eigenem Play-Knopf. */
.continue-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: -4px 0 16px;
  padding: 14px;
  border-radius: 14px;
  background: var(--panel);
  border: 2px solid var(--accent);
}
.continue-card[hidden] { display: none; }
.continue-main { min-width: 0; }
.continue-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--accent);
}
.continue-title { font-weight: 700; font-size: 16px; margin: 2px 0; }
.continue-goal { font-size: 12px; color: var(--muted); }
.continue-play { width: 52px; height: 52px; font-size: 20px; }

.storage-warning {
  margin: 12px 4px 0;
  font-size: 11px;
  line-height: 1.4;
  color: var(--state-caution);
  border: 1px solid var(--state-caution);
  border-radius: 8px;
  padding: 8px 10px;
  background: rgba(242, 201, 76, .08);
}
.storage-warning[hidden] { display: none; }

/* Versionsnummer, klein und unaufdringlich am Fuß des Start-Screens. */
.app-version-tag {
  margin: 10px 4px 0;
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  opacity: .6;
}

.tech-badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.tech-badge {
  font-family: inherit; cursor: pointer;
  font-size: 10px;
  padding: 3px 8px;
  border-radius: 20px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--muted);
}
.tech-badge.active { color: var(--accent); border-color: var(--accent); }
.tech-badge.outage {
  text-decoration: line-through;
  color: var(--state-danger);
  border-color: var(--state-danger);
}

/* auto-fill packt so viele 72px-Spalten wie möglich in die 480px breite Shell.
   Die Einstellen-Kachel (.add-chip) belegt eine weitere Spalte — bei vollem Team (8) entfällt sie. */
#roster-preview {
  display: grid;
  /* Mindestbreite 72px, damit das Tier-Tag ("TRAINEE") nicht abschneidet. */
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 8px;
  margin-bottom: 16px;
}
/* Auf schmalen Bildschirmen fest fünf Spalten: vier Mitarbeiter plus die Einstellen-Kachel
   stehen in einer Zeile, statt dass die Kachel allein in eine zweite Zeile rutscht. */
@media (max-width: 480px) {
  #roster-preview { grid-template-columns: repeat(5, minmax(0, 1fr)); column-gap: 6px; }
  /* Name in eigener Zeile, Themen-Icons darunter: nebeneinander blieben vom Namen nur 1-2 Buchstaben. */
  #roster-preview .roster-chip .roster-name-row { flex-wrap: wrap; row-gap: 0; }
  #roster-preview .roster-chip .roster-name-row .roster-name { flex: 0 0 100%; }
}
.roster-chip {
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 6px 2px;
  text-align: center;
  font-size: 11px;
  cursor: default;
  overflow: hidden;
  position: relative;
  min-height: 44px;
}
.roster-chip[data-index] { cursor: pointer; }
.roster-chip .roster-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Derselbe geteilte Skill-Avatar wie die Mitarbeiterkarte (ui/avatar.js), nur
   kleiner (.size-sm) -- ersetzt die Skill-Icons neben dem Namen. */
.roster-chip .roster-avatar-row { display: flex; justify-content: center; margin-bottom: 2px; }
.roster-chip .roster-name-row { display: flex; align-items: center; justify-content: center; gap: 2px; min-width: 0; }
.roster-chip .roster-name-row .roster-name { flex: 0 1 auto; min-width: 0; }
.roster-chip .tier-tag {
  padding: 2px 3px;
  letter-spacing: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  display: block;
}
.roster-chip.upgradeable {
  border-color: var(--accent);
  cursor: pointer;
  box-shadow: 0 0 0 2px rgba(245, 171, 61, .45);
}
/* Ein Mitarbeiter, für den es noch etwas zu kaufen gibt, ist anklickbar —
   auch wenn das Budget dafür gerade nicht reicht: der Weg soll sichtbar
   bleiben, der Dialog zeigt dann deaktivierte Einträge mit Preis. */
.roster-chip.has-options { cursor: pointer; }

/* Einstellen-Kachel am Ende des Teams. Gleiche Grundform wie ein
   Mitarbeiter-Chip, damit das Raster nicht springt. */
.add-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-style: dashed;
  cursor: pointer;
  color: var(--muted);
  min-height: 52px;
}
.add-chip .add-plus { font-size: 18px; font-weight: 700; line-height: 1; color: var(--accent); }
/* Verb über dem Preis: Normalschreibung, damit es auch in den langen Sprachen in die schmale Kachel passt. */
.add-chip .add-verb {
  font-size: 10px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.add-chip .add-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
/* Dieselbe Sprache wie die gesperrte Auftragskarte — der gestrichelte
   Rahmen ist schon die Grundform von .add-chip, hier kommt nur die leise
   Schraffur dazu. */
.add-chip.locked {
  opacity: 1;
  background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.03) 0 8px, transparent 8px 16px);
}
.add-chip.locked .add-plus { color: var(--muted); font-size: 15px; }
.add-chip.affordable { border-color: var(--accent); border-style: solid; box-shadow: 0 0 0 2px rgba(245, 171, 61, .14); }

.tier-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: 2px 6px;
  border-radius: 5px;
  margin-top: 2px;
  /* In einer Flex-Zeile (Mitarbeiterkarte, .agent-top) darf das Tag nicht schrumpfen —
     sonst brechen seine Buchstaben um, statt dass ihm ein Geschwister-Element Platz macht. */
  flex-shrink: 0;
}
.tier-tag.tier-trainee { background: rgba(201, 201, 201, .15); color: var(--gray); }
.tier-tag.tier-experienced { background: rgba(75, 85, 102, .35); color: #B7C0CE; }
.tier-tag.tier-expert { background: rgba(245, 171, 61, .18); color: var(--accent); }
.tier-tag.tier-veteran { background: rgba(74, 108, 247, .18); color: var(--octopus-blue); }
.tier-tag.in-agent-card { margin-top: 0; padding: 1px 5px; }

#contract-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
/* "Karte ganz oben" ganz ohne die Array-Position (und damit die
   Level-Nummerierung, "idx+1" in start-screen.js) der übrigen Karten
   anzufassen — order:-1 wirkt nur auf die visuelle Reihenfolge im Flexbox. */
.daily-card { order: -1; }
.contract-card {
  background: var(--panel);
  border: 2px solid var(--line);
  border-radius: 14px;
  padding: 14px;
  cursor: pointer;
}
/* Keine Kartenauswahl — gestartet wird direkt am Play-Knopf der Karte. */
.contract-card { cursor: default; }
/* Ein gesperrter Auftrag ist kein Fehler, sondern ein Ziel — gestrichelter
   Rahmen und eine sehr leise diagonale Schraffur lesen sich als "abgesperrt",
   ohne die Karte unleserlich zu machen (opacity zurück auf 1). */
.contract-card.locked {
  cursor: not-allowed;
  opacity: 1;
  border-style: dashed;
  border-color: var(--line);
  background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.03) 0 8px, transparent 8px 16px);
}
/* Sitzt exakt dort, wo eine freie Karte ihren Play-Knopf hat — gleiche
   Größe, gleiche Position, damit auf einen Blick sichtbar ist, was fehlt. */
.lock-slot {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 2px dashed var(--muted);
  color: var(--muted);
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.c-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.c-head-main { min-width: 0; }
/* Kompakte Zeile: die ganze Fläche links vom Play-Knopf klappt die Details auf. */
.contract-card.compact { padding: 8px 10px 8px 14px; }
.contract-card.compact .c-head { align-items: center; }
.c-toggle {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.c-line1, .c-line2 { display: flex; align-items: center; gap: 8px; min-width: 0; }
.contract-card.compact .c-level, .contract-card.compact .c-title { margin-bottom: 0; }
.contract-card.compact .c-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c-line2 .c-stars { margin-top: 0; flex-shrink: 0; }
.c-lock-need { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-volume {
  font-size: 10px;
  color: var(--text);
  background: var(--panel-2);
  border-radius: 6px;
  padding: 1px 6px;
  white-space: nowrap;
}
.c-volume-line { font-size: 11px; color: var(--text); margin-bottom: 6px; }
/* Stufen-Chips der Auftragskarte: gewählt = Akzentrand, gesperrt = gedämpft, aber tippbar (erklärt sich per Hinweis). */
.c-stages { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0 4px; }
.stage-chip {
  min-height: 36px;
  padding: 4px 12px;
  border-radius: 999px;
  border: 2px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  cursor: pointer;
}
.stage-chip.selected { border-color: var(--accent); color: var(--accent); }
.stage-chip.locked { color: var(--muted); border-style: dashed; }
.c-details { padding: 8px 0 4px; }
.c-details[hidden] { display: none; }
.contract-card.open { border-color: var(--neutral-progress); }
.contract-group {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin: 8px 4px 0;
}
/* Der Play-Knopf ist die einzige Startmöglichkeit und darf deshalb nicht
   übersehen werden: Akzentfarbe, rund, mindestens 44px Trefferfläche. */
.play-btn {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #2A1600;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0 0 2px; /* das Dreieck wirkt sonst nach links versetzt */
  transition: transform .1s ease, box-shadow .15s ease;
}
.play-btn:hover { box-shadow: 0 0 0 4px rgba(245, 171, 61, .18); }
.play-btn:active { transform: scale(.94); }
.contract-card .c-level {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--accent);
  margin-bottom: 4px;
}
.contract-card .c-title { font-weight: 700; font-size: 15px; margin-bottom: 4px; }
.risk-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
  margin-bottom: 6px;
}
/* Farbe allein unterscheidet die drei Stufen nicht zuverlässig
   genug (Farbfehlsichtigkeit) — jede Stufe bekommt zusätzlich eine eigene
   Form. .good bleibt der Kreis aus border-radius, .medium/.bad überschreiben
   die Kontur per clip-path (das hat Vorrang vor border-radius). */
.risk-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.risk-dot.good { background: var(--state-ok); }
.risk-dot.medium {
  background: var(--state-caution);
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
.risk-dot.bad {
  background: var(--state-danger);
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
.contract-card .c-desc { color: var(--muted); font-size: 12px; margin-bottom: 8px; }
.c-unlock { margin-bottom: 4px; }
.c-unlock-text { font-size: 11px; color: var(--muted); margin-bottom: 6px; }
.c-unlock-text b { color: var(--text); }
.c-unlock-track { height: 5px; background: #0B0D13; border-radius: 3px; overflow: hidden; }
.c-unlock-fill { height: 100%; background: var(--neutral-progress); border-radius: 3px; transition: width .3s ease; }
/* Ab 70% wechselt der Balken auf die Akzentfarbe — der Moment, in dem sich
   ein weiterer Versuch am ehesten lohnt (Freigabe Matthias). */
.c-unlock-fill.near { background: var(--accent); }
.contract-card .c-meta {
  display: flex;
  gap: 14px;
  font-size: 11px;
  color: var(--muted);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  flex-wrap: wrap;
}
.contract-card .c-meta b { color: var(--text); }

/* --------------------------------------------------------------------------
   Store
   -------------------------------------------------------------------------- */
.store-header-row { display: flex; align-items: center; gap: 10px; }
.d-badge {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
  padding: 0;
  border: none;
  background: none;
  cursor: default;
  display: block;
}
.d-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }
.d-badge.small { width: 20px; height: 20px; border-radius: 5px; }

.store-section { margin-bottom: 20px; }
.store-item {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px;
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.store-item.locked { opacity: .55; }
.store-item-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.store-item-title { font-weight: 700; font-size: 14px; }
.store-item-title-row { display: flex; align-items: center; gap: 6px; }
/* Überschrift plus Info-Knopf in einer Zeile. Der Knopf trägt die
   Begründung für die Benennung "Servicemitarbeiter" — bewusst ein Knopf und
   kein title-Tooltip, weil die App Mobile-First ist und dort niemand hovert. */
.section-head {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.section-head h1 { margin-right: 0; }

.info-btn {
  background: none;
  border: none;
  font-size: 13px;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  opacity: .85;
}
.store-item-desc { color: var(--muted); font-size: 12px; margin-top: 2px; }
.store-item-effect { color: #B7C0CE; font-size: 11px; margin-top: 4px; font-style: italic; }
.store-item-level {
  font-size: 10px;
  color: var(--muted);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  margin-top: 2px;
}
.buy-btn {
  flex-shrink: 0;
  padding: 9px 14px;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: #2A1600;
  font-weight: 700;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
  font-family: inherit;
}
.buy-btn:disabled { background: var(--panel-2); color: var(--muted); cursor: not-allowed; }

/* --------------------------------------------------------------------------
   Auswahl-Dialog
   Ein Eintrag = eine kaufbare Sache. Deaktivierte Einträge bleiben sichtbar
   (mit Preis), damit der nächste Schritt erkennbar ist, statt zu verschwinden
   — dasselbe Muster wie die deaktivierten Kauf-Knöpfe im Store.
   -------------------------------------------------------------------------- */
.choice-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 6px; text-align: left; }
.choice-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.choice-item:disabled { opacity: .5; cursor: not-allowed; }
.choice-item-main { min-width: 0; }
/* Titel und Zusatzzeile untereinander — beide sind <span> (ein <button> darf
   nur Phrasing-Inhalt tragen), brauchen also eine eigene Zeilenschaltung. */
.choice-item-title, .choice-item-meta { display: block; }
.choice-item-title { font-weight: 700; font-size: 13px; }
.choice-item-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.choice-item-price {
  flex-shrink: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}
.choice-item:disabled .choice-item-price { color: var(--muted); }
/* Erster Tipp bewaffnet den Eintrag statt einen zweiten
   Dialog zu öffnen (siehe dialogs.js/setChoiceConfirming()). --accent ist
   hier folgerichtig, weil sie im Farbsystem ausschließlich für
   Interaktion reserviert ist — genau das ist ein bewaffneter Kauf. */
.choice-item.confirming {
  border-color: var(--accent);
  border-style: solid;
  box-shadow: 0 0 0 2px rgba(245, 171, 61, .14);
}
.choice-item.confirming .choice-item-price {
  background: var(--accent);
  color: #2A1600;
  padding: 3px 8px;
  border-radius: 6px;
}
/* Zwischenüberschrift, seit der Erweiterungs-Dialog bis zu sieben Einträge
   hat. Erste Überschrift ohne oberen Abstand. */
.choice-group {
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 6px 2px 0;
}
.choice-group:first-child { margin-top: 0; }

body.shift-active #app-footer { display: none; }

/* --------------------------------------------------------------------------
   Spiel-Screen — feste Bühne
   Sieben Grid-Reihen mit fester (bzw. gedeckelter) Höhe statt einer Seite,
   die wächst und ab einer bestimmten Teamgröße scrollen musste. Reihenfolge:
   Kopf -> Kontextzeile -> Ausfall-Hinweis -> Warteschlange -> Hinweis ->
   Mitarbeiter -> Werkzeugleiste (unten, in Daumenreichweite).
   -------------------------------------------------------------------------- */
#screen-game.active {
  display: grid;
  grid-template-rows: 46px 20px auto 75px 27px 1fr calc(63px + env(safe-area-inset-bottom));
  row-gap: 1px;
  height: 100vh;
  height: 100dvh;
  /* Auf einem hohen Desktop-Fenster nicht zu einem sehr hohen, schmalen Streifen werden. */
  max-height: 900px;
  min-height: 0;
  padding: 7px 10px 0;
  overflow: hidden;
  position: relative;
}
#screen-game h1 { margin: 0 2px 2px; font-size: 10px; }
/* #outage-notice ist meistens display:none (kein Ausfall) — ein
   display:none-Element erzeugt in CSS Grid gar kein Grid-Item
   und wird von der automatischen Zeilenzuordnung komplett übersprungen.
   Ohne feste Zeilennummern rücken dann alle folgenden Bereiche eine Zeile
   nach oben: die Mitarbeiterkarten landen in der 82px-Zeile der Warteschlange
   statt in der flexiblen Rest-Zeile, während #hint die ganze übrige Höhe
   bekommt. Explizite grid-row je Bereich hält die sieben Zeilen fest, ganz
   unabhängig davon, ob der Ausfall-Hinweis gerade sichtbar ist. */
#screen-game.active > .game-header-bar { grid-row: 1; }
#screen-game.active > #context-row { grid-row: 2; }
#screen-game.active > #outage-notice { grid-row: 3; }
#screen-game.active > #queue-section { grid-row: 4; }
#screen-game.active > #hint { grid-row: 5; }
#screen-game.active > #agents-section { grid-row: 6; }
#screen-game.active > .game-toolbar { grid-row: 7; }

/* --- Kopfleiste: vier Kennzahlen inline + Info-Knopf + Fortschrittsbalken - */
.game-header-bar {
  height: 46px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
}
.game-header-row { display: flex; align-items: center; gap: 6px; }
.wb-cell { flex: 1 1 0; min-width: 0; text-align: center; }
.game-header-bar .stat-label {
  font-size: 10px;
  margin: 0 0 1px;
  letter-spacing: .05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.game-header-bar .stat-value { font-size: 14px; line-height: 1.1; }
/* Serien-Badge neben dem Score. .hidden (JS) blendet es
   aus, solange S.streak < 3 ist. Der kurze "Bump" beim Erreichen von 5/10
   nutzt eine normale CSS-Animation und wird deshalb automatisch von der
   globalen prefers-reduced-motion-Regel weiter unten gekappt — kein
   zusätzlicher JS-Guard nötig (siehe game-screen.js render()). */
.streak-badge { display: inline-block; margin-left: 4px; font-size: 12px; vertical-align: middle; }
.streak-badge.streak-bump { animation: streak-bump-pop .4s ease; }
@keyframes streak-bump-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.5); }
  100% { transform: scale(1); }
}
.header-info-btn {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: none;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  opacity: .85;
}
.game-header-progress { height: 3px; background: #0B0D13; border-radius: 2px; overflow: hidden; }
.game-header-progress-fill { height: 100%; width: 0%; background: var(--accent); transition: width .2s linear; }
/* Blitzt einmal beim Wellenwechsel (ui/milestones.js); fällt wie streak-bump-pop
   automatisch unter die globale prefers-reduced-motion-Regel. */
.game-header-progress-fill.wave-flash { animation: wave-flash-pop .5s ease; }
@keyframes wave-flash-pop {
  0% { filter: brightness(1); }
  40% { filter: brightness(2.2); }
  100% { filter: brightness(1); }
}

#time-value.risk { color: var(--state-caution); }
#time-value.bad { color: var(--state-danger); }
#sla-value.good { color: var(--state-ok); }
#sla-value.risk { color: var(--state-caution); }
#sla-value.bad { color: var(--state-danger); }

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }

/* Blink-Budget: die Farbe oben gilt immer, der Puls nur,
   wenn render() (game-screen.js) genau diese Stufe als die aktuell
   wichtigste Warnung ausgewählt hat (#screen-game[data-alert="…"]) — nach
   fester Rangfolge danger > acd > sla > time > stress blinkt so nie mehr
   als eine Anzeige gleichzeitig. */
#screen-game[data-alert="sla"] #sla-value.risk { animation: pulse 1s infinite; }
#screen-game[data-alert="sla"] #sla-value.bad { animation: pulse .5s infinite; }
#screen-game[data-alert="time"] #time-value.bad { animation: pulse .8s infinite; }

/* --- Kontextzeile + Ausfall-Hinweis ----------------------------------------- */
/* Eine feste Zeile direkt unter der Kopfzeile: links Auftrag und Ziel (bzw. Welle, Nachlauf), rechts der
   Coaching-Zähler. Banner stehen nicht hier, sondern in der Überschrift der Warteschlange. */
#context-row { position: relative; min-height: 0; }
#shift-subtitle {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  color: var(--muted);
  margin: 0 2px;
  white-space: nowrap;
}
#context-line { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#coach-counter { flex: 0 0 auto; font-weight: 700; }
#coach-counter.done { opacity: .45; }
#coach-counter.warn { color: var(--state-danger); }
/* 0px, solange nichts ausfällt: display:none auf der Zeile selbst lässt
   die auto-hohe Grid-Reihe auf 0 zusammenfallen. */
.outage-notice {
  display: none;
  align-items: baseline;
  gap: 5px;
  font-size: 10px;
  color: var(--state-danger);
  white-space: nowrap;
  overflow: hidden;
}
.outage-notice.show { display: flex; }
#lbl-game-tech { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; flex-shrink: 0; }
#game-tech-badges { overflow: hidden; text-overflow: ellipsis; }

/* --- Werkzeugleiste unten: ein eigenes Dock ------------------------------- */
/* Volle Breite, eigener Hintergrund (--panel-2, die Karten nutzen --panel), Trennlinie oben und 12px Abstand zu
   den Karten (2px Zeilenabstand + 10px Außenabstand). Die Knöpfe sind Pillen und teilen sich die Breite zu
   gleichen Teilen: grid-auto-flow:column plus grid-auto-columns:1fr heißt zugleich, dass ausgeblendete Knöpfe
   (ACD bis zum Kauf, Rückgängig, Überspringen) keine leere Spalte hinterlassen. */
.game-toolbar {
  margin: 11px -10px 0;
  padding: 5px 10px calc(6px + env(safe-area-inset-bottom));
  background: var(--panel-2);
  border-top: 1px solid var(--line);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  grid-template-rows: 1fr;
  gap: 8px;
}
.tool-btn {
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 8px;
  border-radius: 999px;
  border: 2px solid var(--line);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  transition: border-color .15s ease, box-shadow .15s ease, opacity .2s ease;
}
.tool-btn[hidden] { display: none; }
.tool-icon {
  position: relative;
  height: 16px;
  font-size: 14px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.tool-caption {
  font-size: 10px;
  font-weight: 700;
  line-height: 1.1;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Laufende ACD: grüner Lauflicht-Rahmen (conic-gradient als Rahmen, eine Umdrehung je 2 s), die Beschriftung zeigt die
   Restzeit groß in Grün; in den letzten Sekunden (#screen-game.acd-ending) wird beides gelb. Das Lauflicht ist die
   einzige Dauerbewegung in der Leiste. Ohne @property-Unterstützung bleibt der Rahmen statisch grün. */
@property --acd-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
#planner-btn.active {
  --acd-c: var(--state-ok);
  border-color: transparent;
  background:
    linear-gradient(var(--panel), var(--panel)) padding-box,
    conic-gradient(from var(--acd-angle), var(--acd-c), color-mix(in srgb, var(--acd-c) 15%, var(--line)) 70%, var(--acd-c)) border-box;
  animation: acd-spin 2s linear infinite;
}
#screen-game.acd-ending #planner-btn.active { --acd-c: var(--state-caution); }
#planner-btn.active #planner-caption { font-size: 15px; color: var(--acd-c); }
@keyframes acd-spin { to { --acd-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) {
  #planner-btn.active { animation: none; background: var(--panel); border-color: var(--acd-c); }
}
.tool-btn.used { opacity: .45; cursor: not-allowed; animation: none; }

.joker-icon-wrap { position: relative; }
.octopus-icon { height: 18px; width: auto; max-width: 15px; object-fit: contain; display: block; }
.joker-used-badge {
  display: none;
  position: absolute;
  top: -5px;
  right: -6px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--state-danger);
  color: #fff;
  font-size: 10px;
  line-height: 15px;
  text-align: center;
  font-weight: 700;
}
/* Grüne Umrandung, solange eine sinnvolle Nutzung möglich ist — also eine
   Ladung übrig UND jemand krank oder in Zwangspause. Verschwindet von selbst,
   sobald das nicht mehr gilt. Steht bewusst VOR .armed, damit ein
   scharfgeschalteter Joker sein Aussehen behält (Kaskaden-Reihenfolge). */
/* Siehe Kommentar bei .call-chip — gleicher Grund. Zusätzlich
   das native Bild-Ziehen des Octopus-Icons abschalten (draggable="false" im
   Markup reicht in Chromium, -webkit-user-drag deckt Safari ab) — sonst
   übernimmt der Browser die Geste als HTML5-Bild-Drag und unsere
   Pointer-Events bleiben aus (beobachtet beim Testen: nach dem ersten
   pointermove kam kein weiteres mehr an). */
#joker-btn { touch-action: none; }
#joker-btn .octopus-icon { -webkit-user-drag: none; user-select: none; }
#joker-btn.has-target {
  border-color: var(--state-ok);
  box-shadow: 0 0 0 3px rgba(47, 191, 113, .28);
}

#joker-btn.armed {
  border-color: var(--neutral-progress);
  box-shadow: 0 0 0 3px rgba(75, 85, 102, .35);
  animation: pulse 1.2s infinite;
}
.tool-btn.used .octopus-icon { filter: grayscale(1) brightness(.6); }
.tool-btn.used .joker-used-badge { display: block; }
.tool-btn.used .joker-label { text-decoration: line-through; }

/* --- Warteschlange: hält ihre 82px-Reihe komplett aus -------------------- */
#queue-section { display: flex; flex-direction: column; min-height: 0; position: relative; }
#queue-section .queue-head { flex: 0 0 auto; margin: 0 2px 3px; align-items: baseline; justify-content: space-between; }
#queue-section .queue-head h1 { margin: 0; }
/* Banner-Platz rechts in der Überschriftzeile: Serie, Welle und Platzwechsel teilen sich ihn, sichtbar ist
   immer eines (Vorrang Platzwechsel vor Welle vor Serie). Die Zeilenhöhe bleibt konstant. */
#queue-section .queue-head { height: 14px; align-items: center; }
#queue-banner-slot { position: relative; flex: 1 1 auto; min-width: 0; height: 14px; margin-left: 8px; }
#queue-banner-slot:has(> .seat-banner.show) > .milestone-banner { visibility: hidden; }

/* Meilenstein- und Platzwechsel-Banner: einzeilig, rechtsbündig im Banner-Platz der Warteschlangen-Überschrift.
   Nur Einblenden, kein Ausblenden: sobald .show fehlt, ist das Banner sofort weg.
   pointer-events:none, die Warteschlange bleibt bedienbar. */
.milestone-banner,
.seat-banner {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: none;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  padding: 0 6px;
  overflow: hidden;
  border-radius: 7px;
  background: var(--bg);
  pointer-events: none;
  white-space: nowrap;
  color: var(--text);
  font-weight: 700;
  font-size: 11px;
  line-height: 14px;
}
.milestone-banner > div { overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 0 1 auto; }
.milestone-banner > div:first-child { flex-shrink: 0; }
.milestone-banner > div + div { font-weight: 400; color: var(--muted); }
.milestone-banner:empty { display: none !important; }
.milestone-banner.show { display: flex; animation: banner-in .25s ease-out; }
.seat-banner { border: 1px solid var(--accent); z-index: 45; }
.seat-banner > span { overflow: hidden; text-overflow: ellipsis; }
.seat-banner.show { display: flex; animation: banner-in .25s ease-out; }
@keyframes banner-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .milestone-banner.show, .seat-banner.show { animation: none; }
}
/* Rückgängig-Knopf in der Leiste: Countdown-Ring um das Symbol, --undo-progress (0 bis 1) setzt seats-ui.js per CSSOM. */
.seat-undo-btn { border-color: var(--accent); }
.seat-undo-btn .tool-icon::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--undo-progress, 1) * 360deg), var(--line) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1.5px));
}
.tool-btn:disabled { opacity: .45; cursor: not-allowed; }
.pause-abort-btn { border-color: var(--state-danger); color: var(--state-danger); }
/* MAX_QUEUE_SLOTS ist die einzige Quelle für die Spaltenzahl — app.js setzt
   --queue-cols daraus, der Fallback 5 hält die Darstellung intakt, falls das
   Skript nicht läuft. grid-auto-rows:minmax(0,1fr) lässt die (einzige)
   Zeile die komplette Resthöhe von #queue-section füllen. */
#queue {
  /* Bezugsrahmen für den absolut positionierten
     .hangup-Klon (showHangupChip() in game-screen.js) — ohne dieses
     position:relative wäre er relativ zu einem weiter außen liegenden
     Vorfahren positioniert und träfe nicht die Chip-Position. */
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(var(--queue-cols, 5), 1fr);
  grid-auto-rows: minmax(0, 1fr);
  gap: 6px;
}
/* Chips und Karten sind Schaltflächen; deren Innenleben besteht aus span-Elementen und braucht hier die Blockdarstellung. */
.call-chip .bar-track, .call-chip .bar-fill, .call-chip .chip-label,
.agent-card .stress-track, .agent-card .stress-fill, .agent-card .agent-bar-fill,
.agent-card .agent-load-track, .agent-card .agent-load-fill { display: block; }
button.call-chip, button.agent-card {
  font: inherit;
  color: inherit;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
}
button.call-chip { padding: 0; }
button.agent-card { text-align: left; }
/* Fokus der Tastaturbedienung: Akzentrahmen mit Abstand, damit er neben Auswahl-, Skill- und Statusrahmen lesbar bleibt. */
.call-chip:focus-visible, .agent-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 14px;
}
.call-chip {
  height: auto;
  min-height: 0;
  background: var(--panel-2);
  border: 2px solid var(--line);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  cursor: pointer;
  position: relative;
  transition: transform .1s ease, border-color .15s ease;
  /* Verhindert das Scrollen/Zoomen der Seite während des
     Ziehens auf Touch-Geräten (sonst kapert der Browser die Geste). */
  touch-action: none;
}
.call-chip.selected {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 0 0 3px rgba(245, 171, 61, .15);
}
/* Geführte erste Schicht: der erste Führungsschritt hebt genau EINEN Chip
   hervor, unabhängig von .selected (das erst nach dem Antippen greift).
   Derselbe Puls wie .agent-card.free.assignable weiter unten (zweiter Führungsschritt) —
   ein Signal, zwei Stellen, bewusst wiederverwendet statt neu erfunden. */
.call-chip.coach-focus { animation: pulse-glow 1s infinite; }
/* Das Icon ist die Hauptaussage des Chips (das Thema), nicht Dekoration neben Balken/Sekunden. */
.call-chip .icon { font-size: 22px; line-height: 1; }
/* Kundenstimmung als Symbol neben dem Icon. */
.call-chip .icon-row { display: flex; align-items: center; justify-content: center; gap: 3px; }
.call-chip .mood { font-size: 12px; line-height: 1; }
/* Aufleger sichtbar machen: showHangupChip() (game-screen.js) klont den Chip
   vor dem Entfernen, blendet 📵 ein und blitzt kurz rot auf. Die globale
   Regel @media (prefers-reduced-motion: reduce) weiter unten kappt die
   Animation ohnehin auf .001ms — der Klon bleibt trotzdem exakt 400ms sichtbar
   (per setTimeout in JS, nicht animationsgetrieben). */
.call-chip.hangup {
  pointer-events: none;
  cursor: default;
  z-index: 5;
  animation: hangup-flash .4s ease-out forwards;
}
/* Spontan aufgelegt: grau statt rot, der Spieler hat nichts falsch gemacht. */
.call-chip.hangup.hangup-spontaneous { filter: grayscale(1); animation-name: hangup-flash-spontaneous; }
@keyframes hangup-flash-spontaneous {
  0% { border-color: var(--muted); background: var(--muted); }
  100% { border-color: var(--muted); background: var(--panel-2); }
}
@keyframes hangup-flash {
  0% { border-color: var(--state-danger); background: var(--state-danger); }
  100% { border-color: var(--state-danger); background: var(--panel-2); }
}
.call-chip .bar-track {
  width: 70%;
  height: 4px;
  background: #0B0D13;
  border-radius: 3px;
  overflow: hidden;
}
.call-chip .bar-fill {
  height: 100%;
  background: var(--state-ok);
  width: 100%;
  transition: width .1s linear, background .2s ease;
}
.call-chip.urgent .bar-fill { background: var(--state-danger); }
.call-chip.warn .bar-fill { background: var(--state-caution); }
.call-chip.training { background: var(--panel); }
/* Der Trainings-Chip hat einen Balken (die Frist aus TRAINING_IGNORE_DEADLINE_MS
   läuft sichtbar ab), bleibt aber bewusst neutral statt gruen/gelb/rot: ein
   Training ist nachrangig und soll nicht mit echten Anrufen um Aufmerksamkeit
   konkurrieren. render() setzt für Trainings deshalb keine .warn/.urgent-Klassen. */
.call-chip.training .bar-fill { background: var(--neutral-progress); }
.call-chip.callback { border-color: var(--neutral-progress); }
/* Scherzanruf: gestrichelter grauer Rahmen, ohne Warnfarben und ohne Skill-Streifen. */
.call-chip.prank { background: var(--panel); border: 2px dashed var(--neutral-progress); }
.call-chip.prank .bar-fill { background: var(--neutral-progress); }
.call-chip.prank .chip-label { font-size: 8px; letter-spacing: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 3px; box-sizing: border-box; }
/* Wiederanruf (Fachwissen). Warnfarbener Rahmen — anders als ein Rückruf ist
   er kein Angebot an den Kunden, sondern die Folge eines nicht abschließend
   gelösten Gesprächs. */
.call-chip.repeat { border-color: var(--state-caution); }
/* 3px Farbstreifen oben plus eine leichte Tönung des ganzen Chip-Hintergrunds — additiv zu
   .call-chip, nicht bei Training/Rückruf (die tragen keine topic-N-Klasse, siehe
   ensureQueueChip() in game-screen.js). Das Themen-Icon selbst sitzt jetzt als echtes
   .icon-Element im Markup (ensureQueueChip()), nicht mehr als ::before-Inhalt. Muss NACH
   .training/.callback/.repeat stehen, sonst würde deren Hintergrund/Rahmenfarbe hier
   gewinnen statt der Themenfarbe. */
.call-chip.topic-billing { border-top: 3px solid var(--topic-billing); background: rgba(91,141,239,.14); }
.call-chip.topic-tech { border-top: 3px solid var(--topic-tech); background: rgba(167,139,250,.14); }
.call-chip.topic-sales { border-top: 3px solid var(--topic-sales); background: rgba(244,114,182,.14); }
/* Kleines Abzeichen für den Wiederanruf-Zusatzhinweis (🔁) oben links auf dem Chip — das
   Thema bleibt per Haupt-Icon die eigentliche Aussage. */
.call-chip.vip { border-color: #F5C542; box-shadow: 0 0 0 1px #F5C542; }
.chip-badge { position: absolute; top: 3px; left: 4px; font-size: 11px; line-height: 1; }
.call-chip .chip-label {
  font-size: 10px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}
#queue-empty {
  grid-column: 1 / -1;
  color: var(--muted);
  font-size: 11px;
  padding: 8px 0;
  text-align: center;
}
/* Text „+N Wartende“ nur für Screenreader; sichtbar ist das Abzeichen .chip-overflow am letzten Chip. */
#queue-overflow {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.chip-overflow { position: absolute; top: 3px; right: 4px; font-size: 10px; line-height: 1; font-weight: 700; color: var(--state-caution); }

/* --- Mitarbeiter: bekommt den kompletten Rest, gedeckelt bei 120px/Reihe -- */
/* Keine feste Spaltenzahl-Schwelle — zwei Spalten reichen bei fester Bühne
   in jeder gemessenen Kombination aus Team- und Bildschirmgröße. */
#agents-section { display: flex; flex-direction: column; min-height: 0; }
#agents-section .section-head { flex: 0 0 auto; margin: 0 2px 3px; }
#agents {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* Reihen füllen den Platz bis höchstens 120px und schrumpfen bei Platzmangel nicht unter 80px:
     wenige Mitarbeiter bekommen große Karten, acht passen ohne Scrollen. */
  grid-auto-rows: minmax(80px, 120px);
  align-content: start;
  gap: 6px;
}
.agent-card {
  position: relative;
  overflow: hidden;
  background: var(--panel);
  border: 2px solid var(--line);
  border-radius: 14px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
  touch-action: none;
  -webkit-touch-callout: none;
  user-select: none;
  transition: border-color .15s ease, transform .1s ease, opacity .2s ease, box-shadow .15s ease;
}
.agent-card.lifted { transform: scale(1.04); opacity: .6; box-shadow: 0 8px 20px rgba(0, 0, 0, .5); }
/* Freie Mitarbeiter tragen einen grünen Rahmen. Ist ein Anruf ausgewählt, pulsiert er grün (Rückruf, Coaching); bei
   einem Anruf mit Skill übernehmen die match-*-Regeln weiter unten: Haupt-Skill in Skill-Farbe mit Puls, Zweit-Skill
   gestrichelt, fachfremd bleibt grün ohne Puls. Beschäftigt, Pause und krank bekommen keinen grünen Rahmen. */
.agent-card.free {
  border-color: var(--state-ok);
  box-shadow: 0 0 0 2px rgba(47, 191, 113, .18);
}
.agent-card.free.assignable { animation: pulse-glow 1s infinite; }
@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 0 3px rgba(47, 191, 113, .35); }
  50% { box-shadow: 0 0 0 7px rgba(47, 191, 113, .12); }
}
.agent-card.busy { opacity: .88; }
.agent-card.training { opacity: .88; }
.agent-card.on-break { opacity: .5; cursor: not-allowed; }
.agent-card.sick { opacity: .5; cursor: not-allowed; border-color: var(--state-caution); }
/* Blink-Budget: kein Puls mehr — ein Dauerzustand
   (Stress baut sich langsam auf und ab) blinkte hier permanent mit, das
   Warnsymbol vor dem Status-Text (game-screen.js) trägt das Signal jetzt
   mit. */
.agent-card.warn-stress { border-color: var(--state-caution); }
.agent-card.joker-rescued { animation: joker-blink 0.35s ease-in-out 4; }
@keyframes joker-blink {
  0%, 100% { border-color: var(--state-ok); box-shadow: 0 0 0 2px rgba(47, 191, 113, .18); }
  50% { border-color: var(--octopus-blue); box-shadow: 0 0 0 6px rgba(74, 108, 247, .45); background: #1a2440; }
}
/* nowrap statt wrap: eine umbrechende Zeile schob die Kartenzeilen darunter aus den
   120px Kartenhöhe heraus. Die Kopfzeile trägt nur Avatar, Name und Themen-Icons;
   das Tier-Tag sitzt rechts in der Stress-Zeile (.stress-row), denn Status-Text und
   Trainings-Abzeichen brauchen die ganze Breite der Status-Zeile. */
.agent-top { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
/* Skill-Avatar (ui/avatar.js: skillAvatarHtml()): Kreis in der Farbe des Haupt-Skills,
   position:relative, damit das Zweit-Skill-Abzeichen (.av-second) unten rechts andocken kann. */
.agent-avatar {
  position: relative;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  --sk1: var(--neutral-progress);
  --sk2: var(--sk1);
  background: var(--sk1);
}
.agent-avatar.size-sm { width: 28px; height: 28px; }
.agent-avatar.sk-billing { --sk1: var(--topic-billing); }
.agent-avatar.sk-tech { --sk1: var(--topic-tech); }
.agent-avatar.sk-sales { --sk1: var(--topic-sales); }
.agent-avatar.sk2-billing { --sk2: var(--topic-billing); }
.agent-avatar.sk2-tech { --sk2: var(--topic-tech); }
.agent-avatar.sk2-sales { --sk2: var(--topic-sales); }
/* Haupt-Skill groß im Kreis, Zweit-Skill als eigenes kleines Abzeichen unten rechts
   in seiner Skill-Farbe -- Haupt oder Zweit erkennt man an der Form, nicht an der Größe. */
.agent-avatar .av-icon { font-size: 17px; line-height: 1; }
.agent-avatar.size-sm .av-icon.primary { font-size: 15px; }
.av-second {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--sk2);
  border: 1.5px solid var(--panel);
  display: flex;
  align-items: center;
  justify-content: center;
}
.av-second .av-icon.secondary { font-size: 9px; }
/* Zähl-Abzeichen: Gespräche dieser Schicht, grau; gelb bei Überlast oder Dauereinsatz. */
.count-badge {
  position: absolute; left: -5px; top: -5px;
  min-width: 16px; height: 16px; padding: 0 3px; box-sizing: border-box;
  border-radius: 8px; background: var(--neutral-progress); color: var(--text);
  border: 1.5px solid var(--panel); font-size: 10px; font-weight: 700; line-height: 13px; text-align: center;
}
.count-badge.warn { background: var(--state-caution); color: #111; }
/* Zustands-Emoji vor dem Namen (vorher als Abzeichen am Avatar). */
.agent-state { font-size: 11px; line-height: 1; flex-shrink: 0; }
/* Erlaubt der Ellipse auf .agent-name unten, tatsächlich zu greifen: ohne min-width:0
   schiebt ein langer Name den Container statt darin abgeschnitten zu werden. */
.agent-info { min-width: 0; flex: 1 1 auto; }
.agent-name {
  font-weight: 700;
  font-size: 13px;
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Der Name bekommt die ganze Zeile -- die Skill-Icons sitzen jetzt im
   Avatar-Kreis (.agent-avatar), nicht mehr daneben. */
.agent-name-row { display: flex; align-items: center; gap: 3px; min-width: 0; }
.agent-status-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
.agent-status {
  font-size: 10px;
  color: var(--muted);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.agent-card.free .agent-status { color: var(--state-ok); }
/* Routing-Empfehlung (Spotlight) und „frei in n s“ an passenden Beschäftigten. Beides ohne Animation (Blink-Budget). */
.card-eta { display: none; font-size: 10px; font-weight: 700; color: var(--accent); white-space: nowrap; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.agent-card.has-eta .card-eta { display: block; }
.agent-card.has-eta .agent-status { display: none; }
/* Während ein Anruf mit Skill ausgewählt ist, zeigt render() (game-screen.js) an jeder
   freien Karte per match-*-Klasse, wie gut ihr Mitarbeiter passt: Haupt-Skill
   pulsiert in Skill-Farbe, Zweit-Skill zeigt einen gestrichelten Rahmen in Skill-Farbe ohne
   Puls, kein Skill bleibt normales .free -- keine Abdunkelung mehr, ein fachfremder
   Mitarbeiter ist weiterhin ganz normal zuweisbar. Die Skill-Farbe kommt über --match-color
   aus der zugehörigen .match-topic-*-Klasse (game-screen.js setzt beide Klassen gemeinsam).
   Die Selektoren tragen .free.assignable mit, damit sie in der Spezifität über dem grünen Puls
   von .agent-card.free.assignable liegen (nicht die Reihenfolge entscheidet): dessen animation wird
   je nach Fall durch den eigenen Puls oder durch "none" ersetzt, läuft also nie zusätzlich. */
.match-topic-billing { --match-color: var(--topic-billing); }
.match-topic-tech { --match-color: var(--topic-tech); }
.match-topic-sales { --match-color: var(--topic-sales); }
.agent-card.free.assignable.match-primary {
  border-color: var(--match-color, var(--state-ok));
  border-style: solid;
  border-width: 3px;
  animation: match-pulse 1s infinite;
}
@keyframes match-pulse {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--match-color, var(--state-ok)) 45%, transparent); }
  50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--match-color, var(--state-ok)) 12%, transparent); }
}
.agent-card.free.assignable.match-secondary {
  border-color: var(--match-color, var(--state-ok));
  border-style: dashed;
  border-width: 2px;
  animation: none;
  box-shadow: none;
}
.agent-card.free.assignable.match-none { animation: none; }
/* Spotlight der Routing-Empfehlung: die Karte hebt sich an und trägt einen doppelten Rahmen (außen Skill-Farbe, innen
   2px weiß), ohne Puls. Übernimmt ein Fachfremder (.suggested-overflow), ist der Doppelrahmen grün. Die Selektoren
   beginnen mit #agents, damit sie in der Spezifität über den match-*-Regeln liegen. */
#agents .agent-card.suggested {
  transform: translateY(-3px);
  border-style: solid;
  border-width: 3px;
  border-color: var(--match-color, var(--state-ok));
  box-shadow: inset 0 0 0 2px #fff, 0 6px 14px rgba(0, 0, 0, .45);
  animation: none;
}
#agents .agent-card.suggested-overflow { border-color: var(--state-ok); }
@media (prefers-reduced-motion: reduce) {
  #agents .agent-card.suggested { transform: none; }
}
/* Standardmäßig ausgeblendet; das Skript blendet den Balken bei Gespräch
   oder Training per style.display ein (CSSOM, von der CSP nicht betroffen). */
.agent-bar-track {
  display: none;
  position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  z-index: 2;
  background: #0B0D13;
  border-radius: 0 0 12px 12px;
  overflow: hidden;
}
.agent-bar-fill {
  --bar-color: var(--neutral-progress);
  height: 100%;
  background: var(--bar-color);
  width: 0%;
  transition: width .1s linear;
}
/* Balkenfarbe zeigt den Skill des laufenden Gesprächs; ohne Skill
   (Rückruf/Coaching) bleibt die neutrale Fortschrittsfarbe oben. */
.agent-bar-fill.topic-billing { --bar-color: var(--topic-billing); }
.agent-bar-fill.topic-tech { --bar-color: var(--topic-tech); }
.agent-bar-fill.topic-sales { --bar-color: var(--topic-sales); }
/* Fachfremd: dieselbe Skill-Farbe, aber schraffiert (ohne Animation). */
.agent-bar-fill.offskill {
  background: repeating-linear-gradient(135deg, var(--bar-color) 0 5px, rgba(11, 13, 19, .65) 5px 10px);
}
/* Die Anruf-Zählung tritt optisch zurück (dünnerer
   Balken) — der Text selbst bleibt bei 10px, dem
   festgelegten Mindestmass, "kleiner" heißt hier also weniger Fläche, nicht
   schlechter lesbar. */
.agent-load { display: none; align-items: center; justify-content: space-between; gap: 6px; }
.agent-load-label { font-size: 10px; color: var(--muted); white-space: nowrap; }
.agent-load-track { flex: 1; height: 3px; background: #0B0D13; border-radius: 3px; overflow: hidden; }
.agent-load-fill {
  height: 100%;
  background: var(--muted);
  width: 0%;
  transition: width .3s ease, background .3s ease;
}
/* Stress wird der wichtigste Balken — dicker (6px statt
   4px) und eine eigene Zeile direkt unter dem Namen (siehe buildAgentCards()
   in game-screen.js), damit die Hauptursache von Stress (Überlastung)
   sofort sichtbar ist, statt hinter der Anruf-Zählung zu stehen. */
.stress-row { display: flex; align-items: center; gap: 6px; }
/* Eigene Klasse statt .agent-load-label: beide Zeilen haben ein Label mit
   demselben Aussehen, aber render() muss sie eindeutig ansprechen können. */
.stress-label { font-size: 10px; color: var(--muted); white-space: nowrap; }
.stress-track { flex: 1; height: 6px; background: #0B0D13; border-radius: 3px; overflow: hidden; }
.stress-fill {
  height: 100%;
  width: 0%;
  background: var(--state-ok);
  transition: width .3s ease, background .3s ease;
}

.fly-point {
  position: fixed;
  z-index: 50;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 700;
  font-size: 15px;
  pointer-events: none;
  will-change: transform, opacity;
}

/* Warteschlange und Agenten bleiben im Nachlauf bedienbar — dort darf
   zugewiesen werden (siehe assignSelected()). Gesperrt bleiben nur die
   Dinge, die zur Schicht selbst gehören: Flex-Kraft und ACD. */
#screen-game.shift-locked #joker-btn,
#screen-game.shift-locked #planner-btn {
  opacity: .55;
  pointer-events: none;
}

#hint {
  margin: 0;
  font-size: 11px;
  color: var(--muted);
  text-align: center;
  line-height: 1.2;
  min-height: 0;
}

/* --------------------------------------------------------------------------
   Toasts & Hinweise
   -------------------------------------------------------------------------- */
.toast-container {
  position: fixed;
  top: calc(14px + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  /* Muss über den Overlays liegen, damit Toasts über einem offenen Dialog
     sichtbar bleiben statt hinter dessen deckendem Hintergrund zu verschwinden. */
  z-index: 85;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
  pointer-events: none;
  width: 90%;
  max-width: 400px;
}
/* Während der Schicht liegt oben die Kopfleiste (SL, Score, Restzeit) — ein Toast dort
   würde sie verdecken. Unten ist während der Schicht Platz oberhalb der Werkzeugleiste. column-reverse hält
   den neuesten Toast an der Ankerkante (unten), auch wenn mehrere gleichzeitig sichtbar sind. */
body.shift-active .toast-container {
  top: auto;
  bottom: calc(66px + env(safe-area-inset-bottom));
  flex-direction: column-reverse;
}
.toast {
  background: var(--panel);
  border: 1px solid var(--state-danger);
  color: var(--text);
  font-size: 12px;
  padding: 8px 14px;
  border-radius: 20px;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .25s ease, transform .25s ease;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .4);
  text-align: center;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.joker, .toast.info { border-color: var(--neutral-progress); }

/* Keine eigene #hint-Regel hier — mit der festen Bühne hat #hint nur noch
   eine 14px-Zeile und wird deshalb kompakter in der "Spiel-Screen"-Regel
   weiter oben definiert. Zwei Regeln für dieselbe ID mit gleicher
   Spezifität würden sich sonst per Kaskaden-Reihenfolge gegenseitig aushebeln. */

/* Geführte erste Schicht: Sprechblase, die den Chip bzw. die
   Mitarbeiterliste erklärt. Bewusst kein Overlay (siehe Kommentar in
   index.html) — ein kleines, freistehendes Kärtchen wie .toast, nur länger
   sichtbar und per CSSOM (ui/coach.js) an ein Ziel-Element gebunden statt
   zentriert. z-index 50, dieselbe Stufe wie .fly-point: beides sind
   transiente, nicht-modale Einblendungen über dem Spielfeld, unter dem
   den Overlays (80) und den Toasts (85), siehe Reihenfolge-Kommentar bei
   .overlay weiter unten. */
.coach-bubble {
  position: fixed;
  z-index: 50;
  max-width: 260px;
  background: var(--panel);
  border: 2px solid var(--accent);
  border-radius: 12px;
  padding: 10px 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .4);
  text-align: center;
  /* Das Ziel des zweiten Führungsschritts (#agents, die GANZE Mitarbeiterliste) kann auf
     manchen Bildschirmgrößen so viel Höhe einnehmen, dass über/unter ihm
     kein freier Platz mehr bleibt (#screen-game ist ein festes 7-Zeilen-Grid
     ohne echten Leerraum, siehe tasks/lessons.md) — die Blase liegt dann
     zwangsläufig über ein paar Mitarbeiterkarten. pointer-events:none lässt
     Klicks trotzdem zur Karte darunter durch; nur der Überspringen-Knopf
     bekommt sein eigenes pointer-events:auto zurück. */
  pointer-events: none;
}
.coach-bubble p { margin: 0; font-size: 13px; color: var(--text); }
.coach-bubble .link-btn { width: auto; margin: 6px auto 0; padding: 4px; pointer-events: auto; }

/* --------------------------------------------------------------------------
   Overlays
   -------------------------------------------------------------------------- */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(11, 14, 19, .94);
  display: none;
  align-items: center;
  justify-content: center;
  /* Ein modales Overlay gehört immer über eine nicht-modale Leiste — sonst
     kann z. B. eine Leiste den Schließen-Knopf eines Dialogs verdecken.
     Reihenfolge: Popover 15 < Fly-Point 50 < Overlay 80
     < Toast 85 < Fatal-Overlay 90. */
  z-index: 80;
  padding: 20px;
}
.overlay.show { display: flex; }
/* Das Fatal-Overlay muss über allem anderen liegen. */
#fatal-overlay { z-index: 90; background: rgba(11, 14, 19, .98); }

.overlay-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 26px;
  max-width: 340px;
  width: 100%;
  text-align: center;
  max-height: 90vh;
  overflow-y: auto;
}
.overlay-actions { display: flex; gap: 8px; }

#event-card h2 { margin: 0 0 10px; font-size: 18px; color: var(--state-caution); }
#explainer-card h2 { margin: 0 0 4px; font-size: 18px; color: var(--accent); }
#explainer-card .explainer-eyebrow {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--muted);
  margin-bottom: 6px;
}
#fatal-card h2 { margin: 0 0 10px; font-size: 18px; color: var(--state-danger); }

.overlay-card p {
  color: var(--text);
  font-size: 14px;
  margin: 0 0 20px;
  line-height: 1.5;
}
#pause-card h2, #tutorial-card h2, #confirm-card h2, #rename-card h2, #choice-card h2 { margin: 0 0 10px; font-size: 18px; }
#rename-input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  font-size: 16px; /* 16px verhindert Auto-Zoom auf iOS, gleiches Muster wie #name-input */
  margin-bottom: 14px;
  font-family: inherit;
}
#rename-input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }

/* Der Nutzungshinweis ist mehrabsätzig und soll kopierbar sein. */
#explainer-text {
  white-space: pre-line;
  user-select: text;
  -webkit-user-select: text;
  text-align: left;
}
#tutorial-card { text-align: left; }
#tutorial-card #tutorial-step-counter { text-align: left; }

.fatal-detail {
  display: none;
  text-align: left;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px;
  margin: 0 0 16px;
  max-height: 140px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  user-select: text;
  -webkit-user-select: text;
}
.fatal-detail.show { display: block; }

/* --------------------------------------------------------------------------
   Dashboard
   -------------------------------------------------------------------------- */
.contract-result { font-weight: 700; font-size: 13px; margin: 0 0 14px; }
.contract-result.good { color: var(--state-ok); }
.contract-result.bad { color: var(--state-danger); }

.dash-kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin: 4px 0 18px;
}
.dash-kpi-tile {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px;
}
.dash-kpi-tile .stat-value { font-size: 20px; }
/* Bei ungerader Kachelzahl (Endlosmodus: Score, Budget, Wellen) füllt die
   letzte Kachel die Zeile, statt eine Lücke stehen zu lassen. */
.dash-kpi-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
.dash-kpi-note {
  font-size: 12px;
  color: var(--muted);
  margin: -4px 0 8px;
}
.dash-kpi-tile .stat-value.good { color: var(--state-ok); }
.dash-kpi-tile .stat-value.bad { color: var(--state-danger); }

.dash-donut-note { font-size: 12px; color: var(--muted); margin-top: 6px; }

.dash-tech-line {
  font-size: 12px;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 12px;
  margin-bottom: 6px;
}
.dash-line-chart {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px;
  margin-bottom: 18px;
}
.dash-line-chart svg { width: 100%; height: 90px; display: block; }
.dash-line-legend {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--muted);
  margin-top: 4px;
}

.donut {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  margin: 0 auto 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.donut-hole {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: var(--panel);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 700;
  font-size: 18px;
}
.donut-legend {
  display: flex;
  justify-content: center;
  gap: 12px;
  font-size: 10px;
  color: var(--muted);
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.donut-legend .dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
}
.donut-legend .dot.accepted { background: var(--state-ok); }
.donut-legend .dot.iva { background: var(--neutral-progress); }
.donut-legend .dot.missed { background: var(--state-danger); }

.dash-bar-chart { margin-bottom: 20px; display: flex; flex-direction: column; gap: 8px; }
.dash-agent-chart { margin-bottom: 18px; display: flex; flex-direction: column; gap: 8px; }
.dash-bar-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.dash-bar-row .bar-label {
  width: 88px;
  color: var(--muted);
  flex-shrink: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dash-bar-row .bar-track {
  flex: 1;
  height: 10px;
  background: #0B0D13;
  border-radius: 5px;
  overflow: hidden;
}
.dash-bar-row .bar-fill { height: 100%; border-radius: 5px; transition: width .4s ease; }
.dash-bar-row .bar-count {
  width: 30px;
  text-align: right;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  flex-shrink: 0;
}
.dash-insight {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 13px;
  margin-bottom: 12px;
}
.dash-provider-note { font-size: 11px; color: var(--muted); margin-bottom: 18px; }
.dash-diabolocom-box {
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 16px;
}
.dash-diabolocom-box #dash-diabolocom-note {
  font-size: 12px;
  color: var(--text);
  line-height: 1.4;
}
.dash-diabolocom-link {
  display: inline-block;
  margin-top: 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  text-decoration: none;
}
.dash-diabolocom-link:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   Report als Belohnung: Sterne, Knopfzeile, Details, Konfetti
   -------------------------------------------------------------------------- */
.dash-stars {
  display: flex;
  gap: 6px;
  justify-content: center;
  font-size: 32px;
  line-height: 1;
  margin: 4px 0 10px;
}
.dash-stars .star { color: var(--neutral-progress); }
.dash-stars .star.filled { color: var(--state-caution); }

/* Kleinere Sterne unter dem Titel der Auftragskarte auf der Startseite —
   gleiche zwei Klassen (.star/.filled) wie oben, nur in eigener Größe. */
.c-stars { display: flex; gap: 2px; font-size: 12px; line-height: 1; margin-top: 2px; }
.c-stars .star { color: var(--neutral-progress); }
.c-stars .star.filled { color: var(--state-caution); }

.dash-btn-row { margin: 4px 0 18px; }
.dash-btn-row .primary-btn { margin-bottom: 8px; }
.dash-btn-row-secondary { display: flex; gap: 8px; flex-wrap: wrap; }
.dash-btn-row-secondary .secondary-btn { margin-top: 0; flex: 1 1 0; }
/* Zwischenablage-Fallback, nur sichtbar wenn navigator.clipboard
   fehlschlägt oder fehlt (siehe Klick-Handler in dashboard.js). */
.daily-share-fallback { margin: -10px 0 18px; }
.daily-share-fallback-hint { color: var(--muted); font-size: 12px; margin: 0 0 8px; }
.daily-share-fallback-input {
  width: 100%;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
}
.daily-share-fallback-input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }

/* "Details" fasst Wallboard, Verlauf, Donut, Mitarbeiter und Technik
   zusammen — per Standard eingeklappt (siehe index.html), damit der Report
   zuerst mit Sternen, Ergebnis und den drei Knöpfen ankommt. */
#dash-details { margin-bottom: 4px; }
#dash-details summary {
  cursor: pointer;
  list-style: none;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 10px 0;
  border-top: 1px solid var(--line);
  margin-bottom: 8px;
}
#dash-details summary::-webkit-details-marker { display: none; }
#dash-details summary::before { content: '▸ '; }
#dash-details[open] summary::before { content: '▾ '; }

/* Konfetti bei neuem Bestwert oder ★★★ (triggerConfetti() in ui/fx.js):
   JS befüllt/leert ausschließlich den Container mit 24 vorab hier
   positionierten/eingefaerbten Elementen, keine Positions-/Farblogik in
   JS (R3: keine Inline-Styles). Reine CSS-Animation — die globale
   prefers-reduced-motion-Regel unten kappt sie automatisch zusätzlich zu
   dem harten Abbruch in triggerConfetti() selbst (das dort gar keine
   Elemente erst erzeugt). Der Sternregel-Text liegt per z-index darüber, das Konfetti fällt dahinter. height:0 hält den leeren Container aus dem
   Fluss, solange kein Konfetti läuft.  */
.dash-confetti { position: relative; height: 0; overflow: visible; }
.cf-piece {
  position: absolute;
  top: 0;
  width: 7px;
  height: 12px;
  border-radius: 2px;
  opacity: 0;
  animation: cf-fall 1.2s ease-in forwards;
}
@keyframes cf-fall {
  0% { opacity: 1; transform: translateY(-10px) rotate(0deg); }
  100% { opacity: 0; transform: translateY(140px) rotate(280deg); }
}
.cf-1 { left: 0.0%; background: var(--accent); animation-delay: 0.18s; }
.cf-2 { left: 4.2%; background: var(--state-ok); animation-delay: 0.37s; }
.cf-3 { left: 8.3%; background: var(--state-caution); animation-delay: 0.06s; }
.cf-4 { left: 12.5%; background: var(--octopus-blue); animation-delay: 0.24s; }
.cf-5 { left: 16.7%; background: var(--accent); animation-delay: 0.42s; }
.cf-6 { left: 20.9%; background: var(--state-ok); animation-delay: 0.11s; }
.cf-7 { left: 25.0%; background: var(--state-caution); animation-delay: 0.29s; }
.cf-8 { left: 29.2%; background: var(--octopus-blue); animation-delay: 0.48s; }
.cf-9 { left: 33.4%; background: var(--accent); animation-delay: 0.17s; }
.cf-10 { left: 37.6%; background: var(--state-ok); animation-delay: 0.35s; }
.cf-11 { left: 41.7%; background: var(--state-caution); animation-delay: 0.04s; }
.cf-12 { left: 45.9%; background: var(--octopus-blue); animation-delay: 0.22s; }
.cf-13 { left: 50.1%; background: var(--accent); animation-delay: 0.41s; }
.cf-14 { left: 54.3%; background: var(--state-ok); animation-delay: 0.09s; }
.cf-15 { left: 58.4%; background: var(--state-caution); animation-delay: 0.28s; }
.cf-16 { left: 62.6%; background: var(--octopus-blue); animation-delay: 0.46s; }
.cf-17 { left: 66.8%; background: var(--accent); animation-delay: 0.14s; }
.cf-18 { left: 71.0%; background: var(--state-ok); animation-delay: 0.33s; }
.cf-19 { left: 75.1%; background: var(--state-caution); animation-delay: 0.01s; }
.cf-20 { left: 79.3%; background: var(--octopus-blue); animation-delay: 0.2s; }
.cf-21 { left: 83.5%; background: var(--accent); animation-delay: 0.39s; }
.cf-22 { left: 87.7%; background: var(--state-ok); animation-delay: 0.07s; }
.cf-23 { left: 91.8%; background: var(--state-caution); animation-delay: 0.26s; }
.cf-24 { left: 96.0%; background: var(--octopus-blue); animation-delay: 0.44s; }

/* --------------------------------------------------------------------------
   Reduzierte Bewegung respektieren
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}


/* ==========================================================================
   ACD-Countdown, Rahmen-Signale, Endsequenz
   Dieser Block steht bewusst am Dateiende: eine seiner Regeln muss in der
   Kaskade GEWINNEN, und bei gleicher Spezifität gewinnt die spätere Regel.
   Betroffen ist .agent-card.joker-target (gegen .agent-card.sick, das
   border-color setzt). Steht der Block weiter oben, greift er nicht —
   dieselbe Falle wie bei #joker-btn.has-target.
   ========================================================================== */

/* --- Werkzeugknöpfe ------------------------------------------------------- */
.tool-btn { position: relative; overflow: hidden; }

/* --- Rahmen um den Spielbildschirm ---------------------------------------- */
/* position:fixed rahmt das Sichtfenster, nicht den Inhalt — dadurch ist der
   Rahmen unabhängig davon sichtbar, wie weit gescrollt wurde.
   z-index 60 fügt sich in die bestehende Ordnung ein:
   Popover 15 < Fly-Point 50 < RAHMEN 60 < Overlay 80
   < Toast 85 < Fatal-Overlay 90.
   Gelb = die ACD läuft aus, Rot = die Schicht steht auf der Kippe. Nie beide
   gleichzeitig; render() schaltet Gelb ab, sobald Rot gilt. */
#screen-game.acd-ending::after,
#screen-game.danger-edge::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 60;
  border: 4px solid var(--accent);
  border-radius: 4px;
  animation: edge-pulse 1s ease-in-out infinite;
}
#screen-game.danger-edge::after {
  border-color: var(--state-danger);
  animation-duration: .7s;
}
@keyframes edge-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .2; }
}

/* --- Flex-Kraft: rettbare Mitarbeiter ------------------------------------- */
/* Octopus-Blau ist die Farbe der Flex-Kraft — sie steckt schon im Symbol, in
   der joker-rescued-Animation und im Veteranen-Tag.
   opacity kommt zurück auf .92: .on-break und .sick setzen .5, und ein blauer
   Rahmen auf einer halbdurchsichtigen Karte sieht kaputt aus statt einladend.
   cursor ebenfalls, weil .on-break/.sick auf not-allowed stehen — hier ist der
   Klick aber genau das, was passieren soll. */
.agent-card.joker-target {
  border-color: var(--octopus-blue);
  opacity: .92;
  cursor: pointer;
  animation: joker-target-pulse 1.2s ease-in-out infinite;
}
@keyframes joker-target-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(74, 108, 247, .5); }
  50% { box-shadow: 0 0 0 8px rgba(74, 108, 247, .12); }
}

/* Schwebende Kopie des gezogenen Chips/Buttons, folgt dem
   Zeiger per style.transform (R3 — keine Inline-Styles in HTML-Strings,
   aber CSSOM-Zuweisungen aus JS sind erlaubt). z-index 55 liegt über den
   Karten (siehe .agent-card) und unter Overlays/Dialogen. */
.drag-ghost {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 55;
  pointer-events: none;
  opacity: .9;
}
/* Gueltiges/ungueltiges Ablegeziel während des Ziehens — dieselben Farben
   wie .agent-card.free (gültig) bzw. .agent-card.sick (ungültig), damit
   das Signal zum Rest der Karten-Zustände passt. */
.agent-card.drop-target {
  border-color: var(--state-ok);
  box-shadow: 0 0 0 4px rgba(47, 191, 113, .35);
}
.agent-card.drop-invalid {
  border-color: var(--state-danger);
  opacity: .65;
}

/* --- Endsequenz ----------------------------------------------------------- */
/* Durchlässig (0,62 statt 0,94 wie die übrigen Overlays): der Endzustand des
   Contact Centers bleibt sichtbar; das Spiel springt nicht ohne einen einzigen
   Frame ins Dashboard. */
.endseq-overlay {
  background: rgba(11, 14, 19, .62);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  cursor: pointer;
}
.endseq-card {
  text-align: center;
  pointer-events: none;
  padding: 24px 28px;
  border-radius: 18px;
  background: rgba(23, 29, 38, .88);
  border: 1px solid var(--line);
  max-width: 320px;
  width: 100%;
}
.endseq-title {
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.endseq-reason {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.35;
  margin-bottom: 10px;
}
.endseq-count {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 64px;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}
.endseq-count.tick { animation: endseq-tick .45s ease-out; }
@keyframes endseq-tick {
  0% { transform: scale(1.5); opacity: .2; }
  60% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.endseq-hint {
  margin-top: 12px;
  font-size: 11px;
  color: var(--muted);
}

/* ==========================================================================
   Datenschutzseite — datenschutz.html (eigene, statische Seite außerhalb der
   App-Screens von index.html, teilt sich aber #shell/.screen/#app-footer mit
   ihnen und nutzt damit dieselbe 480px-Spalte).
   ========================================================================== */
.legal-card {
  width: 100%;
  max-width: 100%;
  padding: 4px 4px 24px;
}
.legal-back-link {
  display: inline-block;
  width: auto;
  margin: 0 0 18px;
  padding: 8px 0;
  text-align: left;
}
.legal-title {
  margin: 0 0 20px;
  font-size: 22px;
  color: var(--text);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 700;
}
.legal-section { margin: 0 0 22px; }
.legal-section h2 {
  margin: 0 0 8px;
  font-size: 15px;
  color: var(--text);
  font-weight: 700;
}
.legal-section p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}
/* Hebt die noch offenen [[BITTE AUSFÜLLEN: ...]]-Stellen farblich hervor,
   solange die Seite ein Gerüst ist (--state-caution: Achtung nötig, siehe
   Farbsystem). Entfällt automatisch, sobald ein Abschnitt mit
   echtem Text ersetzt und die Klasse entfernt wird. */
.legal-section p.legal-placeholder { color: var(--state-caution); }

/* ==========================================================================
   Kontakte gleiten herein, ACD-Vermittlung, Stress-Stoß, Verpasst-Farbe
   ========================================================================== */
#missed-value.risk { color: var(--state-caution); }
#missed-value.bad { color: var(--state-danger); }

.call-chip.chip-enter { animation: chip-enter .22s ease-out; }
@keyframes chip-enter {
  from { opacity: 0; transform: translateX(24px); }
  to { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .call-chip.chip-enter { animation-name: chip-enter-fade; }
  @keyframes chip-enter-fade { from { opacity: 0; } to { opacity: 1; } }
}
.call-chip.acd-flight { z-index: 60; pointer-events: none; }

.agent-card.assign-flash { animation: assign-flash .5s ease-out; --flash-color: var(--accent); }
.agent-card.assign-flash-billing { --flash-color: var(--topic-billing); }
.agent-card.assign-flash-tech { --flash-color: var(--topic-tech); }
.agent-card.assign-flash-sales { --flash-color: var(--topic-sales); }
.agent-card.assign-flash-ok { --flash-color: var(--state-ok); }
@media (prefers-reduced-motion: reduce) { .agent-card.assign-flash { animation: none; box-shadow: 0 0 0 3px var(--flash-color); } }
@keyframes assign-flash {
  0% { box-shadow: 0 0 0 3px var(--flash-color), 0 0 14px var(--flash-color); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.stress-row { position: relative; }
.stress-track.stress-kick { animation: stress-kick .4s ease-out; }
@keyframes stress-kick {
  0% { filter: brightness(2.4); }
  100% { filter: brightness(1); }
}
.stress-kick-fly {
  position: absolute; right: 30px; top: -6px;
  font-size: 11px; font-weight: 700; color: var(--state-caution);
  pointer-events: none;
  animation: stress-kick-fly .9s ease-out forwards;
}
@keyframes stress-kick-fly {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-12px); }
}

/* Stern-Regeln (Auftragskarte und Report) */
button.c-stars { background: none; border: none; padding: 4px 0; min-height: 44px; font: inherit; color: inherit; cursor: pointer; text-align: left; }
.star-rules { position: relative; z-index: 1; list-style: none; margin: 6px 0 8px; padding: 0; font-size: 12px; color: var(--muted); }
.star-rules[hidden] { display: none; }
.star-rule { display: flex; gap: 6px; padding: 2px 0; }
.star-rule.met { color: var(--text); }
.star-rule-mark { flex: 0 0 auto; color: var(--muted); }
.star-rule.met .star-rule-mark { color: var(--state-ok); }
.kpi-avg { font-size: 10px; color: var(--muted); margin-top: 2px; }

/* Report: "knapp daneben" und Kaufempfehlung (Spielen -> Verstehen -> Kaufen -> Spielen). */
.dash-near-miss { margin: 8px 4px 0; font-size: 13px; font-weight: 700; color: var(--accent); }
.dash-near-miss[hidden] { display: none; }
.dash-reco-btn { display: block; width: 100%; margin-top: 10px; }
.dash-reco-btn[hidden] { display: none; }
.store-item.store-item-reco { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(245, 171, 61, .25); }


/* ==========================================================================
   Gesprächsende, Banner, Platzwechsel, Chips
   Am Dateiende, damit diese Regeln bei gleicher Spezifität gewinnen.
   ========================================================================== */

/* Punkte auf der Karte: rechts unten, groß, ohne Eingabe. Dauer setzt fx.js (CARD_POINTS_MS). */
.card-points {
  position: absolute; top: auto; bottom: 6px; right: 10px; z-index: 6;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 700; font-size: 1.5rem; line-height: 1.1;
  color: var(--state-ok);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .9), 0 0 2px #000;
  pointer-events: none;
  animation: card-points-life 1600ms ease-out both;
}
@keyframes card-points-life {
  0% { opacity: 0; transform: scale(.8); }
  12% { opacity: 1; transform: scale(1.15); }
  80% { opacity: 1; transform: scale(1.15); }
  100% { opacity: 0; transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) { .card-points { animation: none; } }
/* „Gerettet!“ hängt unter der Punktezahl und verschwindet mit ihr. */
.card-saved {
  display: block; font-family: inherit; font-size: .65rem; font-weight: 700; line-height: 1.1; text-align: right;
  letter-spacing: 0; color: var(--state-ok);
}

/* Score: einmaliger Puls nach einem Gewinn, kein Dauer-Blinken. */
.score-pulse { animation: score-pulse-once .3s ease-out; }
@keyframes score-pulse-once {
  0% { transform: scale(1); }
  50% { transform: scale(1.25); color: var(--state-ok); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { .score-pulse { animation: none; } }

/* Serien-Banner: nur der Titel, ohne zweiten Teil. */
.milestone-banner.milestone-banner-small > div:first-child { font-size: 11px; }


/* Platzwechsel: ruhiger Rahmen, der ausblendet (kein Pulsieren). Outline statt Border, damit Zustandsrahmen unberührt bleiben. */
.agent-card.seat-moved {
  outline: 3px solid var(--accent);
  outline-offset: -3px;
  animation: seat-moved-fade 1500ms ease-out both;
}
@keyframes seat-moved-fade {
  0%, 55% { outline-color: var(--accent); }
  100% { outline-color: transparent; }
}
@media (prefers-reduced-motion: reduce) { .agent-card.seat-moved { animation: none; } }

/* Technik-Abzeichen: der Pfeil zeigt, dass sie tippbar sind. */
.tech-badge .chevron { margin-left: 4px; opacity: .6; }
