/* Chat Tower Companion -- pages/build.css
 * P6-Kette Glied 6/8 (web-241). Reine Verschiebung aus web/public/style.css
 * PLUS die ui-461-Design-Locks 1-4 (Hexa-Basis mobile Usability, s.
 * web-241-Ticket + ui-461-Ticket "## Design-Locks").
 * Scope: Dashboard-Tab "Waffe/Build" -- Waffenslot-Equip-Grid + der komplette
 * Build-Tab (Hexa-Invest-Grid/-Stepper, Template-CRUD, Faktoren-Tooltip-
 * Markup). Deckt sich mit dem JS-Modul
 * web/client/companion/collection/templates.js (web-238).
 *
 * Kaskaden-Lock: MUSS vor pages/dashboard.css UND pages/shared-mobile.css
 * laden -- mehrere hier definierte Basisregeln (.build-stage/.build-spine/
 * .build-dot/.em-chip/.em-reset u.a.) werden von spaeteren Mobile-/Touch-
 * Overrides in genau diesen zwei Dateien ueberschrieben (gleiche
 * Spezifitaet, spaetere Datei-Position gewinnt) -- s. web-241-Ticket
 * Cross-File-Sweep fuer die volle Belegliste. */


/* ui-523: der vormalige .wth-hint*-Block (ui-517, DL-1 "Hexa-Basis-Intro" +
   DL-3 "Upgrade-Tips" Inline-Banner) ist restlos entfernt — dieselben
   Wortlaute laufen jetzt als Floating-Coachmark-Schritte über die geteilte
   .ob-*-Box-Chrome (web/client/css/companion/pages/dashboard.css, Sequenzen
   `weapon_tab_hexa_intro`/`weapon_tab_upgrade_tips` in
   web/public/dash-onboarding.js) — keine eigene CSS-Klasse mehr nötig. */

/* ===== Waffenslot ===== */

/* ui-121 (2026-06-13): .weapon-current-Banner entfernt (Equip-Grid-Highlight reicht als Feedback). */

/* ui-115 (2026-06-13): Trenner zwischen Equip-Grid und Build-Sektion im Waffe-Tab. */
.build-divider {
  border: none;
  border-top: 1px dashed var(--line-2);
  margin: 1.1em 0;
}

.weapon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0.6em;
}
.weapon-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3em;
  padding: 0.8em 0.6em;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: 5px;
  text-align: center;
}
.weapon-card.equipped {
  border-color: var(--yellow);
  box-shadow: 0 0 12px rgba(255, 216, 74, 0.3);
}
.weapon-card.locked { opacity: 0.35; cursor: not-allowed; }
.weapon-card:hover:not(:disabled):not(.equipped) {
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: 0 0 12px rgba(56, 225, 255, 0.3);
}
.wc-glyph { font-size: 1.5em; color: var(--yellow); display: flex; align-items: center; justify-content: center; }
/* weicher Multi-Layer-Glow (ui-069) für Waffenslot-Karten, 30px. */
.wc-glyph img.wg-img {
  display: block;
  filter: drop-shadow(0 0 4px rgba(255, 216, 74, 0.32))
          drop-shadow(0 0 10px rgba(255, 216, 74, 0.24));
}
.wc-label { font-weight: 500; }
/* ui-519: 0.75em (~9.75px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.wc-status { font-size: var(--fs-caption); color: var(--muted); }
.weapon-card.equipped .wc-status { color: var(--yellow); }

/* ui-628 (AK5): 9 Tower-Typen -> Lock 6 -> immer ein Auswahl-Sheet statt des
   Kachel-Grids (renderWeaponSlot(), views/dashboard.js rendert Pick-Knopf +
   Sheet zusaetzlich, unveraendert im DOM auf Desktop). `.weapon-grid`/
   `.weapon-card` sind NUR hier in dashboard.js im Einsatz (kein geteilter
   Klassenname mit profile.js o.ae.), unscoped ausblenden ist sicher. */
@media (max-width: 600px) {
  .weapon-grid { display: none; }
}

/* ui-631 AK1/AK4: Desktop-Pendant zum Mobile-Hide oben — 9 Tower-Typen sind
   IMMER >= SUBNAV_DESK_PICK_MIN (views/subnav.js), das Kachel-Grid weicht
   deshalb ab 601px unbedingt dem neuen Auswahl-Chip + Popover ("Chip statt
   Karten-Raster", seit ui-638 im `.subnav-desk-head`-Kopf-Container statt
   eines eigenen `.subnav-desk-row`, views/dashboard.js renderWeaponSlot()).
   Unscoped wie das Mobile-Hide oben — `.weapon-grid`/`.weapon-card` sind
   nur hier in dashboard.js im Einsatz. */
@media (min-width: 601px) {
  .weapon-grid { display: none; }
}

/* ui-635 (Fifty 14.09., Prototyp-Abnahme "C"): Tower-Sub-Nav-Zeilen (Sheet
   ui-628 + Desktop-Popover ui-631) sind seither KEINE `.weapon-card`-
   Kacheln mehr, sondern derselbe generische `.subnav-sheet-row`-Zeilen-
   Baustein (renderSubnavRow(), views/subnav.js) wie Erfolge-Filter/Rang/
   Baum — eigene Modifier-Klasse `.tower-pick-row` hier (Konsument liefert
   Zeilen + eigene Modifier-Klasse in der eigenen pages/*.css, s.
   components.css "ui-630"-Kopfkommentar). Groesse/Hoehe/Hervorhebung
   kommen bereits aus der geteilten `.subnav-sheet-row`-Basis (40px
   Desktop-Popover/44px Mobile-Sheet, aria-selected-Cyan); einzige
   Tower-eigene CSS-Ergaenzung: DL-1 verlangt 0.42 Deckkraft fuer gesperrte
   Zeilen in BEIDEN Kontexten — die geteilte Desktop-Popover-Regel
   (`.subnav-desk-pop .subnav-sheet-row:disabled`) traegt das bereits
   (components.css), die Mobile-Sheet-Regel
   (`.subnav-sheet-rows .subnav-sheet-row:disabled`) nicht (dort 0.35,
   historisch nie von einem nativ-disabled Sheet-Zeilen-Konsumenten
   erreicht — Erfolge-Filter/Baum nutzen nie natives `disabled`, Tower ist
   der erste). Deshalb eine gezielte Ueberschreibung hier statt den
   geteilten 0.35-Default global zu aendern. */
@media (max-width: 600px) {
  .subnav-sheet-rows .tower-pick-row:disabled { opacity: 0.42; }
}

/* ui-635 CDP-Beleg-Fund (2-Spalten-Desktop-Popover, lange Label + "🔒
   gesperrt"-Status gleichzeitig, z.B. "Raketenwerfer"): `<button>` ist als
   Grid-Item OHNE eigenes `overflow` ein `min-width:auto`-Kandidat -- die
   Grid-Spalte (`repeat(2, 1fr)`, components.css) waechst dadurch auf den
   Content-Min-Content statt auf die Zeile zu schrumpfen, obwohl der Label-
   Span selbst bereits `min-width:0` + Ellipsis traegt (subnav-row-text,
   components.css) -- DAS reicht nicht, wenn der GRID-ITEM selbst nicht
   schrumpfen darf. `.subnav-row-text`s Ellipsis kann diesen Grid-Sizing-
   Effekt nicht kompensieren (die Zeile "gewinnt" trotzdem ihre natuerliche
   Breite, sprengt die 340px-Popover-Box -> horizontaler Scrollbalken, live
   per CDP vermessen: popScrollWidth 395 vs. popClientWidth 338). Fix: die
   ZEILE selbst braucht min-width:0, damit sie auf ihre 1fr-Spalte
   schrumpft -- danach greift die Ellipsis im Label wie vorgesehen. Nur
   Tower betroffen (bisher einziger 2-Spalten-Popover-Konsument mit
   gleichzeitig langen Labeln UND einem rechten Wort-Status; Erfolge-Filter
   hat im Popover nur ein einzelnes 🔒-Zeichen, kein Wort). Unter
   `.subnav-sheet-rows` gescopt (ui-602 AK3-Ratchet-Guard: eine bare
   Top-Level-Klasse wirkt potenziell auf jeder Companion-Seite,
   web/client/README.md § Fallen-Register) statt einer bare `.tower-pick-
   row`-Regel — `.subnav-sheet-rows` ist der Zeilen-Wrapper in BEIDEN
   Kontexten (renderSubnavSheet() UND renderDeskPopover(), views/subnav.js,
   je unterschiedlich nur in der AEUSSEREN Huelle .subnav-sheet/.subnav-
   desk-pop), ein Selektor deckt deshalb Sheet UND Popover gleichermassen
   ab, keine Media-Query noetig (anders als die 0.42-Deckkraft-Regel oben,
   die NUR im Mobile-Sheet-Kontext fehlt). */
.subnav-sheet-rows .tower-pick-row { min-width: 0; }

/* =====================================================================
 * Build-Tab (ui-027, 2026-06-07)
 * Waffen-zentrierter Build-Pfad-Stepper: Hexa-Basis → Template-Steps → Endzustand.
 * Farb-Semantik: Magenta = Hexa-Basis, Cyan = Lift, Gelb = skip/Kosten, Muted = Off.
 * ===================================================================== */

/* ---- Farb-Schlüssel ---- */
.k-meta { color: var(--magenta); }
.k-lift { color: var(--cyan); }
.k-skip { color: var(--yellow); }
.k-off  { color: var(--muted); }

/* ---- Kopfzeile (ui-115: Waffen-Strip entfernt, DL-4) ---- */
/* ui-641/DL-1 "Platz B" (Re-Spawn nach ui-638-Merge): Hexa-Budget-Chip +
   Tower-Typ-Chip (.subnav-desk, components.css) als EINE Chip-Gruppe --
   dieser Wrapper ist der `pickHtml`-Slot von renderDeskHead() (ui-638), kein
   eigener Block mehr davor. Kein eigenes margin-bottom noetig (Abstand zum
   Sheet/Grid darunter kommt aus `.panel-hint`s eigenem margin im
   `.subnav-desk-head-text`-Geschwister). `.subnav-desk` bringt bereits
   `min-height:40px` mit (components.css); die Groessen-Variante unten
   gleicht nur den Chip auf dieselbe Hoehe an (AK2 "gleiche Hoehe"). */
.build-tower-chips {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 8px;
}
/* Groessen-Variante NUR hier (Basis-Regel in components.css bleibt fuer den
   Erfolge-Kopf unveraendert, Lock 3). */
.build-tower-chips .ach-balance-chip {
  min-height: 40px;
  padding: 0.4em 0.9em;
}
.build-weapon-strip {
  display: flex;
  gap: 0.4em;
  flex-wrap: wrap;
}
.build-weapon-tab {
  display: flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.38em 0.75em;
  border: 1px solid var(--line-2);
  border-radius: 20px;
  font-size: 0.9em;
  color: var(--text);
  background: var(--bg-2);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, box-shadow 0.15s;
}
.build-weapon-tab:hover:not([data-locked="true"]) {
  border-color: var(--cyan);
  color: var(--cyan);
}
.build-weapon-tab--active {
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: 0 0 10px rgba(56, 225, 255, 0.2);
}
.build-weapon-tab--locked {
  opacity: 0.45;
  cursor: default;
}
.build-weapon-tab-glyph { color: inherit; font-size: 1.05em; display: inline-flex; align-items: center; }
/* ui-040: Glyph-<img> für Build-Sub-Tab. */
.build-weapon-tab-glyph img.wg-img { display: block; }
.build-weapon-badge {
  font-size: 0.84em; /* ui-344: 0.7em→0.84em, war ~9.45px */
  line-height: 1;
}
.build-weapon-badge--meta { color: var(--magenta); }
.build-weapon-badge--tpl  { color: var(--cyan); }
.build-weapon-tab-lock { font-size: 0.84em; } /* ui-344: 0.75em→0.84em, war ~10.13px */
/* ui-641/DL-2: Chip zeigt nur Icon + Wert -- "Hexa-Budget" bleibt als Text
   NUR fuers Screenreader/den Coachmark-Anker, Clip-Pattern wie
   pages/dashboard.css .tab-label--mobile (etabliertes Idiom). */
.build-hexa-pill-lbl {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---- Intro-Zeile ---- */
.build-intro {
  font-size: 0.88em;
  color: var(--muted);
  margin: 0 0 1em;
  line-height: 1.5;
}
.build-intro b { color: var(--text); font-weight: 600; }

/* ---- Weapon-Panels (CSS-toggle wie Hexas/Templates) ---- */
.build-weapon-panels { position: relative; }
.build-weapon-panel { display: none; }
.build-weapon-panel.is-active { display: block; }

/* ---- Locked-Panel ---- */
.build-locked-box {
  padding: 2em 1.5em;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-2);
}
.build-locked-glyph { font-size: 2em; color: var(--muted); margin-bottom: 0.3em; display: flex; align-items: center; justify-content: center; }
/* ui-040: Glyph-<img> für locked Build-Panel (--muted, kein Glow, DL-3). */
.build-locked-glyph img.wg-img { display: block; }
.build-locked-title { font-size: 1em; color: var(--muted); margin: 0 0 0.5em; }
.build-locked-text  { font-size: 0.88em; color: var(--muted); margin: 0.3em 0; }

/* ---- Progress-Header ---- */
.build-progress {
  display: flex;
  align-items: center;
  gap: 0.6em;
  flex-wrap: wrap;
  padding: 0.65em 1em;
  border: 1px solid var(--line);
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  background: linear-gradient(90deg, rgba(255,69,181,.07), rgba(56,225,255,.05));
  margin-bottom: 0;
}
.bp-title {
  font-weight: 600;
  color: var(--text);
  font-size: 0.95em;
  margin-right: auto;
}
/* ui-519: 0.74em (~9.62px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.bp-chip {
  font-size: var(--fs-caption);
  padding: 0.2em 0.6em;
  border-radius: 12px;
  border: 1px solid var(--line-2);
  color: var(--muted);
}
.bp-chip b { color: var(--text); }
.bp-chip--lift { border-color: rgba(56,225,255,.45); color: var(--cyan); }
.bp-chip--skip { border-color: rgba(255,216,74,.45); color: var(--yellow); }
.bp-chip--cost { border-color: rgba(255,216,74,.4);  color: var(--yellow); }

/* ---- Stepper ---- */
.build-stepper {
  border: 1px solid var(--line);
  border-top: none;
  border-radius: 0 0 10px 10px;
  background: var(--panel);
  overflow: hidden;
}
.build-stage {
  display: flex;
  gap: 0.9em;
  padding: 1em 1.1em;
  border-bottom: 1px solid var(--line);
  position: relative;
}
.build-stage:last-child { border-bottom: none; }
.build-spine {
  flex: 0 0 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}
/* ui-519 (K2-Pruefung, ui-489-Regeln): traegt bei Step-Stages nur die nackte
   Stufen-Nummer ("1"/"2"/…) in einer FIXEN 30x30px-Kreis-Kachel — exakt der
   K2-Whitelist-Fall "Nummern in fixen Kacheln" (ui-489-audit.md). 0.8em
   effektiv 10.4px im Desktop-Viewer-Embed (13px-Root) / 12px auf 15px-Root
   (Ursache s. Kommentar an .build-invest-cell-lvl weiter unten) — BEIDE
   ueber dem 10px-K2-Boden, unveraendert gelassen (kein Lesetext, die
   Sequenz-Nummer steht redundant auch in .build-step-no "Step N" daneben). */
.build-dot {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8em;
  font-weight: 800;
  position: relative;
  z-index: 1;
  transition: transform 0.15s, box-shadow 0.15s;
}
.build-spine-line {
  position: absolute;
  top: 30px;
  bottom: -30px;
  left: 50%;
  transform: translateX(-50%);
  width: 3px;
  background: var(--line-2);
  border-radius: 0;
  z-index: 0;
}
.build-stage-body { flex: 1; min-width: 0; }

/* Stage 0 — Hexa-Basis */
.build-stage--base {
  background: linear-gradient(180deg, rgba(255,69,181,.06), transparent);
}
.build-stage--base .build-dot {
  width: 34px;
  height: 34px;
  clip-path: polygon(25% 5%, 75% 5%, 100% 50%, 75% 95%, 25% 95%, 0 50%);
  border-radius: 0;
  background: rgba(255,69,181,.22) !important;
  outline: 2px solid var(--magenta);
  outline-offset: -2px;
  color: var(--magenta);
  box-shadow: none;
}
.build-stage--base .build-spine-line {
  background: linear-gradient(180deg, var(--magenta), var(--cyan));
  opacity: 0.55;
}
.build-stage--base.solo .build-spine-line { display: none; }

/* Step-Stages */
.build-stage--step.lift .build-dot {
  background: rgba(56,225,255,.12);
  color: var(--cyan);
  border: 1px solid var(--cyan);
  box-shadow: 0 0 10px rgba(56,225,255,.35);
}
.build-stage--step.skip .build-dot {
  background: rgba(255,216,74,.12);
  color: var(--yellow);
  border: 1px solid var(--yellow);
}
.build-stage--step.off .build-dot {
  background: transparent;
  color: var(--muted);
  border: 1px dashed var(--line-2);
}
.build-stage--step.lift .build-spine-line {
  background: var(--cyan);
  box-shadow: 0 0 8px rgba(56,225,255,.4);
  opacity: 0.9;
}
.build-stage--step.skip .build-spine-line {
  background: repeating-linear-gradient(
    180deg, var(--yellow) 0 6px, transparent 6px 12px);
  opacity: 0.7;
}
.build-stage--step.off .build-spine-line {
  background: repeating-linear-gradient(
    180deg, var(--muted) 0 4px, transparent 4px 10px);
  opacity: 0.5;
}
.build-stage--laststep .build-spine-line { display: none; }
.build-stage--step.lift:hover .build-dot { transform: scale(1.1); }

/* Hexa-Basis-Inhalt */
.build-base-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6em;
  flex-wrap: wrap;
}
.build-base-title  { font-weight: 600; color: var(--magenta); font-size: 0.95em; }
.build-base-invested { font-size: 0.8em; color: var(--muted); }
.build-base-invested b { color: var(--magenta); }
/* ui-519: 0.8em (~10.4px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.build-base-skips { margin-top: 0.5em; font-size: var(--fs-caption); color: var(--muted); line-height: 1.5; }
.build-base-skips b { color: var(--yellow); }

/* web-066: Pro-Waffe-Budget-Meter */
.build-budget {
  margin-top: 0.7em;
  padding: 0.6em 0.75em;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-2);
}
.build-budget-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6em;
  flex-wrap: wrap;
}
/* ui-519: 0.8em/0.78em (~10.4px/~10.14px effektiv im Desktop-Viewer-Embed —
   Ursache s. Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption
   (K1), beide Zeilen. */
.build-budget-lbl { font-size: var(--fs-caption); color: var(--text); font-weight: 600; }
.build-budget-lbl .wn { color: var(--cyan); }
.build-budget-nums { font-size: var(--fs-caption); color: var(--muted); }
.build-budget-nums b { color: var(--magenta); }
.build-budget-free { color: var(--green) !important; }
/* ui-534: Familien-Look-Angleich an input.build-invest-range (Slider-Balken
   direkt darunter im Invest-Grid) — Root-Cause war KEINE Regression: der
   Track hatte seit web-066 nie einen eigenen Border/Marker, nur die
   Karte (.build-budget) drumherum. Bei 0 % Füllstand (Fifty-Repro: frischer
   Gast, "0,0/2,0 verbaut") verschmolz der unbefüllte Track (background:
   var(--line), #1c2742) fast unsichtbar mit der Karten-Fläche
   (.build-budget: background var(--bg-2), #0d1322) — kein Border, kein
   Marker, während input.build-invest-range direkt darunter selbst bei
   Wert 0 einen leuchtenden Cyan-Thumb zeigt (Live-CDP-Beleg: Ticket
   `## Notes`). border + overflow:visible (statt hidden — gibt dem
   ::after-Marker unten den Raum, über die 9px-Track-Höhe hinauszuragen,
   identisch zum 16px-Thumb auf der 8px-Slider-Spur) sind neu; Füllfarbe
   bleibt Magenta (Farb-Schlüssel oben: "Magenta = Hexa-Basis", keine neue
   Farbwelt). */
.build-budget-meter {
  position: relative;
  height: 9px;
  margin-top: 0.5em;
  border: 1px solid var(--line-2);
  border-radius: 5px;
  background: var(--line);
  overflow: visible;
}
.build-budget-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: linear-gradient(90deg, var(--magenta), var(--magenta-light));
  border-radius: 5px;
  transition: width 0.22s ease;
}
/* ui-534: Positions-Marker am Füllstand-Ende — exakt Farb-/Rundungs-Vokabular
   des Slider-Thumbs (input.build-invest-range::-webkit-slider-thumb: Cyan-
   Kreis, --bg-Ring). Rein dekorativ (kein cursor/Drag) — reitet automatisch
   auf fillEl.style.width mit (::after ist relativ zur eigenen .build-budget-
   fill-Box positioniert, keine JS-/Markup-Änderung in templates.js nötig).
   Bleibt bewusst IMMER Cyan (auch im is-full-Zustand) — spiegelt den
   Slider-Thumb, der ebenfalls state-unabhängig ist; nur die Füllfarbe trägt
   die Magenta/Rot-Semantik. */
.build-budget-fill::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 0;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--cyan);
  border: 2px solid var(--bg);
  transform: translate(50%, -50%);
}
.build-budget.is-full .build-budget-fill {
  background: linear-gradient(90deg, var(--red), var(--red-light));
}
.build-budget-hint { font-size: var(--fs-caption); color: var(--muted); margin-top: 0.45em; } /* ui-505 (M3): 0.72em (~10.8px, 0.72em-Treppe) -> --fs-caption (K1) */
.build-budget.is-full .build-budget-hint { color: var(--red); }

/* Invest-Grid (Hexa-Basis) */
/* ui-461 Design-Lock 1 (web-241, P6-Kette): Karten-Minimum 172px -> 244px.
   Handys rendern durchgehend 1-spaltig; 2 Spalten erst ab einem Container
   >=~500px (jede Karte >=244px) — Fortsetzung des ui-343-Kanons
   "Lesbarkeit vor Dichte". Fiftys Symptom (a): bei ~430px-Geraetebreite
   erzwang der alte 172px-Boden 2 Spalten mit ~200px-Kacheln, in denen die
   nowrap-Zeilen (Design-Lock 2) mit den ±-Buttons kollidierten. */
.build-invest-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(244px, 1fr));
  gap: 0.45em;
  margin-top: 0.7em;
}
/* ui-135: Zelle wird Flex-Spalte (Top-Row + Slider darunter) */
/* ui-285: position:relative — Anker für den absolut positionierten Faktoren-Tooltip. */
/* ui-300: padding-top erhöht (0.5em → 1.45em), damit die erste Row (Glyph/Label/
   PM-Buttons) tiefer in der Kachel sitzt — schafft den Freiraum in der oberen
   Ecke, den ui-292 stattdessen über einen negativen top-Wert am Icon erzwungen
   hatte (das schob das sichtbare Icon aus der Box, ui-300-Ursache). Kachel wird
   dadurch insgesamt höher (Flex-Column, kein Umbruch) — genau Fiftys Vorgabe
   „Kachel höher, −/+ runter". */
.build-invest-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.45em;
  padding: 1.45em 0.55em 0.5em;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-2);
  transition: border-color 0.15s;
}
/* ui-498: .build-invest-cell.off entfernt — das Grid rendert nie mehr
   disabled/income-Kacheln (Render-Filter statt Anzeige-Zustand, s. templates.js
   buildInvestGrid()). */
/* ui-135: Vorschau-/Committing-States */
.build-invest-cell.is-preview    { border-color: var(--cyan); }
.build-invest-cell.is-committing { opacity: 0.7; }
/* ui-400: kein Zellen-z-index-Lift mehr noetig — das Tooltip rendert seit der
   CTTip-Migration im fixed Portal #ct-tip (z-250 seit ui-415, vormals z-80) an
   document.body und liegt damit strukturell ueber allen Kacheln/Geschwistern;
   der ui-287-Finding-B-Fall (Nachbar-.info stach durchs in-place-Panel) kann
   nicht mehr auftreten. */
/* ui-135: bisheriger Zellinhalt in Top-Row */
/* ui-461 Design-Lock 2 (web-241): Top-Row darf umbrechen statt zu quetschen
   — .main bekommt einen Flex-Basis-Bodensatz (130px statt 0%), damit die
   Reihe bei Enge sinnvoll umbricht (Prototyp .claude/sprint/prototypes/
   ui-461.html .v-soll .main), nicht erst wenn .main auf Null geschrumpft ist. */
.build-invest-cell-row  { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45em; }
/* ui-547: kein fixes width/font-size mehr — die Box umschließt jetzt nur
   noch das SVG-Kind, dessen Größe seither ALLEIN svg.stat-ic--lg traegt
   (components.css, 1.7rem statt der vormaligen 1em-Kette). flex-shrink:0
   haelt das groessere Icon bei knappem Platz stabil (die Nachbar-.main
   bricht stattdessen um, Design-Lock 2 unten). */
.build-invest-cell-glyph { color: var(--magenta); flex-shrink: 0; text-align: center; }
.build-invest-cell-main { flex: 1 1 130px; min-width: 0; }
/* ui-519: 0.8em (~10.4px effektiv im Desktop-Viewer-Embed, s. Ursachen-
   Kommentar an .build-invest-cell-lvl unten) -> --fs-caption (K1). */
.build-invest-cell-lbl  { font-size: var(--fs-caption); color: var(--text); }
/* ui-461 Design-Lock 2: kein nowrap mehr — Zahl+Einheit-Paare werden
   stattdessen in companion/collection/templates.js per U+00A0 (nbsp)
   gekoppelt (naechste 17.969,7 <icon>, +55 Lvl), damit
   Umbrueche nur zwischen logischen Gruppen fallen, nicht mitten in einer
   Zahl+Einheit. Fiftys Symptom (a): das alte nowrap liess die Kachel bei
   Enge NICHT umbrechen, wodurch Text ueber die ±-Buttons lief. */
/* ui-519 (Ursache fuer die ganze Attribut-Kachel-Familie): Companion-CSS
   nimmt zwar `html,body{font-size:15px}` (base.css) mit in den Desktop-
   Viewer-Embed (Setup-Popin, `#popin-mount.ct-embed-mount`) — aber
   `desktop.css` haelt seine EIGENE `body{font:13px/1.4 …}`-Deklaration
   bewusst als LETZTE im Kaskaden-Lock ("gewinnt zuletzt, auch gegen ein
   evtl. injiziertes Companion-CSS-Fragment", s. dortiger Kopfkommentar) —
   nur `<html>` bleibt bei Companions 15px (rem-Basis unveraendert), `<body>`
   UND jeder em-verkettete Nachfahre ohne eigene font-size (genau dieser
   ganze Kachel-Baum) rechnen ab 13px, nicht 15px. Live gemessen (CDP,
   `.build-invest-cell-lvl` vorher 0.74em): 15px-Root (Companion-Standalone
   /dashboard, NUR fuer Mobile-UA erreichbar) = 11.1px — ueber dem Boden, hat
   die ui-489/M3-Audits deshalb NICHT als Haertefall gefuehrt; 13px-Root
   (Desktop-Viewer-Embed — web-086 redirected JEDEN Desktop-Besuch von
   /dashboard dorthin, also der de-facto EINZIGE Pfad, den Fifty am Stream-
   PC sieht) = 9.62px, klar unter dem 11px-K1-Boden. Fix: Token/px statt
   em-Kette (ui-505-Regel) — --fs-caption ist rem-basiert (clamp auf
   0.7333–0.7667rem, tokens.css), rem zielt IMMER auf <html> (15px in
   BEIDEN Kontexten) und ist damit robust gegen den 13px-body-Override. */
.build-invest-cell-lvl  { font-size: var(--fs-caption); color: var(--magenta); font-weight: 600; }
.build-invest-cell-eff  { color: var(--cyan); font-weight: 700; }
/* ui-334: Kachel-Variante des Einheiten-Hinweises — "/" + Dart-SVG statt
   Fließtext (0.72em-Text war bei Kachel-Größe unleserlich, Fifty-Screenshot).
   Bedeutung bleibt in title/aria-label (Design-Lock 4), SVG selbst aria-hidden.
   currentColor am SVG, damit die Farbe (--muted, Design-Lock 5) am Wrapper hängt. */
.build-invest-cell-hint-icon { display: inline-flex; align-items: center; gap: 0.16em; color: var(--muted); vertical-align: baseline; }
/* ui-519: 1.05em bleibt em (echtes Skalierungsverhaeltnis "/" zur eigenen
   Zeile, ui-505-Ausnahme) — rechnet jetzt aber auf .build-invest-cell-lvls
   NEUEM --fs-caption-Wert (~11-11,5px) statt der alten em-Kette: effektiv
   ~11,55-12,08px, unabhaengig vom 13px/15px-Body-Kontext (s. Ursachen-
   Kommentar oben). Vormals (0.74em-Basis): 11,1px@15/9,62px@13 — unter Boden. */
.build-invest-cell-hint-icon .per { font-size: 1.05em; font-weight: 400; line-height: 1; }
.build-invest-cell-hint-icon svg { width: 11px; height: auto; display: block; color: inherit; }
/* ui-461 Design-Lock 2: kein nowrap mehr (s. .build-invest-cell-lvl oben —
   dieselbe Begruendung, &nbsp;-Kopplung uebernimmt templates.js). */
/* ui-519: 0.75em (~9.75px effektiv im Desktop-Viewer-Embed) -> --fs-caption
   (K1) — Ursache s. Kommentar an .build-invest-cell-lvl oben. */
.build-invest-cell-buy  { font-size: var(--fs-caption); color: var(--muted); margin-top: 1px; }
/* ui-135: Vorschau-Werte während des Ziehens cyan */
.build-invest-cell-lvl.is-preview { color: var(--cyan); }
.build-invest-cell-eff.is-preview { color: var(--cyan); }
/* ui-461 Design-Lock 2: margin-left:auto — rutscht bei Enge (flex-wrap auf
   .build-invest-cell-row, s.o.) als eigene, rechtsbuendige Zeile nach unten
   statt mit dem Label-Text zu kollidieren. */
.build-invest-cell-pm   { display: flex; gap: 0.2em; margin-left: auto; }
.build-invest-cell-pm button {
  padding: 0;
  width: 24px;
  height: 24px;
  border-radius: 5px;
  font-size: 1em;
  line-height: 1;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, transform 0.1s;
}
.build-invest-cell-pm button:hover:not(:disabled) { border-color: var(--cyan); color: var(--cyan); }
.build-invest-cell-pm button:active:not(:disabled) { transform: scale(0.85); }
.build-invest-cell-pm button:disabled { opacity: 0.35; cursor: not-allowed; }

/* ui-285: Faktoren-Erklär-Tooltip — Trigger-Icon + Inhalt (Referenz-Prototyp
   ui-285.html, Design-Locks). Trigger sitzt oben rechts in der Kachel, 44px-
   Hitbox via ::after (ui-214-Kanon), SVG erbt currentColor für alle States.
   ui-400: Öffnen/Anzeige läuft über CTTip (app.js) — der Wrap ist ein
   .tipwrap-Träger (Variante D), das Panel ist das gemeinsame Portal #ct-tip
   (ui-395-Block am Dateiende); hier bleiben nur Trigger-Optik + Inhalt.
   ui-300 (Fiftys Layout-Vorgabe, ersetzt den ui-292-Verschiebe-Trick): ui-292
   hatte den Y-Platzmangel über top:-4px gelöst — das schob das sichtbare Icon
   3px über die Kachel-Oberkante hinaus (Live-Screenshot-Fund). Statt das Icon
   aus der Box zu schieben, schafft ui-300 echten Platz IN der Kachel (erhöhtes
   .build-invest-cell padding-top, s.o.) und setzt das Icon zurück auf einen
   positiven top-Wert — jetzt vollständig innerhalb, sichtbar in der Ecke. */
/* Doppelklasse schlägt die .tipwrap-Basisregeln (position:relative,
   margin-left, ui-395-Block am Dateiende) unabhängig von der Regel-Reihenfolge
   (Spezifität 0-2-0) — der Waffe-Tab-Wrap ankert absolut in der Kachel-Ecke. */
.tipwrap.build-tipwrap { position: absolute; top: 3px; right: 5px; z-index: 5; margin-left: 0; }
.info {
  position: relative;
  color: var(--muted);
  line-height: 0;
  cursor: help;
  border: none;
  background: none;
  padding: 3px;
  border-radius: 999px;
  transition: color 0.15s ease, background 0.15s ease;
}
.info svg { display: block; width: 13px; height: 13px; }
/* ui-300: 44px-Hitbox (ui-214-Kanon: Gesamtgröße >=44x44) unverändert ggü.
   ui-292 — die Top/Bottom-Inset-SUMME muss bei konstanter Icon-Höhe (19px)
   konstant bei 25px bleiben (44−19), unabhängig von der neuen Icon-POSITION
   (top:3px statt -4px, s.o.) — die Hitbox wandert einfach mit dem Icon mit.
   Bleibt asymmetrisch: wächst mehr nach oben + links (Richtung Kachel-Ecke/
   Label-Bereich, wo nichts anderes klickbar ist) als nach rechts (Richtung
   Grid-Gap zur Nachbar-Kachel), und NUR knapp nach unten (bottom geringfügig
   NACH INNEN geschrumpft, Sicherheitsmarge) — genau dort sitzen die
   +/−-Buttons. Mit dem zusätzlichen Kachel-padding-top liegt die Hitbox jetzt
   mit deutlich mehr Puffer über der PM-Zeile (verifiziert, ## Notes). */
.info::after { content: ''; position: absolute; inset: -27px -9px 2px -16px; }
.build-invest-cell:hover .info { color: var(--text); }
/* Offen-State: CTTip setzt .tip-open auf den Wrap (Host), nicht mehr auf die
   Zelle (ui-400 — vormals .build-invest-cell.tip-open). */
.info:hover, .info:focus-visible, .build-tipwrap.tip-open .info {
  color: var(--cyan);
  background: rgba(56, 225, 255, 0.08); /* --cyan als rgba (kein var() in rgba() dekomponierbar) */
  outline: none;
}

/* ui-400: nur noch CONTENT-Styles — Rahmen (Fläche/Border/Schatten/Breite),
   Position (fixed, Viewport-geklemmt) und pointer-events:none kommen vom
   CTTip-Portal #ct-tip (seit web-241 in client/css/companion/components.css,
   vormals „ui-395-Block am Dateiende" derselben style.css). .build-tip-body
   steckt als Kind der versteckten .tip-Quelle in der Kachel und wird von
   CTTip per innerHTML ins Portal kopiert — diese Regeln wirken dort. Die
   frühere in-place-Mechanik (.build-stat-tip mit align-left/Clipping-
   Ancestor-JS, ui-285/287) ist entfernt: das fixed Portal kann von den
   overflow-Containern des Steppers nicht mehr beschnitten werden. Schrift
   bewusst auf den alten Werten (0.78rem/normal statt Portal-12.5px/1.5) —
   Optik-Lock ui-400. */
.build-tip-body { font-size: 0.78rem; line-height: normal; color: var(--text); }
.build-tip-body h4 { margin: 0 0 6px; font-size: 0.8rem; color: var(--text); font-weight: 600; }
.build-tip-body table { border-collapse: collapse; width: 100%; }
.build-tip-body td { padding: 2.5px 0; vertical-align: baseline; }
/* ui-461 Design-Lock 5 (web-241): Label-Spalte darf umbrechen (kein nowrap
   war hier je gesetzt — white-space:normal ist Default), zusaetzlich
   overflow-wrap:anywhere als Sicherheitsnetz gegen lange, leerzeichenlose
   Labels (z.B. zusammengesetzte Faktor-Namen) — verhindert horizontalen
   Uberlauf des jetzt breiteren (340px statt 250px, s. components.css), aber
   weiterhin schmalen #ct-tip-Portals auf Embed-Viewports. */
.build-tip-body td:first-child { color: var(--muted); padding-right: 14px; overflow-wrap: anywhere; }
.build-tip-body td:last-child {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.build-tip-body tr.dim td { color: var(--muted); opacity: 0.45; }
.build-tip-body tr.total td {
  border-top: 1px solid var(--line);
  padding-top: 5px;
  color: var(--cyan);
  font-weight: 700;
}
.build-tip-body .src-card  { color: var(--gold); }
.build-tip-body .src-weap  { color: var(--magenta); }
.build-tip-body .src-group { color: var(--green); }

/* ui-135: Slider-Zeile */
.build-invest-cell-slider { display: flex; align-items: center; gap: 0.5em; }
/* Range-Slider: Magenta-Fill via --fill-CSS-Var (Gradient), Cyan-Thumb */
/* ui-461 Design-Lock 4 (web-241): flex:1 1 0 (numerisch identisch zum
   vorigen "flex:1"-Shorthand, jetzt explizit ausgeschrieben) + min-width:0 —
   die eigentliche Wirkung ist min-width:0: ohne sie greift der Flex-Item-
   Default min-width:auto (= intrinsische <input type=range>-Breite), das
   Slider verweigert dadurch das Schrumpfen und draengt das Nachbar-Label
   (.build-invest-range-max) aus der Kachel. Fiftys Symptom (b). */
input.build-invest-range {
  flex: 1 1 0;
  min-width: 0;
  -webkit-appearance: none;
  appearance: none;
  height: 8px;
  border-radius: 5px;
  background: linear-gradient(
    90deg,
    var(--magenta) 0 var(--fill, 0%),
    var(--line)    var(--fill, 0%)
  );
  cursor: pointer;
  margin: 0;
  outline-offset: 3px;
}
input.build-invest-range:disabled { opacity: 0.4; cursor: not-allowed; }
/* Thumb = Cyan (interaktiv), gespiegelt aus Prototyp */
input.build-invest-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--cyan);
  border: 2px solid var(--bg);
  cursor: grab;
  transition: box-shadow 0.15s, transform 0.1s;
}
input.build-invest-range:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 4px rgba(56, 225, 255, 0.3);
}
input.build-invest-range:active::-webkit-slider-thumb {
  cursor: grabbing;
  transform: scale(1.12);
}
input.build-invest-range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--cyan);
  border: 2px solid var(--bg);
  cursor: grab;
}
input.build-invest-range::-moz-range-track { background: transparent; }
/* ui-461 Design-Lock 4: font-size 0.75em -> 0.72em (Prototyp-/Ticket-Wert)
   + explizites flex:0 1 auto (Default-Wert, jetzt dokumentiert — der Slider
   nebenan traegt jetzt die Schrumpf-Last, s.o.). white-space:nowrap +
   min-width:3.6em bleiben (Label bleibt in bounds, bricht nicht).
   ui-505 (M3): 0.72em (~10.8px, 0.72em-Treppe) -> --fs-caption (K1) — Design-
   Lock-4-Historie bleibt oben stehen, min-width:3.6em skaliert weiterhin mit
   der (jetzt token-basierten) eigenen font-size, kein Layout-Bruch. */
.build-invest-range-max { font-size: var(--fs-caption); color: var(--muted); white-space: nowrap; min-width: 3.6em; text-align: right; flex: 0 1 auto; }

/* ui-135: Vorschau-Segment im Budget-Meter (gestrichelt Cyan) */
.build-budget-preview {
  position: absolute;
  top: 0;
  bottom: 0;
  background: repeating-linear-gradient(
    45deg,
    var(--cyan),   var(--cyan)   3px,
    transparent    3px,          transparent 6px
  );
  opacity: 0.55;
  transition: none;
}

/* ui-498: Collapse-Toggle (.build-base-collapse) entfernt — das Basis-Grid
   zeigt immer alle levelbaren Stats, kein „nur investierte/alle zeigen"-
   Umschalter mehr. */

/* Reset-Sektion */
.build-reset-row {
  display: flex;
  align-items: center;
  gap: 0.8em;
  margin-top: 0.8em;
  flex-wrap: wrap;
}
/* ui-519: 0.82em (~10.66px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.build-reset-btn {
  font-size: var(--fs-caption);
  padding: 0.35em 0.8em;
  border: 1px solid var(--red);
  color: var(--red);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  transition: box-shadow 0.15s;
}
.build-reset-btn:hover:not(:disabled) {
  box-shadow: 0 0 10px rgba(255, 77, 110, 0.3);
}
.build-reset-btn:disabled { opacity: 0.35; cursor: not-allowed; }
/* ui-519: 0.78em (~10.14px effektiv im Desktop-Viewer-Embed) -> --fs-caption
   (K1) — Ursache s. Kommentar an .build-invest-cell-lvl weiter unten. */
.build-refund-txt { font-size: var(--fs-caption); color: var(--muted); }
.build-refund-txt b { color: var(--magenta); }

/* ---- Step-Karte ---- */
.build-step-row {
  display: flex;
  align-items: center;
  gap: 0.7em;
  flex-wrap: wrap;
}
.build-step-drag {
  cursor: grab;
  color: var(--muted);
  font-size: 1em;
  user-select: none;
  padding: 0 0.1em;
  flex-shrink: 0;
}
.build-step-head { display: flex; align-items: center; gap: 0.5em; flex-wrap: wrap; flex: 1; min-width: 0; }
.build-step-no {
  font-size: var(--fs-caption); /* ui-505 (M3): 0.68em (~10.2px) -> --fs-caption (K1) — "Step N"-Text, keine blosse Zahl */
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 0.08em 0.5em;
  white-space: nowrap;
}
.build-stage--step.lift .build-step-no { color: var(--cyan);   border-color: rgba(56,225,255,.4); }
.build-stage--step.skip .build-step-no { color: var(--yellow); border-color: rgba(255,216,74,.4); }

/* ui-547: Attribut-Icon links vom Stat-Select (svg.stat-ic--lg trägt die
   Größe, components.css) — Zustandsfarben spiegeln die .build-step-no-Pille
   direkt daneben (Basis/off = muted, lift = cyan, skip = yellow). */
.build-step-icon { display: inline-flex; align-items: center; flex-shrink: 0; color: var(--muted); }
.build-stage--step.lift .build-step-icon { color: var(--cyan); }
.build-stage--step.skip .build-step-icon { color: var(--yellow); }

/* Step-Stat-Select */
.build-step-select {
  appearance: none;
  background: var(--bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%2338e1ff' fill='none' stroke-width='1.4'/%3E%3C/svg%3E") no-repeat right 0.55em center;
  border: 1px solid var(--line-2);
  color: var(--text);
  border-radius: 6px;
  padding: 0.3em 1.7em 0.3em 0.55em;
  font-family: inherit;
  font-size: 0.9em;
  font-weight: 600;
  cursor: pointer;
}
.build-step-select:focus {
  outline: none;
  border-color: var(--cyan);
  box-shadow: 0 0 0 2px rgba(56,225,255,.18);
}
.build-stage--step.skip .build-step-select { color: var(--yellow); }
.build-stage--step.off  .build-step-select { color: var(--muted); }

/* Step-Sub-Zeile */
/* ui-519: 0.8em (~10.4px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.build-step-sub { font-size: var(--fs-caption); color: var(--muted); margin-top: 2px; }
.build-step-sub .from { color: var(--muted); }
.build-step-sub .to   { color: var(--cyan); font-weight: 600; }
.build-stage--step.skip .build-step-sub .to { color: var(--yellow); }

/* Level im Spiel (game-158, vormals "Ziel-Level") */
.build-step-target {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2em;
  flex-shrink: 0;
}
.build-step-target-top { display: flex; align-items: center; gap: 0.35em; }
.build-step-target label { font-size: var(--fs-caption); color: var(--muted); } /* ui-505 (M3): 0.72em (~10.8px, 0.72em-Treppe) -> --fs-caption (K1) */
/* game-158: graue Vorschau des effektiven Endlevels (Level im Spiel + Hexa-Basis) unter der +/--Zeile. */
.build-step-target-meta { font-size: var(--fs-caption); color: var(--muted); white-space: nowrap; }
.build-step-target-pm { display: flex; align-items: center; gap: 0.25em; }
.build-step-target-pm button {
  padding: 0;
  width: 24px;
  height: 24px;
  border-radius: 5px;
  font-size: 1em;
  line-height: 1;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, transform 0.1s;
}
.build-step-target-pm button:hover:not(:disabled) { border-color: var(--cyan); color: var(--cyan); }
.build-step-target-pm button:active:not(:disabled) { transform: scale(0.85); }
.build-step-target-pm button:disabled { opacity: 0.35; cursor: not-allowed; }
.build-step-target input {
  width: 56px;
  background: var(--bg);
  border: 1px solid var(--line-2);
  color: var(--text);
  border-radius: 5px;
  padding: 0.28em 0.4em;
  font-size: 0.9em;
  text-align: center;
  font-family: inherit;
}
.build-step-target input:focus {
  outline: none;
  border-color: var(--cyan);
}

/* Kosten + Delete */
/* ui-519: 0.82em (~10.66px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.build-step-cost {
  font-size: var(--fs-caption);
  color: var(--yellow);
  white-space: nowrap;
  min-width: 70px;
  text-align: right;
  flex-shrink: 0;
}
.build-step-del {
  padding: 0;
  width: 26px;
  height: 26px;
  border-radius: 5px;
  color: var(--muted);
  border: 1px solid var(--line);
  background: transparent;
  font-size: 1em;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  transition: color 0.12s, border-color 0.12s;
}
.build-step-del:hover { color: var(--red); border-color: var(--red); }

/* Step-Pills */
.build-step-pill {
  display: inline-block;
  font-size: var(--fs-caption); /* ui-505 (M3): 0.68em (~10.2px) -> --fs-caption (K1) — traegt echten Skip-/Off-Grund als Text */
  padding: 0.12em 0.5em;
  border-radius: 10px;
  margin-top: 0.3em;
}
.build-pill-skip { color: var(--yellow); border: 1px solid rgba(255,216,74,.4);  background: rgba(255,216,74,.06); }
.build-pill-off  { color: var(--muted);  border: 1px solid var(--line-2); }

/* Add-Step-Zeile */
.build-stage--add {
  padding: 0.65em 1.1em;
  display: flex;
  flex-direction: column;
  gap: 0.5em;
}
/* ui-553: Typ-Vorwahl-Zeile (Icon-Slot + natives Select, .build-step-icon/
   .build-step-select wiederverwendet — gleiche Optik/Helfer wie die
   Step-Zeilen, s. templates.js). Eigene Zeile ÜBER dem Hinzufügen-Button
   (statt daneben) hält jede der beiden Zeilen bei jeder Breite auf ihrer
   natürlichen Mindestbreite — bei 390px reicht ein einzelnes flex:1-Select
   robuster als ein 3-Spalten-Wettbewerb um dieselbe Zeile. */
.build-add-picker {
  display: flex;
  align-items: center;
  gap: 0.5em;
}
.build-add-select {
  flex: 1;
  min-width: 0;
}
.build-add-btn {
  border: 1px dashed var(--line-2);
  color: var(--muted);
  width: 100%;
  padding: 0.5em;
  background: transparent;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.9em;
  font-family: inherit;
  transition: border-color 0.15s, color 0.15s;
}
.build-add-btn:hover { border-color: var(--cyan); color: var(--cyan); }

/* Empty-Hint */
.build-empty-hint {
  padding: 1.4em 1.1em;
  color: var(--muted);
  font-size: 0.9em;
  text-align: center;
  line-height: 1.6;
}

/* SortableJS-Drag-States (ui-390: Step-Reorder via SortableJS statt nativer
   HTML5-DnD — die fruehere .build-dragover-Indikatorlinie entfaellt).
   Ghost = semi-transparenter Platzhalter an der Einfuegeposition, Chosen =
   die Stage, die der User gerade haelt (analog templates.js-Order-Rows;
   .build-stage hat keinen eigenen Rahmen, daher Inset-Glow statt border). */
.build-stage--step.sortable-ghost {
  opacity: 0.35;
  background: rgba(56, 225, 255, 0.08);
}
.build-stage--step.sortable-chosen {
  box-shadow: 0 0 12px rgba(255, 69, 181, 0.25) inset;
}
.build-stage--step.sortable-chosen .build-step-drag { cursor: grabbing; }

/* ui-390: Touch-Targets >=44px fuer die Build-Step-Controls (Waffe-Tab).
 * Der ⋮⋮-Reorder-Griff (~10px breit) ist seit ui-390 der einzige Drag-
 * Startpunkt (SortableJS handle) — ohne 44px-Flaeche ist das Touch-Reorder
 * praktisch nicht treffbar. Ziel-Level +/− waren 24x24, der Hexa-Invest-
 * Slider-Thumb 16x16. Nur Touch-Geraete; Desktop/OBS bleiben byte-gleich.
 * REIHENFOLGE: Block steht bewusst NACH den Basis-Regeln (.build-step-drag,
 * .build-step-target-pm button, Slider-Thumbs — alle oben in dieser Datei) —
 * bei gleicher Spezifitaet gewinnt die spaetere Regel; im ui-204-Sammel-Block
 * (pages/shared-mobile.css, dort VOR den Build-Basis-Regeln geladen) wuerden diese hier verlieren.
 * ui-394 (44px-Sweep, web-221 P3.1): Build-nahe Mess-Treffer sind unten in
 * diesem Block einsortiert; der Rest des Sweeps (Nicht-Build-Surfaces)
 * steht im ui-394-Block am DATEIENDE (dort begruendet). */
@media (hover: none), (pointer: coarse) {
  .build-step-drag {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .build-step-target-pm button {
    width: 44px;
    height: 44px;
  }
  input.build-invest-range::-webkit-slider-thumb {
    width: 44px;
    height: 44px;
  }
  input.build-invest-range::-moz-range-thumb {
    width: 44px;
    height: 44px;
  }

  /* ui-394 (Messbefund 390x844/768x1024): weitere Build-Controls unter 44px.
   * Basis-Regeln liegen alle OBERHALB dieses Blocks in dieser Datei (invest-pm,
   * invest-range, base-collapse, reset, step-select, target-input, step-del,
   * add) — gehoeren deshalb HIER rein, nicht in den ui-204-Sammel-Block. */
  /* ui-461 Design-Lock 3 (web-241): + border-radius/font-size (width/height
     44px war schon Bestand seit ui-390, s.o. — "44 ist verbindlich", der
     Prototyp-Toggle mit 42px war nur eine Naeherung). Desktop/Maus bleibt
     24x24px (Basisregel oben, unveraendert) — dieser Block greift NUR unter
     hover:none/pointer:coarse. */
  .build-invest-cell-pm button {
    width: 44px;   /* Basis 24x24 — Hexa-Invest +/− pro Stat-Kachel */
    height: 44px;
    border-radius: 8px;
    font-size: 1.15em;
  }
  /* Hexa-Invest-Slider: die effektive Grab-Zone des <input> ist seine
   * Border-Box (8px hoch) — der 44px-Thumb (ui-390, oben) wirkt nur
   * INNERHALB dieser Box. height 44 + padding-block 18 vergroessert die
   * Hit-Zone auf 44px; background-clip:content-box haelt den gezeichneten
   * Track-Gradient auf den 8px-Content (border-box: 44 − 2×18 = 8). */
  input.build-invest-range {
    height: 44px;
    padding-block: 18px;
    background-clip: content-box;
  }
  .build-step-select { min-height: 44px; }   /* Basis ~28px (padding-basiert) */
  .build-step-target input { height: 44px; } /* Ziel-Level-Feld, Basis ~28px */
  .build-step-del {
    width: 44px;   /* Basis 26x26 — Schritt-Loeschen ✕ */
    height: 44px;
  }
  .build-reset-btn { min-height: 44px; }     /* „Basis zuruecksetzen", 28px */
  .build-add-btn { min-height: 44px; }       /* „+ Schritt hinzufuegen", 34px */
  /* Overlap-Schutz fuer die vergroesserten Targets: head behaelt eine echte
   * Mindestbreite statt flex-basis-0-Quetschung (flex:1 + min-width:0 in der
   * Basis) — die Row wrappt (flex-wrap existiert dort), statt dass das
   * Select ueber die 44px-Buttons ragt. Gleiche drei Regeln stehen auch im
   * ≤600px-Block (pages/dashboard.css „Build-Stepper: Schritt-Zeile"), der den
   * frueheren stalen Grid-Override ersetzt (Root-Cause-Messbefund dort) —
   * dieser Block hier deckt Touch-Geraete BREITER 600px ab (Tablets), wo der
   * ≤600px-Block nicht greift. */
  .build-step-row { row-gap: 0.45em; }
  .build-step-head { min-width: min(100%, 220px); }
  .build-step-select { max-width: 100%; min-width: 0; }
}

/* ---- End-Zustand ---- */
.build-endstate {
  margin-top: 1.2em;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-2);
  padding: 1em 1.1em;
}
.build-endstate h3 { margin: 0 0 0.15em; font-size: 0.95em; color: var(--green); }
/* ui-519: 0.82em (~10.66px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter unten) -> --fs-caption (K1). */
.build-endstate-sub { font-size: var(--fs-caption); color: var(--muted); margin-bottom: 0.7em; }
.build-es-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 0.75em;
}
.build-es-cell {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.42em 0.6em;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
}
.build-es-cell.off { opacity: 0.35; }
/* ui-547: kein fixes width mehr — s. .build-invest-cell-glyph-Kommentar
   weiter oben in dieser Datei (dieselbe Begründung, svg.stat-ic--lg traegt
   die Größe). */
.build-es-g { color: var(--muted); text-align: center; flex-shrink: 0; }
/* ui-519: 0.82em (~10.66px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter oben in dieser Datei) ->
   --fs-caption (K1). */
.build-es-l { flex: 1; font-size: var(--fs-caption); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.build-es-bar {
  flex: 0 0 56px;
  height: 6px;
  border-radius: 4px;
  background: var(--line);
  overflow: hidden;
  display: flex;
  flex-shrink: 0;
}
.build-es-bar .seg-meta { background: var(--magenta); }
.build-es-bar .seg-lift { background: var(--cyan); }
/* ui-519: 0.8em (~10.4px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter oben in dieser Datei) ->
   --fs-caption (K1). */
.build-es-v { font-size: var(--fs-caption); color: var(--text); font-weight: 600; min-width: 60px; text-align: right; flex-shrink: 0; }

/* ---- ui-486/DL-6: Fokus-Set — eigenständiger, EINZIGER Fokus-Set-Editor ----
   Vormals web-166 "Fokus-Set danach"-Endmode-Chooser (NUR bei Template
   sichtbar, Min-1-Guard) — DL-6 ersetzt ihn durch diesen IMMER sichtbaren
   Block; .em-allmode-badge/.em-hint/.em-chip.is-locked sind mit dem
   Min-1-Guard entfallen (toter-Code-Sweep). */
.build-endmode {
  margin-top: 1.2em;
  border-top: 1px solid var(--line);
  padding-top: 1em;
}
.build-endmode-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5em;
  margin-bottom: 0.15em;
}
.build-endmode-head h3 { margin: 0; font-size: 0.95em; color: var(--cyan); }
/* ui-519: 0.82em (~10.66px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter oben in dieser Datei) ->
   --fs-caption (K1). */
.build-endmode-sub { font-size: var(--fs-caption); color: var(--muted); margin: 0.7em 0 0; }

.em-grid { display: flex; flex-wrap: wrap; gap: 0.45em; }

/* Toggle-Chip = Checkbox-Affordanz. Checked = cyan (primär/interaktiv).
   ui-519: 0.84em (~10.92px effektiv im Desktop-Viewer-Embed, knapp unter dem
   Boden — Ursache s. Kommentar an .build-invest-cell-lvl weiter oben in
   dieser Datei) -> --fs-caption (K1); traegt .em-l (Stat-Name-Lesetext). */
.em-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-height: 38px;
  padding: 0.3em 0.7em 0.3em 0.55em;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--bg-2);
  color: var(--muted);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.15s, color 0.15s, background 0.15s, box-shadow 0.15s;
  font-size: var(--fs-caption);
}
.em-chip:hover { border-color: rgba(56, 225, 255, 0.55); color: var(--text); }
.em-chip:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
/* ui-519 (K2-Whitelist-Aufnahme, ui-489-Regeln): das Haekchen-Glyph ist reine
   Redundanz-Deko — der "an"-Zustand des Chips ist BEREITS ueber Border/
   Hintergrund/Box-Shadow (.em-chip.is-on unten) sichtbar, das Haekchen selbst
   traegt keine eigene Information ("wer es nicht lesen kann, verliert
   nichts"). War bereits VOR diesem Ticket ein bekannter Haertefall
   (ui-489-audit.md Liste A: "10.08px | build.css:1001 | .em-chip .em-box"),
   von M3 (ui-505) nicht mit-migriert. em-relativ auf .em-chip waere ohnehin
   strukturell falsch: 0.8em auf DEM NEUEN --fs-caption-Wert (~11-11,5px)
   ergaebe wieder nur ~8,8-9,2px, also unter selbst dem K2-Boden — deshalb
   --fs-micro (10px, fixer K2-Token) statt einer weiteren em-Kette. */
.em-chip .em-box {
  width: 1.05em;
  height: 1.05em;
  border-radius: 4px;
  flex-shrink: 0;
  border: 1.5px solid var(--line-2);
  display: grid;
  place-items: center;
  font-size: var(--fs-micro);
  color: var(--text-on-accent);
  line-height: 1;
  transition: background 0.15s, border-color 0.15s;
}
/* ui-547: kein fixes width mehr — s. .build-invest-cell-glyph-Kommentar
   weiter oben in dieser Datei (dieselbe Begründung, svg.stat-ic--lg traegt
   die Größe; flex-shrink:0 haelt den Chip stabil, .em-l bricht bei Bedarf
   in den naechsten Chip statt das Icon zu quetschen). */
.em-chip .em-g { color: var(--muted); flex-shrink: 0; text-align: center; transition: color 0.15s; }
.em-chip .em-l { white-space: nowrap; }

.em-chip.is-on {
  border-color: var(--cyan);
  color: var(--text);
  background: rgba(56, 225, 255, 0.10);
  box-shadow: 0 0 10px rgba(56, 225, 255, 0.18);
}
.em-chip.is-on .em-box { background: var(--cyan); border-color: var(--cyan); }
.em-chip.is-on .em-g { color: var(--cyan); }

.em-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8em;
  margin-top: 0.7em;
}
/* ui-518: der frühere "Speichern"-Button (.em-save, DL-2) ist ersatzlos
   entfernt (Chip-Klick speichert jetzt automatisch, s. templates.js
   toggle()/saveFocusSet()) — die Regel dazu ist mit ihm entfernt, kein
   totes CSS für ein nicht mehr existentes Element. */
/* ui-519: 0.78em (~10.14px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter oben in dieser Datei) ->
   --fs-caption (K1), beide verbliebenen Regeln (Set-leeren/Status-Text). */
.em-reset {
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--muted);
  font: inherit;
  font-size: var(--fs-caption);
  padding: 0.3em 0.8em;
  border-radius: 999px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.em-reset:hover { border-color: var(--cyan); color: var(--cyan); box-shadow: none; }
/* DL-2 Status-Text ("gespeichert: N Attribute" / "kein Set gespeichert") —
   neutral, kein Warn-Ton (Kontrast zum entfallenen .em-hint, das ein
   Min-1-Guard-Warnblitzen war). */
.em-state { font-size: var(--fs-caption); color: var(--muted); }

/* =====================================================================
   ui-655: Template-Import ("Von anderem Tower importieren")
   Design-Quelle: .claude/sprint/prototypes/template-import.html (Fifty
   abgenommen 17.09.). Einstieg (.build-import-entry) direkt unter
   .build-add-btn (gleiche Baustein-Optik, Hover/Fokus Gold statt Cyan).
   Popin/Sheet ist ein EIGENER Backdrop (nicht components.css
   .cs-modal-backdrop — dessen Mobile-Default ist zentriert, hier ist
   Mobil explizit ein Bottom-Sheet, s. @media unten), Panel-Look wie
   pages/techtree.css .tt-pop (Panel-Hintergrund, Cyan-Rahmen, Radius,
   Shadow). Bestätigen-Knopf reutzt die build-reset-btn-Familie NUR farblich
   (roter Rahmen + identischer Hover-Glow-Wert), eigene Maße fürs Popin-
   Footer statt der kleinen Reset-Zeilen-Größe.
   ===================================================================== */

.build-import-entry { display: flex; flex-direction: column; gap: 0.35em; margin-top: 0.5em; }
.build-import-btn:hover, .build-import-btn:focus-visible { border-color: var(--gold); color: var(--gold); outline: none; }
.build-import-cap { font-size: var(--fs-caption); color: var(--muted); }

.build-import-backdrop {
  position: fixed;
  inset: 0;
  /* Gleiche Rolle wie components.css .cs-modal-backdrop (ein echtes
     blockierendes role="dialog"-Modal, das auch aus einem offenen Setup-
     Popin heraus geöffnet werden kann, #popin-scrim z-200) — selber
     Zahlenwert, kein neuer Stapel nötig. */
  z-index: 260;
  background: rgba(3, 5, 12, 0.72);
  display: none;
  align-items: center;
  justify-content: center;
  padding: max(20px, env(safe-area-inset-top, 0px)) max(20px, env(safe-area-inset-right, 0px)) max(20px, env(safe-area-inset-bottom, 0px)) max(20px, env(safe-area-inset-left, 0px));
}
.build-import-backdrop.open { display: flex; }
.build-import-modal {
  width: min(440px, 100%);
  max-height: min(88svh, 780px);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--cyan);
  border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6);
}
.build-import-head {
  padding: 12px 14px 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.build-import-title { font-weight: 700; }
.build-import-steps { margin-left: auto; font-size: var(--fs-caption); color: var(--muted); letter-spacing: 0.04em; }
.build-import-steps b { color: var(--cyan); }
.build-import-x {
  border: none;
  background: none;
  color: var(--muted);
  font-size: 15px;
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
  border-radius: 6px;
}
.build-import-x:hover, .build-import-x:focus-visible { color: var(--cyan); outline: none; }
.build-import-body { padding: 10px 14px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.build-import-foot {
  padding: 10px 14px 14px;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
  flex-shrink: 0;
}
.build-import-lead { color: var(--text-dim); font-size: 13px; margin: 0 0 8px; }

/* Schritt 1 — Auswahl-Zeilen */
.build-import-src {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 10px;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  margin: 6px 0;
  cursor: pointer;
  background: var(--bg-2);
}
.build-import-src:hover, .build-import-src:focus-visible { border-color: var(--cyan); outline: none; }
.build-import-src.is-selected { border-color: var(--cyan); box-shadow: 0 0 0 2px rgba(56, 225, 255, 0.18); }
.build-import-src.is-unavailable { opacity: 0.45; cursor: not-allowed; }
.build-import-src-icon { width: 30px; height: 30px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.build-import-src-main { flex: 1; min-width: 0; }
.build-import-src-name { font-weight: 700; }
.build-import-src-meta { font-size: var(--fs-caption); color: var(--muted); }
.build-import-src-prev { font-size: 12px; color: var(--text-dim); margin-top: 3px; }
.build-import-more { color: var(--muted); }
.build-import-src-radio { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line-2); margin-top: 6px; flex-shrink: 0; }
.build-import-src.is-selected .build-import-src-radio { border-color: var(--cyan); background: radial-gradient(var(--cyan) 45%, transparent 50%); }

/* Schritt 2 — Bestätigung */
.build-import-warn { border: 1px solid var(--red); background: rgba(255, 77, 110, 0.08); color: var(--text); border-radius: 8px; padding: 9px 11px; font-size: 13.5px; }
.build-import-warn b { color: var(--red); }
.build-import-ok { border: 1px solid var(--line-2); background: var(--bg-2); border-radius: 8px; padding: 9px 11px; font-size: 13.5px; }
.build-import-summary { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 13px; }
.build-import-summary td { padding: 4px 0; vertical-align: top; }
.build-import-summary td.k { color: var(--muted); width: 88px; }
.build-import-skiphint { margin-top: 10px; font-size: 12.5px; color: var(--yellow); border-left: 3px solid var(--yellow); padding-left: 8px; }
.build-import-focus-row {
  margin-top: 10px;
  display: flex;
  gap: 8px;
  align-items: flex-start;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  padding: 8px 10px;
  background: var(--bg-2);
}
.build-import-focus-row input { margin-top: 3px; accent-color: var(--cyan); }
.build-import-focus-row.is-locked { opacity: 0.55; cursor: not-allowed; }
.build-import-focus-cap { display: block; font-size: var(--fs-caption); color: var(--muted); margin-top: 2px; }

/* Footer-Buttons */
.build-import-autosave { font-size: var(--fs-caption); color: var(--muted); flex-basis: 100%; text-align: right; margin-bottom: 2px; }
.build-import-foot-btn {
  font-family: inherit;
  font-size: var(--fs-small);
  padding: 0.5em 1.1em;
  min-height: 44px;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, box-shadow 0.15s;
}
.build-import-foot-btn:hover, .build-import-foot-btn:focus-visible { border-color: var(--cyan); color: var(--cyan); outline: none; }
.build-import-foot-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.build-import-foot-btn--go { border-color: var(--cyan); color: var(--cyan); }
/* build-reset-btn-Familie (Design-Lock): identischer roter Rahmen +
   derselbe Hover-Glow-Wert wie .build-reset-btn:hover weiter oben in
   dieser Datei — eigene Klasse, weil die Footer-Buttons hier größer sind
   als die kompakte Reset-Zeile im Editor selbst. */
.build-import-foot-btn--danger { border-color: var(--red); color: var(--red); }
.build-import-foot-btn--danger:hover, .build-import-foot-btn--danger:focus-visible {
  border-color: var(--red);
  color: var(--red);
  box-shadow: 0 0 10px rgba(255, 77, 110, 0.3);
}

/* Mobil: Bottom-Sheet statt zentriertem Popin (Design-Lock) — derselbe
   600px-Schwellwert wie der Rest dieser Datei (s. .weapon-grid oben). */
@media (max-width: 600px) {
  .build-import-backdrop { align-items: flex-end; padding: 0; }
  .build-import-modal {
    width: 100%;
    max-height: 86svh;
    border-radius: 16px 16px 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
}

/* Import-Flash (frisch importierte Steps + ggf. Fokus-Set-Block, Design-Lock) */
@keyframes buildImportFlash {
  0% { background: rgba(56, 225, 255, 0.16); }
  100% { background: transparent; }
}
.build-import-flash { animation: buildImportFlash 1.4s ease-out 1; }

/* ---- Legende ---- */
/* ui-519: 0.78em (~10.14px effektiv im Desktop-Viewer-Embed — Ursache s.
   Kommentar an .build-invest-cell-lvl weiter oben in dieser Datei) ->
   --fs-caption (K1). */
.build-legend {
  display: flex;
  gap: 1em;
  flex-wrap: wrap;
  font-size: var(--fs-caption);
  color: var(--muted);
  margin-top: 0.9em;
}
.build-legend span { display: inline-flex; align-items: center; gap: 0.4em; }
.sw { width: 18px; height: 7px; border-radius: 3px; display: inline-block; }
.sw-meta { background: var(--magenta); }
.sw-lift { background: var(--cyan); }
.sw-skip { background: repeating-linear-gradient(90deg, var(--yellow) 0 4px, transparent 4px 8px); }
.sw-off  { background: repeating-linear-gradient(90deg, var(--muted)  0 3px, transparent 3px 7px); }

/* Pulse-Animation (Lift-Dot beim Re-Render) */
@keyframes buildPulseDot {
  0%   { box-shadow: 0 0 0 0   rgba(56,225,255,.55); }
  100% { box-shadow: 0 0 0 14px rgba(56,225,255,0); }
}
.build-dot.justlift { animation: buildPulseDot 0.6s ease-out; }

/* noscript-Hinweis */
.build-noscript-hint {
  padding: 1.2em;
  color: var(--muted);
  font-size: 0.88em;
  text-align: center;
}
