/* ============================================================
   Piazza Studio — neue App-Shell, Dashboard & Projektansicht
   ------------------------------------------------------------
   Namespace `.ps-*` (getrennt vom alten `.cp-*`-Chrome, das während
   der Übergangszeit unangetastet bleibt). Nur `--ps--*`-Tokens; die
   wenigen Design-Literale (#1f473c/#00815d/#3bd17f …) sind über
   Tokens abgebildet, sofern vorhanden.

   Collapse-Animation (kritisch): Sidebar `position:absolute` + width-
   Transition, Content `margin-left`-Transition — NICHT flex-basis
   (friert in Chromium ein). Erste Frame ohne Transition (.no-anim).
   ============================================================ */

.ps-shell {
  position: relative;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background: var(--ps--neutral-50);
  font-family: var(--ps--font-sans);
  --ps-side-w: 224px;
  --ps-chrome-h: 60px;
}
.ps-shell.is-collapsed { --ps-side-w: 78px; }
/* Erste Frame: alle Transitionen aus, damit nichts „aufklappt". */
.ps-shell.no-anim,
.ps-shell.no-anim * { transition: none !important; }

/* Nur für Screenreader: visuell versteckt, aber weiterhin vorlesbar. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Sidebar (dunkelgrün) ---- */
.ps-side {
  position: absolute;
  left: 0; top: 0;
  height: 100vh;
  width: var(--ps-side-w);
  z-index: 20;
  background: var(--ps--bg-inverse);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: width var(--ps--duration-slow) var(--ps--ease-standard);
}

.ps-side__brand {
  position: relative;
  flex: 0 0 auto;
  height: var(--ps-chrome-h);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  overflow: hidden;
}
.ps-side__logo {
  position: absolute;
  left: 16px; top: 50%;
  transform: translateY(-50%);
  width: 160px; height: auto; max-height: 42px;
  object-fit: contain; object-position: left center;
  opacity: 1;
  transition: opacity var(--ps--duration-base);
  cursor: pointer;
}
.ps-side__signet {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  height: 32px; width: auto;
  opacity: 0;
  transition: opacity var(--ps--duration-base);
  cursor: pointer;
  pointer-events: none;
}
.ps-shell.is-collapsed .ps-side__signet { pointer-events: auto; }
.ps-shell.is-collapsed .ps-side__logo { pointer-events: none; }
.ps-side__toggle {
  position: absolute;
  top: 50%; right: 12px;
  transform: translateY(-50%);
  width: 32px; height: 32px;
  border: 0; background: transparent;
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255, 255, 255, 0.82);
  cursor: pointer;
  opacity: 1;
  transition: opacity var(--ps--duration-base), background var(--ps--duration-fast);
}
.ps-side__toggle:hover { background: rgba(255, 255, 255, 0.12); color: #fff; }
.ps-side__toggle i { width: 18px; height: 18px; }

/* eingeklappt: Logo aus, Signet an, Toggle verborgen (zentriert) */
.ps-shell.is-collapsed .ps-side__logo { opacity: 0; }
.ps-shell.is-collapsed .ps-side__signet { opacity: 1; }
.ps-shell.is-collapsed .ps-side__toggle {
  right: auto; left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
}
/* eingeklappt + Hover über den Kopf: Signet aus, Toggle an */
.ps-shell.is-collapsed .ps-side__brand:hover .ps-side__signet { opacity: 0; }
.ps-shell.is-collapsed .ps-side__brand:hover .ps-side__toggle { opacity: 1; }

.ps-side__nav {
  flex: 1; min-height: 0;
  padding: 14px 12px;
  display: flex; flex-direction: column; gap: 2px;
  overflow: hidden;
}
.ps-side__label {
  flex: 0 0 auto;
  font-weight: 700; font-size: 10px; letter-spacing: 0.10em;
  color: rgba(255, 255, 255, 0.42);
  padding: 4px 10px 6px;
  white-space: nowrap; overflow: hidden;
  max-height: 26px; opacity: 1;
  transition: opacity var(--ps--duration-base),
              max-height var(--ps--duration-slow) var(--ps--ease-standard);
}
.ps-side__hr {
  flex: 0 0 auto;
  margin: 14px 4px 10px;
  height: 1px; background: rgba(255, 255, 255, 0.12);
}
.ps-side__item {
  flex: 0 0 auto;
  display: flex; align-items: center;
  gap: 12px; justify-content: flex-start;
  padding: 9px 10px;
  border: 0; background: transparent;
  border-radius: 6px;
  color: rgba(255, 255, 255, 0.82);
  font-weight: 600; font-size: 14px; text-align: left;
  cursor: pointer; overflow: hidden;
  transition: padding var(--ps--duration-slow) var(--ps--ease-standard),
              background var(--ps--duration-fast);
}
.ps-side__item i { width: 18px; height: 18px; flex: 0 0 auto; }
.ps-side__item span {
  white-space: nowrap; overflow: hidden;
  opacity: 1; max-width: 200px;
  transition: opacity var(--ps--duration-base),
              max-width var(--ps--duration-slow) var(--ps--ease-standard);
}
.ps-side__item:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }
.ps-side__item.is-active { background: var(--ps--primary); color: #fff; }
.ps-side__item.is-disabled { opacity: 0.42; cursor: default; }
.ps-side__item.is-disabled:hover { background: transparent; }

/* „Beta"-Kennzeichen rechts neben einem Nav-Eintrag (z. B. Geppetto AI). */
.ps-side__badge {
  flex: 0 0 auto; margin-left: auto;
  font-size: 9px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  line-height: 1; padding: 3px 7px; border-radius: 999px;
  background: var(--ps--accent); color: var(--ps--brand-dark);
  opacity: 1; max-width: 60px; overflow: hidden;
  transition: opacity var(--ps--duration-base),
              max-width var(--ps--duration-slow) var(--ps--ease-standard);
}
/* eingeklappt: nur Icons — Badge mit ausblenden. */
.ps-shell.is-collapsed .ps-side__badge {
  opacity: 0; max-width: 0; padding: 0; margin: 0;
}

/* Dezenter Tastenkürzel-Hinweis unten, über dem Changelog-Footer. */
.ps-side__hint {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 7px;
  padding: 0 16px 10px;
  color: rgba(255, 255, 255, 0.34);
  font-size: 11px; font-weight: 600; white-space: nowrap; overflow: hidden;
}
.ps-side__kbd {
  flex: 0 0 auto; font-family: var(--ps--font-mono); font-size: 10px; font-weight: 700;
  line-height: 1; padding: 3px 6px; border-radius: 5px;
  background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.6);
}

/* Projekt-Umschalter */
.ps-side__switch {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 11px;
  padding: 10px 11px;
  border: 0;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.10);
  cursor: pointer; overflow: hidden;
  margin-bottom: 10px; width: 100%;
  text-align: left;
}
.ps-side__switch i { flex: 0 0 auto; color: #fff; }
.ps-side__switch .ps-side__switchName {
  flex: 1; min-width: 0;
  color: #fff; font-weight: 700; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 1; max-width: 200px;
  transition: opacity var(--ps--duration-base), max-width var(--ps--duration-slow);
}
.ps-side__switch .ps-side__switchCaret {
  flex: 0 0 auto; color: rgba(255, 255, 255, 0.6);
  opacity: 1; transition: opacity var(--ps--duration-base);
}
/* Ordner-Icon im Umschalter: NUR eingeklappt sichtbar (smooth eingeblendet). */
.ps-side__switchIcon {
  flex: 0 0 auto; width: 18px; height: 18px; color: #fff;
  opacity: 0; max-width: 0; overflow: hidden;
  transition: opacity var(--ps--duration-base), max-width var(--ps--duration-slow) var(--ps--ease-standard);
}
.ps-shell.is-collapsed .ps-side__switchIcon { opacity: 1; max-width: 24px; }

/* eingeklappt: Texte/Labels ausblenden + Items zentrieren */
.ps-shell.is-collapsed .ps-side__label { opacity: 0; max-height: 0; }
.ps-shell.is-collapsed .ps-side__item { gap: 0; padding: 9px 0; justify-content: center; }
.ps-shell.is-collapsed .ps-side__item span { opacity: 0; max-width: 0; }
.ps-shell.is-collapsed .ps-side__switch { justify-content: center; gap: 0; }
.ps-shell.is-collapsed .ps-side__switch .ps-side__switchName,
.ps-shell.is-collapsed .ps-side__switch .ps-side__switchCaret { opacity: 0; max-width: 0; }
.ps-shell.is-collapsed .ps-side__foot span { opacity: 0; max-width: 0; }

/* Custom-Tooltip (eingeklappte Sidebar): dunkelgrau, weißer Text, fixed → wird
   nicht vom overflow:hidden der Sidebar abgeschnitten. */
.ps-tip {
  position: fixed; z-index: 90;
  transform: translateY(-50%);
  background: var(--ps--surface-dark); color: #fff;
  font-size: 12px; font-weight: 600; line-height: 1; white-space: nowrap;
  padding: 7px 10px; border-radius: 7px;
  box-shadow: var(--ps--shadow-md); pointer-events: none;
  animation: ps-tip-in 0.12s var(--ps--ease-out);
}
@keyframes ps-tip-in {
  from { opacity: 0; transform: translateY(-50%) translateX(-4px); }
  to   { opacity: 1; transform: translateY(-50%); }
}

.ps-side__foot {
  flex: 0 0 auto;
  padding: 14px 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  display: flex; align-items: center; gap: 8px;
  justify-content: flex-start;
  color: rgba(255, 255, 255, 0.55);
  font-weight: 600; font-size: 12px;
  background: transparent; border-left: 0; border-right: 0; border-bottom: 0;
  cursor: pointer; width: 100%; text-align: left;
}
.ps-shell.is-collapsed .ps-side__foot { justify-content: center; }
.ps-side__foot span {
  white-space: nowrap; overflow: hidden; max-width: 200px;
  transition: opacity var(--ps--duration-base), max-width var(--ps--duration-slow);
}
.ps-side__foot:hover { color: rgba(255, 255, 255, 0.85); }

/* Projektwechsler-Dropdown — position:fixed, damit es aus dem overflow:hidden
   der Sidebar ausbricht; left/top/min-width werden inline aus dem Button-Rect
   gesetzt. */
.ps-switchMenu {
  position: fixed;
  z-index: 60;
  min-width: 220px;
  background: var(--ps--neutral-0);
  border: 1px solid var(--ps--border);
  border-radius: 10px;
  box-shadow: var(--ps--shadow-lg);
  padding: 6px;
  max-height: 60vh; overflow-y: auto;
}
.ps-switchMenu__item {
  display: block; width: 100%; text-align: left;
  padding: 9px 10px; border: 0; background: transparent;
  border-radius: 7px; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--ps--fg);
}
.ps-switchMenu__item:hover { background: var(--ps--bg-soft); }
/* Auswahl-Zustand: siehe shell.css, Abschnitt „Auswahl-Zustand“ (eine Quelle). */
.ps-switchMenu__empty { padding: 12px; font-size: 13px; color: var(--ps--fg-muted); }
.ps-switchMenu__search {
  display: block; width: 100%; box-sizing: border-box;
  margin: 2px 0 6px; padding: 8px 10px;
  border: 1px solid var(--ps--border); border-radius: 7px;
  background: var(--ps--neutral-0); font-size: 13px; color: var(--ps--fg);
}
.ps-switchMenu__search:focus { outline: none; border-color: var(--ps--primary); }
.ps-switchMenu__folder {
  padding: 8px 10px 4px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--ps--fg-muted);
}
/* Ordner-Tag an einer Projektzeile (Übersicht + System-Status): kleines Pill
   mit Ordner-Icon + Name. Abstand zum Namen kommt vom Flex-Gap der Zeile. */
.ps-folderTag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px; border-radius: 999px;
  background: var(--ps--bg-soft); border: 1px solid var(--ps--border);
  font-size: 11px; font-weight: 600; color: var(--ps--fg-muted);
  white-space: nowrap; flex: 0 0 auto;
}
.ps-folderTag i, .ps-folderTag svg { width: 12px; height: 12px; }
/* Sortierbarer Spaltenkopf in der Projekt-Übersicht: sieht aus wie das
   Header-Label (font/Farbe geerbt), aber klickbar; aktiv = Akzentfarbe. */
.ps-dash__sortBtn {
  border: 0; background: transparent; padding: 0; margin: 0;
  font: inherit; color: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: 2px;
}
.ps-dash__sortBtn:hover { color: var(--ps--primary); }
.ps-dash__sortBtn.is-active { color: var(--ps--primary); }

/* ---- Content-Bereich (rechts der Sidebar) ---- */
.ps-content {
  margin-left: var(--ps-side-w);
  height: 100vh;
  display: flex; flex-direction: column;
  transition: margin-left var(--ps--duration-slow) var(--ps--ease-standard);
}
.ps-content--builder { display: block; }
/* Builder-Topbar-Zeile an die 60px-Shell-Chrome angleichen. */
.ps-content--builder .bd-shell { --cp-chrome-h: var(--ps-chrome-h); }

/* Werkstatt (Werkstatt-Redesign Task 1) — full-bleed wie --builder oben, aber
   .ps-content's normale flex-column-Basis reicht hier aus (kein eigenes
   Topbar-Grid): .cc-workshop selbst ist flex:1 (siehe oben) und füllt damit
   die volle 100vh-Höhe von .ps-content. overflow:hidden verhindert, dass der
   Editor/die Meta-Spalte über den Content-Bereich hinaus scrollt. */
.ps-content--workshop { overflow: hidden; }

/* ---- Topbar ---- */
.ps-top {
  flex: 0 0 auto;
  height: var(--ps-chrome-h);
  border-bottom: 1px solid var(--ps--border);
  background: var(--ps--neutral-0);
  display: flex; align-items: center;
  padding: 0 24px; gap: 16px;
}
.ps-top__pos { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.ps-top__posMain { font-weight: 900; font-size: 16px; color: var(--ps--fg); letter-spacing: -0.01em; }
.ps-top__posSub { font-size: 13px; color: var(--ps--neutral-400); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-top__spacer { flex: 1; }
.ps-top__export {
  display: flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 18px;
  border: 0; border-radius: 9px;
  background: var(--ps--primary); color: #fff;
  font-weight: 700; font-size: 14px; cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 129, 93, 0.28);
}
.ps-top__export:hover { background: var(--ps--primary-hover); }
.ps-top__export i { width: 16px; height: 16px; }
.ps-top__divider { width: 1px; height: 30px; background: var(--ps--border); }

/* Speicher-Status (Topbar) — gleiche Geometrie wie .ps-top__iconbtn/__export
   (40 px, Radius 9 px), siehe Abschnitt „Studio-Chrome-Buttons": der Zustand
   ist Chrome, kein Sonderfall. Farben ausschließlich über Rollen-Tokens, damit
   darkmode.css sie erreicht. */
.ps-top__save {
  display: inline-flex; align-items: center; gap: 6px;
  height: 40px; padding: 0 14px; border-radius: 9px;
  font-family: var(--ps--font-sans); font-size: 13px; font-weight: 700;
  border: 1px solid var(--ps--border); background: var(--ps--neutral-0);
  color: var(--ps--fg-muted); white-space: nowrap;
}
/* Signalton für den RAHMEN, --ps--*-fg für den TEXT — dieselbe Trennung wie bei
   den Status-Pillen der Werkstatt. Gemessen (13px/700 auf --ps--neutral-0):
   der reine Signalton --ps--warning erreicht als Textfarbe nur 3,19:1 und liegt
   damit unter der 4,5:1-Schwelle, --ps--warning-fg kommt auf 5,86:1. Im
   Dunkelmodus tauschen beide Rollen mit. */
.ps-top__save--busy { color: var(--ps--warning-fg); }
.ps-top__save--warn { color: var(--ps--warning-fg); border-color: var(--ps--warning); }
.ps-top__save--danger { color: var(--ps--danger-fg); border-color: var(--ps--danger); }
.ps-top__save--muted { color: var(--ps--fg-muted); }
.ps-top__saveDetail { font-weight: 400; color: var(--ps--fg-muted); }
.ps-top__saveAction { margin-left: 4px; text-decoration: underline; }
button.ps-top__save:hover:not(:disabled) { border-color: var(--ps--border-strong); }
button.ps-top__save:disabled { opacity: 0.6; cursor: default; }

/* Sync-Punkt im Fuß der Seitenleiste. Liest denselben Zustand wie der Chip;
   die Geometrie stand vorher als Inline-Stil in sidebar.jsx. */
.ps-syncDot {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  margin-right: 8px; display: inline-block; background: var(--ps--fg-subtle);
}
.ps-syncDot--ok { background: var(--ps--success); }
.ps-syncDot--busy, .ps-syncDot--warn { background: var(--ps--warning); }
.ps-syncDot--danger { background: var(--ps--danger); }
.ps-syncDot--muted { background: var(--ps--fg-subtle); }
.ps-top__iconbtn {
  width: 40px; height: 40px;
  border: 1px solid var(--ps--border); border-radius: 9px;
  background: var(--ps--neutral-0); color: var(--ps--fg-muted);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.ps-top__iconbtn:hover { border-color: var(--ps--border-strong); color: var(--ps--fg); }
.ps-top__iconbtn i { width: 16px; height: 16px; }

/* ---- Account-Menü ---- */
.ps-account { position: relative; }
.ps-account__btn {
  display: flex; align-items: center; gap: 10px;
  border: 0; background: transparent; cursor: pointer; padding: 0;
}
.ps-account__avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--ps--bg-inverse); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; flex: 0 0 auto;
  background-size: cover; background-position: center;
}
.ps-account__meta { display: flex; flex-direction: column; line-height: 1.2; align-items: flex-start; }
.ps-account__name { font-weight: 700; font-size: 13px; color: var(--ps--fg); }
.ps-account__role { font-size: 11px; color: var(--ps--neutral-400); }
.ps-account__caret { width: 15px; height: 15px; color: var(--ps--neutral-400); }
.ps-account__menu {
  position: absolute; right: 0; top: calc(100% + 8px);
  min-width: 200px; z-index: 50;
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border);
  border-radius: 10px; box-shadow: var(--ps--shadow-lg);
  padding: 6px;
}
.ps-account__item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 9px 10px;
  border: 0; background: transparent; border-radius: 7px;
  font-size: 13px; font-weight: 600; color: var(--ps--fg);
  text-align: left; cursor: pointer;
}
.ps-account__item:hover { background: var(--ps--bg-soft); }
.ps-account__item i { width: 15px; height: 15px; color: var(--ps--fg-muted); }
.ps-account__sep { height: 1px; background: var(--ps--border); margin: 6px 4px; }

/* ---- Benachrichtigungs-Glocke (Topbar) ---- */
.ps-bell { position: relative; }
.ps-bell__btn { position: relative; }
/* #dc2626 BLEIBT literal — und das ist der Fall, an dem PS-88 zeigt, warum ein
   Rundum-Ersetzen falsch wäre. Die Fläche trägt WEISSEN Text: gerechnet ergibt
   Weiß auf #dc2626 4,83:1 (AA bestanden, in beiden Modi gleich), Weiß auf dem
   dunklen --ps--danger (#f0736e) nur 2,84:1. Das Token würde den Kontrast hier
   also VERSCHLECHTERN. Ein Abzeichen bringt seinen Hintergrund selbst mit; es
   braucht den Modus nicht. */
.ps-bell__badge {
  position: absolute; top: -5px; right: -5px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: #dc2626; color: #fff;
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center;
}
.ps-bell__menu {
  position: absolute; right: 0; top: calc(100% + 8px);
  width: 360px; max-height: 480px; overflow-y: auto; z-index: 50;
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border);
  border-radius: 10px; box-shadow: var(--ps--shadow-lg);
  padding: 6px;
}
.ps-bell__head, .ps-bell__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; font-size: 12px; font-weight: 700; color: var(--ps--fg-muted);
}
.ps-bell__foot { justify-content: center; border-top: 1px solid var(--ps--border); margin-top: 4px; }
.ps-bell__empty { padding: 18px 10px; font-size: 13px; color: var(--ps--fg-muted); text-align: center; }
.ps-bell__item {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 9px 10px;
  border: 0; background: transparent; border-radius: 7px;
  text-align: left; cursor: pointer;
}
.ps-bell__item:hover { background: var(--ps--bg-soft); }
.ps-bell__item.is-read { opacity: 0.6; }
.ps-bell__item i { width: 15px; height: 15px; flex: 0 0 auto; margin-top: 2px; }
.ps-bell__itemBody { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.ps-bell__title { font-size: 13px; font-weight: 700; color: var(--ps--fg); }
.ps-bell__text {
  font-size: 12px; color: var(--ps--fg-muted); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ps-bell__time { font-size: 11px; color: var(--ps--fg-muted); }
.ps-bell__dot { width: 8px; height: 8px; border-radius: 4px; background: var(--ps--danger); flex: 0 0 auto; margin-top: 6px; }

/* ---- Benachrichtigungsseite ---- */
.ps-notifs__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.ps-notifs__day { margin: 14px 0 4px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ps--fg-muted); }

/* ---- Body (unter der Topbar): optionale SubNav + Hauptfläche ---- */
.ps-below { flex: 1; min-height: 0; display: flex; }

/* SubNav (wiederverwendete .cp-subnav) im neuen Shell positionieren */
.ps-below .cp-subnav {
  position: static;
  height: auto;
  align-self: stretch;
  width: 240px;
  flex: 0 0 auto;
}
.ps-below .cp-subnav__head {
  height: auto;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--ps--border);
}

.ps-main { flex: 1; min-width: 0; min-height: 0; overflow: auto; }
.ps-main__body { padding: 32px 36px 44px; }

/* ===========================================================
   Dashboard (globale Projektliste)
   =========================================================== */
.ps-dash__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; }
.ps-dash__eyebrow { font-weight: 700; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ps--primary); margin-bottom: 10px; }
.ps-dash__title { font-family: var(--ps--font-display); font-weight: 900; font-size: 42px; line-height: 0.98; color: var(--ps--fg); margin: 0; text-transform: uppercase; letter-spacing: -0.02em; }
.ps-dash__headActions { display: flex; align-items: center; gap: 10px; }
.ps-dash__search { position: relative; display: flex; align-items: center; }
/* Lucide ersetzt das <i data-lucide> zur Laufzeit durch ein <svg> — deshalb muss
   die Positionierung das svg treffen, sonst rutscht die Lupe als Flex-Element
   aus dem Feld. */
.ps-dash__search > svg, .ps-dash__search > i { width: 17px; height: 17px; color: var(--ps--neutral-400); position: absolute; left: 16px; pointer-events: none; }
.ps-dash__search input { width: 300px; height: 44px; padding: 0 18px 0 44px; border: 1px solid var(--ps--border); border-radius: 12px; background: var(--ps--neutral-0); font: 400 14px var(--ps--font-sans); color: var(--ps--fg); outline: none; transition: border-color .15s, box-shadow .15s; }
.ps-dash__search input::placeholder { color: var(--ps--fg-muted); }
.ps-dash__search input:hover { border-color: var(--ps--border-strong); }
.ps-dash__search input:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-btn {
  display: flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 18px;
  border: 1px solid var(--ps--border); border-radius: 10px;
  background: var(--ps--neutral-0); color: var(--ps--neutral-700);
  font-weight: 700; font-size: 14px; cursor: pointer;
}
.ps-btn:hover { border-color: var(--ps--border-strong); }
/* Deaktivierte Buttons müssen auch so AUSSEHEN — sonst wirkt z. B. ein
   gesperrter grüner Primär-Button voll klickbar (kanonisch für alle ps-btn). */
.ps-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.ps-btn:disabled:hover { border-color: var(--ps--border); }
.ps-btn i { width: 16px; height: 16px; }
.ps-btn--primary { background: var(--ps--primary); border-color: var(--ps--primary); color: #fff; }
.ps-btn--primary:hover { background: var(--ps--primary-hover); border-color: var(--ps--primary-hover); }
.ps-btn--primary:disabled:hover { background: var(--ps--primary); border-color: var(--ps--primary); }

.ps-dash__kpis { display: flex; gap: 16px; margin-top: 26px; }
.ps-kpi { flex: 1; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; padding: 18px 20px; }
.ps-kpi__icon  { color: var(--ps-kpi-accent, var(--ps--fg)); }
.ps-kpi__value { color: var(--ps-kpi-accent, var(--ps--fg)); }
.ps-kpi__top { display: flex; align-items: center; justify-content: space-between; }
.ps-kpi__label { font-weight: 700; font-size: 12px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ps--neutral-400); }
.ps-kpi__icon { width: 16px; height: 16px; }
.ps-kpi__value { font-weight: 900; font-size: 34px; margin-top: 8px; letter-spacing: -0.02em; }

.ps-dash__folders { display: flex; align-items: center; gap: 10px; margin-top: 24px; overflow-x: auto; padding-bottom: 2px; }
.ps-chip {
  display: flex; align-items: center; gap: 9px; flex: 0 0 auto;
  height: 42px; padding: 0 16px;
  border: 1px solid var(--ps--border); border-radius: 10px;
  background: var(--ps--neutral-0); color: var(--ps--neutral-600);
  font-weight: 700; font-size: 13px; cursor: pointer;
}
.ps-chip i { width: 16px; height: 16px; }
.ps-chip .ps-chip__count { opacity: 0.55; }
.ps-chip.is-active { background: var(--ps--bg-inverse); color: #fff; border-color: var(--ps--bg-inverse); }
.ps-chip--add { border-style: dashed; border-color: var(--ps--border-strong); color: var(--ps--neutral-500); }

.ps-dash__listHead { display: flex; align-items: center; justify-content: space-between; margin-top: 30px; margin-bottom: 14px; }
.ps-dash__listHead h2 { font-weight: 900; font-size: 18px; color: var(--ps--fg); margin: 0; letter-spacing: -0.01em; }
.ps-dash__listHead h2 span { font-weight: 400; color: var(--ps--neutral-400); }

.ps-tableWrap { overflow-x: auto; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; }
.ps-table { min-width: 1246px; }
.ps-table__head {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 22px; border-bottom: 1px solid var(--ps--border);
  background: var(--ps--neutral-50);
  font-weight: 700; font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--ps--neutral-400);
}
/* Kopf-Zellen erben Kopf-Typo (sonst gewönnen die Daten-Spalten-Fonts). */
.ps-table__head > div { font: inherit; color: inherit; }
.ps-row { display: flex; align-items: center; gap: 16px; padding: 14px 22px; border-bottom: 1px solid var(--ps--border); position: relative; }
.ps-row:last-child { border-bottom: 0; }
.ps-row:hover { background: var(--ps--neutral-50); }
.ps-row__name { font-weight: 700; font-size: 15px; color: var(--ps--fg); }
.ps-row__domain { font-size: 12px; color: var(--ps--neutral-400); margin-top: 3px; display: flex; align-items: center; gap: 5px; }
.ps-row__domain i { width: 11px; height: 11px; }
.ps-col-prev { width: 128px; flex: 0 0 auto; border-radius: 7px; overflow: hidden; border: 1px solid var(--ps--border); }
.ps-col-proj { flex: 1; min-width: 0; cursor: pointer; }
.ps-col-status { width: 104px; flex: 0 0 auto; }
.ps-col-plat { width: 200px; flex: 0 0 auto; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ps-col-pages { width: 62px; flex: 0 0 auto; text-align: right; font-weight: 700; font-size: 15px; color: var(--ps--neutral-700); }
.ps-col-comp { width: 96px; flex: 0 0 auto; text-align: right; font-weight: 700; font-size: 15px; color: var(--ps--neutral-700); }
.ps-col-upd { width: 104px; flex: 0 0 auto; font-size: 12px; color: var(--ps--neutral-500); }
.ps-col-pm { width: 84px; flex: 0 0 auto; }
.ps-col-act { width: 112px; flex: 0 0 auto; display: flex; gap: 6px; justify-content: flex-end; }

.ps-pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font-weight: 700; font-size: 11px; }
.ps-pill__dot { width: 6px; height: 6px; border-radius: 50%; }
.ps-tag { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 6px; font-weight: 700; font-size: 11px; }
.ps-tag i { width: 11px; height: 11px; }

/* Status-Pills & Plattform-Tags — tokenbasiert (Dashboard/Overview).
   Light == heutige Inline-Werte; --ps--success/warning werden im Dark
   aufgehellt (darkmode.css), color-mix zieht automatisch mit. */
.ps-pill--live     { background: color-mix(in srgb, var(--ps--success) 13%, transparent); color: var(--ps--success); }
.ps-pill--live .ps-pill__dot     { background: var(--ps--success); }
.ps-pill--draft    { background: color-mix(in srgb, var(--ps--warning) 13%, transparent); color: var(--ps--warning); }
.ps-pill--draft .ps-pill__dot    { background: var(--ps--warning); }
.ps-pill--archived { background: color-mix(in srgb, var(--ps--neutral-400) 13%, transparent); color: var(--ps--neutral-400); }
.ps-pill--archived .ps-pill__dot { background: var(--ps--neutral-400); }
.ps-tag--neos      { background: color-mix(in srgb, var(--ps--brand) 12%, transparent); color: var(--ps--brand); }
.ps-tag--static    { background: var(--ps--neutral-100); color: var(--ps--neutral-500); }
.ps-tag--exported  { background: color-mix(in srgb, var(--ps--success) 12%, transparent); color: var(--ps--success); }
.ps-tag--pending   { background: color-mix(in srgb, var(--ps--warning) 12%, transparent); color: var(--ps--warning); }
/* Hinweis auf nachzutragende Daten (z. B. unvollständiger Name aus der
   Bestandsübernahme). Über --ps--warning, das darkmode.css remappt. */
.ps-tag--warn      { background: color-mix(in srgb, var(--ps--warning) 12%, transparent); color: var(--ps--warning); }
/* Gewerk eines Benutzers (PS-67) — rein beschreibend, deshalb neutral statt
   in einer Statusfarbe. */
.ps-tag--trade     { background: var(--ps--neutral-100); color: var(--ps--neutral-500); }
/* Mehrfachauswahl im Modal (Gewerke). */
.ps-checkrow { display: flex; flex-wrap: wrap; gap: 12px; padding: 4px 0; }
.ps-checkrow__item { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; cursor: pointer; }
/* Gewerk-Filter über der Benutzerliste: gedrückter Zustand. */
.ps-tag--trade.is-active { background: var(--ps--primary-soft); color: var(--ps--primary); }

/* Generische Status-Badges (Metas mit dynamischem hex, mehrere Views).
   Light == altes psHexA(hex,.13)+color:hex; Dark hellt den Farbton generisch
   auf (color-mix mit dem hellen fg), damit jeder Hue auf dunklem Grund lesbar
   bleibt. Farbe kommt aus der Inline-Custom-Property --sp-hex. */
.ps-badge-dyn { background: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) var(--sp-a, 13%), transparent); color: var(--sp-hex, var(--ps--fg-muted)); }
.ps-badge-dyn .ps-pill__dot { background: var(--sp-hex, var(--ps--fg-muted)); }
.ps-fg-dyn { color: var(--sp-hex, inherit); }
html.ps-dark .ps-badge-dyn { background: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) 22%, transparent); color: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) 62%, var(--dm-fg)); }
html.ps-dark .ps-badge-dyn .ps-pill__dot { background: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) 62%, var(--dm-fg)); }
html.ps-dark .ps-fg-dyn { color: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) 62%, var(--dm-fg)); }

/* Zweiton-/Flat-Status-Badges: unabhängige bg- und fg-Farbe (--sp-bg/--sp-fg).
   Light == alte Inline-Werte; Dark ersetzt den hellen Grund durch einen aus
   der fg abgeleiteten dunklen Tint und hellt die fg auf. */
.ps-badge-2t { background: var(--sp-bg); color: var(--sp-fg); }
html.ps-dark .ps-badge-2t { background: color-mix(in srgb, var(--sp-fg, var(--ps--fg-muted)) 20%, transparent); color: color-mix(in srgb, var(--sp-fg, var(--ps--fg-muted)) 68%, var(--dm-fg)); }

.ps-iconbtn { appearance: none; padding: 0; font: inherit; width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--ps--border); background: var(--ps--neutral-0); display: flex; align-items: center; justify-content: center; color: var(--ps--fg); cursor: pointer; transition: border-color .15s, color .15s, background .15s; }
.ps-iconbtn:hover { border-color: var(--ps--border-strong); }
.ps-iconbtn:focus-visible { outline: none; border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-iconbtn i { width: 14px; height: 14px; }
.ps-iconbtn--danger:hover { border-color: var(--ps--danger); color: var(--ps--danger); background: color-mix(in srgb, var(--ps--danger) 6%, transparent); }

.ps-pm { display: flex; align-items: center; gap: 7px; }
.ps-pm__ph { width: 26px; height: 26px; border-radius: 50%; border: 1px dashed var(--ps--border-strong); display: flex; align-items: center; justify-content: center; color: var(--ps--neutral-300); flex: 0 0 auto; }
.ps-pm__ph i { width: 13px; height: 13px; }
/* flex: 0 0 auto ist NICHT kosmetisch: ohne es staucht ein langer, umbrechender
   Name (die Beschriftung daneben) den Kreis horizontal zur Ellipse — das
   Hintergrundbild sieht dann verzerrt aus, obwohl es das nicht ist. Dieselbe
   Regel trägt .ps-account__avatar in der Kopfzeile von Anfang an. */
.ps-pm__avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--ps--bg-inverse); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; background-size: cover; background-position: center; flex: 0 0 auto; }
.ps-pm__label { font-size: 11px; color: var(--ps--neutral-400); }

.ps-popover {
  position: absolute; right: 86px; top: 50%; transform: translateY(-50%);
  width: 236px; background: var(--ps--bg-inverse); color: #fff;
  border-radius: 10px; padding: 13px 14px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.28); z-index: 6;
}
/* Klick-Variante: position:fixed (bricht aus der Tabellen-overflow aus),
   rechts unter dem Info-Icon verankert (top/right inline), animiert. */
.ps-popover--float {
  position: fixed; right: auto; top: auto; transform: none;
  width: 248px; z-index: 80;
  transform-origin: top right;
  animation: ps-pop-in 0.16s var(--ps--ease-out);
}
@keyframes ps-pop-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
.ps-iconbtn.is-active { border-color: var(--ps--primary); color: var(--ps--primary); background: var(--ps--primary-soft); }
/* #8fb9ab BLEIBT literal (PS-88): .ps-popover ist bewusst DUNKEL (--ps--bg-inverse,
   eine der drei dokumentierten Dunkelmodus-Ausnahmen in darkmode.css) und trägt
   weißen Text. Der gedämpfte Ton liegt also in beiden Modi auf derselben dunklen
   Fläche und ist in beiden richtig. Ein --ps--fg-muted würde ihn im hellen Modus
   dunkel machen — auf dunkelgrün. */
.ps-popover__title { font-weight: 700; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: #8fb9ab; margin-bottom: 9px; }
.ps-popover__row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 12px; }
.ps-popover__row span:first-child { color: rgba(255, 255, 255, 0.6); }
.ps-popover__row span:last-child { font-weight: 700; color: #fff; text-align: right; }

.ps-dash__empty { padding: 60px 20px; text-align: center; color: var(--ps--fg-muted); }

/* Bereichs-Hinweis (PS-93): ein Bereich, der erklaert, warum er leer ist —
   Symbol, Ueberschrift, Erklaerung, EIN Knopf zur Stelle, wo man es aendert.
   Nur Tokens, keine literalen Farben: sonst bliebe der Block im Dunkelmodus
   stehen, waehrend alles um ihn herum umschaltet. */
.ps-area-notice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: 520px;
  margin: 0 auto;
}
.ps-area-notice__icon { color: var(--ps--fg-subtle); }
.ps-area-notice__title { font-size: 17px; font-weight: 700; color: var(--ps--fg); }
.ps-area-notice__text { margin: 0; line-height: 1.55; color: var(--ps--fg-muted); }

/* ===========================================================
   System-Status (technisches Fleet-Dashboard)
   =========================================================== */
/* Erreichbarkeits-Punkt; die Live-Variante pulsiert (Farbe kommt inline). */
.ps-sys-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.ps-sys-dot--live { animation: psPulse 2.4s infinite; }
@keyframes psPulse {
  0%   { box-shadow: 0 0 0 0 rgba(31, 157, 85, 0.45); }
  70%  { box-shadow: 0 0 0 6px rgba(31, 157, 85, 0); }
  100% { box-shadow: 0 0 0 0 rgba(31, 157, 85, 0); }
}
/* Aktions-Icon-Button in der Ops-Tabelle. */
.ps-sys-iconbtn { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 8px; color: var(--ps--fg-muted); cursor: pointer; transition: background .12s, color .12s, border-color .12s; }
.ps-sys-iconbtn:hover { background: var(--ps--primary-soft); color: var(--ps--primary); border-color: var(--ps--border-strong); }
.ps-sys-iconbtn:disabled { opacity: .45; cursor: not-allowed; background: var(--ps--neutral-0); color: var(--ps--fg-muted); border-color: var(--ps--border); }
/* Passwortschutz-Schloss neben der Domain (Systemübersicht + Dashboard).
   Aktiv = geschlossenes Schloss in Akzentfarbe, sonst ausgegraut/offen. */
.ps-sys-lock { display: inline-flex; align-items: center; justify-content: center; padding: 2px; background: none; border: 0; border-radius: 6px; color: var(--ps--fg-subtle); opacity: .5; cursor: pointer; transition: opacity .12s, color .12s, background .12s; }
.ps-sys-lock i, .ps-sys-lock svg { width: 13px; height: 13px; }
.ps-sys-lock[data-on='1'] { color: var(--ps--primary); opacity: 1; }
.ps-sys-lock:hover { background: var(--ps--primary-soft); opacity: 1; }
.ps-sys-lock:disabled { cursor: default; }
.ps-sys-lock:disabled:hover { background: none; }

/* Laufende Server-Prüfung: drehendes Icon im Zeilen-Button. */
.ps-sys-spin { animation: psSpin 1s linear infinite; }
@keyframes psSpin { to { transform: rotate(360deg); } }

/* ===========================================================
   Projekt-Übersicht
   =========================================================== */
.ps-ov__eyebrow { font-weight: 700; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ps--primary); margin-bottom: 8px; }
.ps-ov__title { font-family: var(--ps--font-display); font-weight: 900; font-size: 34px; color: var(--ps--fg); margin: 0 0 10px; text-transform: uppercase; letter-spacing: -0.02em; }
.ps-ov__sub { display: flex; align-items: center; gap: 14px; color: var(--ps--neutral-500); font-size: 14px; margin-bottom: 22px; flex-wrap: wrap; }
.ps-ov__sub a { color: inherit; text-decoration: none; display: flex; align-items: center; gap: 6px; }
.ps-ov__sub a:hover { color: var(--ps--primary); }
.ps-ov__sub i { width: 14px; height: 14px; }
.ps-ov__metrics { display: flex; gap: 36px; padding: 16px 20px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 12px; margin-bottom: 26px; flex-wrap: wrap; }
.ps-ov__metric { display: flex; flex-direction: column; }
.ps-ov__metricVal { font-weight: 900; font-size: 22px; color: var(--ps--fg); }
.ps-ov__metricLabel { font-size: 11px; color: var(--ps--neutral-400); margin-top: 2px; }
.ps-ov__h2 { font-weight: 900; font-size: 16px; color: var(--ps--fg); margin: 0 0 14px; letter-spacing: -0.01em; }
.ps-ov__grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
@media (max-width: 1000px) { .ps-ov__grid { grid-template-columns: 1fr 1fr; } }
.ps-tile {
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 12px;
  padding: 16px; display: flex; flex-direction: column;
  cursor: pointer; box-shadow: var(--ps--shadow-xs); text-align: left;
}
.ps-tile:hover { border-color: var(--ps--border-strong); box-shadow: var(--ps--shadow-sm); }
.ps-tile__icon { width: 38px; height: 38px; border-radius: 9px; background: var(--ps--primary-soft); color: var(--ps--primary); display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
.ps-tile__icon i { width: 19px; height: 19px; }
.ps-tile__name { font-weight: 900; font-size: 16px; color: var(--ps--fg); letter-spacing: -0.01em; }
.ps-tile__desc { font-size: 12.5px; color: var(--ps--neutral-500); margin-top: 3px; line-height: 1.45; }
.ps-tile__meta { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; }
.ps-tile__metaText { font-size: 11px; font-weight: 700; color: var(--ps--neutral-400); }
.ps-tile__arrow { width: 15px; height: 15px; color: var(--ps--primary); }

/* ===========================================================
   Dynamische Inhalte (Premium-Collections)
   =========================================================== */
/* HIER STANDEN --ps--status-live / --ps--status-draft (PS-88).
   Sie hielten „live" (grün) und „Entwurf" (amber) als eigenes Paar, weil es in
   der globalen Rampe damals nichts Passendes gab. Seit PS-64 gibt es das:
   --ps--success / --ps--warning als Signalton und --ps--*-fg für Text. Die
   beiden Werte waren mit success/warning WERTGLEICH — zwei Namen für dieselbe
   Farbe, aber nur einer davon wurde in darkmode.css getauscht. Folge: die
   Legende der Collection-Karten („live"/„Entwurf") behielt im dunklen Modus die
   helle Textfarbe. Deshalb ersetzt, nicht umdefiniert: ein Vorrat, ein Ort. */
.ps-dc__intro { font-size: 14px; line-height: 1.55; color: var(--ps--neutral-500); max-width: 720px; margin: 0 0 22px; }
.ps-dc__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 12px; margin-bottom: 22px;
}
.ps-dc__count { font-size: 13px; color: var(--ps--neutral-500); }
.ps-dc__count strong { font-size: 16px; font-weight: 900; color: var(--ps--fg); }

.ps-dc__grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; align-items: stretch; }
@media (max-width: 1000px) { .ps-dc__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 680px)  { .ps-dc__grid { grid-template-columns: 1fr; } }

.ps-dc__card {
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 12px;
  padding: 18px; display: flex; flex-direction: column;
  box-shadow: var(--ps--shadow-xs);
  transition: border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.ps-dc__card.is-on { border-color: color-mix(in srgb, var(--ps--success, #1f9d55) 45%, var(--ps--border)); box-shadow: var(--ps--shadow-sm); }
.ps-dc__cardTop { display: flex; align-items: center; justify-content: space-between; margin-bottom: 13px; }
.ps-dc__icon { width: 42px; height: 42px; border-radius: 10px; background: var(--ps--primary-soft); color: var(--ps--primary); display: flex; align-items: center; justify-content: center; transition: background var(--ps--duration-fast), color var(--ps--duration-fast); }
.ps-dc__icon i { width: 21px; height: 21px; }
.ps-dc__card.is-on .ps-dc__icon { background: color-mix(in srgb, var(--ps--success) 14%, var(--ps--neutral-0)); color: var(--ps--success, #1f9d55); }
.ps-dc__badge { display: inline-flex; align-items: center; gap: 4px; font-size: 10px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ps--warning-fg); background: color-mix(in srgb, var(--ps--warning) 12%, var(--ps--neutral-0)); padding: 3px 8px; border-radius: 999px; }
.ps-dc__badge i { width: 11px; height: 11px; }
.ps-dc__name { font-weight: 900; font-size: 17px; color: var(--ps--fg); letter-spacing: -0.01em; }
.ps-dc__tagline { font-size: 12px; font-weight: 700; color: var(--ps--primary); margin-top: 3px; }
.ps-dc__desc { font-size: 12.5px; line-height: 1.5; color: var(--ps--neutral-500); margin: 10px 0 0; }
.ps-dc__fields { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.ps-dc__field { font-size: 11px; font-weight: 600; color: var(--ps--neutral-500); background: var(--ps--bg-soft); border: 1px solid var(--ps--border); border-radius: 6px; padding: 3px 8px; }
.ps-dc__cardFoot { display: flex; align-items: center; margin-top: auto; padding-top: 16px; }

/* iOS-Switch (größer als der cp-vswitch der Story-Köpfe) */
.ps-dc__switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; width: 100%; }
.ps-dc__switch input { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.ps-dc__switchTrack { position: relative; width: 44px; height: 24px; border-radius: 999px; background: var(--ps--neutral-300); transition: background var(--ps--duration-base) var(--ps--ease-standard); flex-shrink: 0; }
.ps-dc__switchThumb { position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 999px; background: #fff; box-shadow: var(--ps--shadow-sm); transition: transform var(--ps--duration-base) var(--ps--ease-standard); }
.ps-dc__switch input:checked ~ .ps-dc__switchTrack { background: var(--ps--success, #1f9d55); }
.ps-dc__switch input:checked ~ .ps-dc__switchTrack .ps-dc__switchThumb { transform: translateX(20px); }
.ps-dc__switch:focus-within .ps-dc__switchTrack { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ps--success, #1f9d55) 25%, transparent); }
.ps-dc__switchText { font-size: 12.5px; font-weight: 700; color: var(--ps--neutral-500); }
.ps-dc__switch.is-on .ps-dc__switchText { color: var(--ps--success, #1f9d55); }

.ps-dc__note { display: flex; align-items: flex-start; gap: 8px; margin-top: 26px; padding: 12px 14px; background: var(--ps--bg-soft); border: 1px solid var(--ps--border); border-radius: 10px; font-size: 12.5px; line-height: 1.5; color: var(--ps--neutral-500); max-width: 760px; }
.ps-dc__note i { width: 15px; height: 15px; color: var(--ps--primary); flex-shrink: 0; margin-top: 2px; }
.ps-dc__note code { font-family: var(--ps--font-mono); font-size: 11.5px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 5px; padding: 1px 5px; }

/* ---------- Collections-Übersicht (Task 9 → Redesign „1a") ---------- */
.ps-dc__section { margin-bottom: 34px; }
.ps-dc__section h2 { font-size: 15px; font-weight: 900; letter-spacing: -0.01em; color: var(--ps--fg); margin: 0 0 12px; }
.ps-dc__sectionHead { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.ps-dc__sectionHead h2 { margin: 0; }
/* dezente „N von M freigeschaltet"-Notiz rechts neben einer Section-Überschrift */
.ps-dc__sectionNote { font-size: 12px; color: var(--ps--neutral-500); }
.ps-dc__sectionNote strong { color: var(--ps--fg); font-weight: 900; }

.ps-dc__collEmpty { display: flex; align-items: center; gap: 10px; padding: 16px; border: 1px dashed var(--ps--border-strong); border-radius: 12px; background: var(--ps--bg-soft); color: var(--ps--neutral-500); font-size: 13px; line-height: 1.45; max-width: 880px; }

/* Kopfzeile der Übersicht: Eyebrow, großer Titel + Primär-Button, Statuszeile */
.ps-dc__ovHead { margin-bottom: 24px; }
.ps-dc__eyebrow { font-weight: 700; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ps--neutral-400); }
.ps-dc__headRow { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 6px; flex-wrap: wrap; }
.ps-dc__title { margin: 0; font-family: var(--ps--font-sans); font-size: 26px; font-weight: 900; letter-spacing: -0.01em; color: var(--ps--fg); }

.ps-dc__stats { display: flex; align-items: center; gap: 24px; margin-top: 16px; font-size: 13px; color: var(--ps--neutral-500); flex-wrap: wrap; }
.ps-dc__stats strong { color: var(--ps--fg); font-weight: 900; }
.ps-dc__stats .is-draft strong { color: var(--ps--warning-fg); }
.ps-dc__neosTag { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; border-radius: var(--ps--radius-pill); padding: 4px 11px; }
.ps-dc__neosTag--on { background: color-mix(in srgb, var(--ps--primary) 12%, var(--ps--neutral-0)); color: var(--ps--primary); }
.ps-dc__neosTag--off { background: var(--ps--bg-soft); color: var(--ps--neutral-500); }
.ps-dc__neosTag .ps-pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Collection-Karten: Icon-Kachel + Pfeil, Name, Meta, Live/Entwurf-Balken + Legende */
.ps-dc__collGrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.ps-dc__collCard {
  display: flex; flex-direction: column; align-items: stretch; text-align: left;
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; padding: 20px;
  cursor: pointer; box-shadow: var(--ps--shadow-xs);
  transition: border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.ps-dc__collCard:hover { border-color: var(--ps--border-strong); box-shadow: var(--ps--shadow-sm); }
.ps-dc__collCardTop { display: flex; align-items: center; justify-content: space-between; }
.ps-dc__collCardIcon { width: 42px; height: 42px; border-radius: 11px; background: var(--ps--primary-soft); color: var(--ps--primary); display: flex; align-items: center; justify-content: center; }
.ps-dc__collCardArrow { display: inline-flex; color: var(--ps--border-strong); transition: color var(--ps--duration-fast); }
.ps-dc__collCard:hover .ps-dc__collCardArrow { color: var(--ps--primary); }
.ps-dc__collCardName { font-weight: 900; font-size: 16px; color: var(--ps--fg); letter-spacing: -0.01em; margin-top: 14px; }
.ps-dc__collCardMeta { font-size: 12px; color: var(--ps--neutral-500); margin-top: 3px; }
.ps-dc__collCardBar { display: flex; height: 5px; border-radius: 3px; overflow: hidden; margin-top: 14px; background: var(--ps--neutral-100); }
.ps-dc__collCardBar span { display: block; }
.ps-dc__collCardBar .is-live { background: var(--ps--success); }
.ps-dc__collCardBar .is-draft { background: var(--ps--warning); }
.ps-dc__collCardLegend { display: flex; gap: 12px; font-size: 11px; color: var(--ps--neutral-400); margin-top: 7px; }
.ps-dc__collCardLegend b { font-weight: 800; }
.ps-dc__collCardLegend .is-live b { color: var(--ps--success-fg); }
.ps-dc__collCardLegend .is-draft b { color: var(--ps--warning-fg); }

.ps-dc__back { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: var(--ps--neutral-500); background: none; border: none; padding: 0; margin-bottom: 18px; cursor: pointer; }
.ps-dc__back:hover { color: var(--ps--fg); }

.ps-dc__detailHead { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.ps-dc__detailIcon { width: 42px; height: 42px; border-radius: 10px; background: var(--ps--primary-soft); color: var(--ps--primary); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-dc__detailTitle { margin: 0; font-family: var(--ps--font-sans); font-size: 20px; font-weight: 900; letter-spacing: -0.01em; color: var(--ps--fg); }
.ps-dc__detailSub { font-size: 12px; color: var(--ps--neutral-400); margin-top: 2px; }

/* Segment-Control (Detail-Tabs „Einträge | Felder" + Status-Filter der Liste) */
.ps-segctl { display: inline-flex; gap: 4px; padding: 4px; background: var(--ps--bg-soft); border-radius: var(--ps--radius-md); width: max-content; max-width: 100%; }
.ps-segctl__btn { display: inline-flex; align-items: center; gap: 6px; padding: 6px 16px; border: 0; border-radius: 6px; background: none; font: 700 13px var(--ps--font-sans); color: var(--ps--neutral-500); cursor: pointer; white-space: nowrap; }
.ps-segctl__btn:hover { color: var(--ps--fg); }
/* #fff hier ist BEABSICHTIGT und vollständig: darkmode.css setzt für
   .ps-segctl__btn.is-active eigene Werte (--dm-raised / --dm-fg). Das Paar ist
   also da — ein Token an dieser Stelle wäre die schlechtere Lösung, weil das
   aktive Segment im Hellen bewusst WEISSER ist als die Kartenfläche. */
.ps-segctl__btn.is-active { background: #fff; color: var(--ps--fg); box-shadow: var(--ps--shadow-xs); }
.ps-segctl__count { color: var(--ps--neutral-400); font-weight: 700; }
.ps-dc__detailTabs { margin-bottom: 20px; }

.ps-dc__todoNote { font-size: 13px; color: var(--ps--neutral-500); padding: 20px 0; }

/* ===========================================================
   Felder-Editor (Collection-Detail, Tab „Felder") — CMS-Collections Task 10
   =========================================================== */
.ps-cfe__list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.ps-cfe__row { position: relative; border: 1px solid var(--ps--border); border-radius: 11px; padding: 13px 16px; background: var(--ps--neutral-0); transition: border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast), opacity var(--ps--duration-fast); }
/* Das aktuell bearbeitete Feld (Fokus in einem seiner Eingabefelder) bekommt
   den grünen Rahmen + weichen Glow-Ring aus dem 1a-Entwurf. */
.ps-cfe__row:focus-within { border-color: var(--ps--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ps--primary) 12%, transparent); }
/* Drag-and-Drop-Umsortieren über den Grip (collection-fields-editor.jsx):
   die gezogene Zeile wird ausgeblasst, die Zielzeile bekommt eine
   Einfüge-Linie oberhalb ('before') bzw. unterhalb ('after') der Zeile. */
.ps-cfe__row.is-dragging { opacity: 0.4; }
.ps-cfe__row.is-drop-before::before,
.ps-cfe__row.is-drop-after::after {
    content: '';
    position: absolute;
    left: 16px;
    right: 16px;
    height: 3px;
    border-radius: 2px;
    background: var(--ps--primary);
}
.ps-cfe__row.is-drop-before::before { top: -5px; }
.ps-cfe__row.is-drop-after::after { bottom: -5px; }
.ps-cfe__rowHead { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ps-cfe__grip { display: inline-flex; align-items: center; justify-content: center; color: var(--ps--border-strong); flex: 0 0 auto; cursor: grab; }
.ps-cfe__grip:active { cursor: grabbing; }
.ps-cfe__rowIcon { width: 30px; height: 30px; border-radius: 8px; background: var(--ps--primary-soft); color: var(--ps--primary); display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.ps-cfe__rowLabel { font-weight: 700; font-size: 14px; color: var(--ps--fg); letter-spacing: -0.01em; }
.ps-cfe__badge { font-size: 11px; font-weight: 700; color: var(--ps--neutral-500); background: var(--ps--bg-soft); border: 1px solid var(--ps--border); border-radius: 6px; padding: 3px 9px; }
.ps-cfe__badge--req { color: var(--ps--warning-fg); background: color-mix(in srgb, var(--ps--warning) 12%, var(--ps--neutral-0)); border-color: transparent; }
.ps-cfe__rowActions { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.ps-cfe__detail { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--ps--border); }
.ps-cfe__field { display: flex; flex-direction: column; gap: 6px; min-width: 180px; }
.ps-cfe__field > span { font-size: 11.5px; font-weight: 700; color: var(--ps--neutral-500); }
.ps-cfe__field input[type="text"] { height: 36px; padding: 0 10px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); background: var(--ps--neutral-0); outline: none; }
.ps-cfe__field input[type="text"]:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cfe__field--help { flex: 1 1 260px; }
.ps-cfe__required { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 700; color: var(--ps--neutral-500); cursor: pointer; padding-bottom: 8px; }
.ps-cfe__hint { font-size: 11.5px; color: var(--ps--neutral-500); margin: 4px 0 0; }
.ps-cfe__options { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--ps--border); }
.ps-cfe__optionsLabel { display: block; font-size: 11.5px; font-weight: 700; color: var(--ps--neutral-500); margin-bottom: 8px; }
.ps-cfe__optionRow { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.ps-cfe__optionRow input[type="text"] { flex: 1; height: 36px; padding: 0 10px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); background: var(--ps--neutral-0); outline: none; }
.ps-cfe__optionRow input[type="text"]:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
/* Kopfleiste „Feld hinzufügen" (oben, Aktion rechts) — Muster wie
   .ps-cil__bar/.ps-cil__actions bei der Eintrags-Liste. addWrap bleibt der
   positionierte Anker für das Picker-Popover, das jetzt rechtsbündig UNTER
   dem Button öffnet statt unter der ganzen Liste. */
.ps-cfe__bar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.ps-cfe__addWrap { position: relative; margin-left: auto; }
.ps-cfe__picker { position: absolute; top: calc(100% + 10px); right: 0; z-index: 20; display: grid; grid-template-columns: repeat(4, minmax(148px, 1fr)); gap: 4px; padding: 10px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 13px; box-shadow: var(--ps--shadow-lg); width: max-content; max-width: min(640px, 92vw); }
@media (max-width: 720px) { .ps-cfe__picker { grid-template-columns: repeat(2, minmax(140px, 1fr)); } }
.ps-cfe__pickerItem { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; padding: 11px; border: 1px solid transparent; border-radius: 9px; background: none; cursor: pointer; text-align: left; }
.ps-cfe__pickerItem:hover { background: var(--ps--primary-soft); }
.ps-cfe__pickerItem i, .ps-cfe__pickerItem svg { color: var(--ps--primary); flex: 0 0 auto; }
.ps-cfe__pickerName { font-size: 12.5px; font-weight: 800; color: var(--ps--fg); }
.ps-cfe__pickerDesc { font-size: 10.5px; line-height: 1.35; color: var(--ps--neutral-400); }

/* -----------------------------------------------------------
   CMS-Collections: Eintrags-Liste (ps-cil) + Eintrags-Editor (ps-cee)
   ----------------------------------------------------------- */
/* Liste */
.ps-cil__bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.ps-cil__search { display: flex; align-items: center; gap: 8px; flex: 1 1 240px; min-width: 200px; height: 38px; padding: 0 12px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); background: var(--ps--neutral-0); color: var(--ps--neutral-500); }
.ps-cil__search input { flex: 1; border: 0; outline: none; background: none; font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); }
.ps-cil__filter { display: flex; align-items: center; gap: 8px; }
.ps-cil__filterLabel { font-size: 11.5px; font-weight: 700; color: var(--ps--neutral-500); }
.ps-cil__filter select { height: 38px; padding: 0 10px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); background: var(--ps--neutral-0); outline: none; cursor: pointer; }
.ps-cil__filter select:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cil__actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.ps-cil__sortBtn { display: inline-flex; align-items: center; gap: 4px; background: none; border: 0; padding: 0; font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit; cursor: pointer; }
.ps-cil__sortBtn:hover { color: var(--ps--fg); }
/* Klickbare Zeile ist ein <button> — Button-Defaults zurücksetzen, ps-row-Flex behalten. */
.ps-cil__row { width: 100%; text-align: left; background: none; border: 0; border-bottom: 1px solid var(--ps--border); font: inherit; color: inherit; cursor: pointer; }
.ps-cil__row:last-child { border-bottom: 0; }
/* Die Zeile ist ein div, kein Knopf: Checkbox und Icon-Knöpfe dürfen nicht in
   einem <button> liegen (interaktives Element im interaktiven Element).
   Der Öffnen-Knopf spannt stattdessen die ganze Zeilenbreite bis auf Checkbox
   und Aktionen — alles darin ist reine Anzeige (nur <span>, Phrasing Content).
   So bleibt fast die ganze Zeile anklickbar, mit einem ECHTEN Knopf: kein
   Klick-Handler auf einer nicht-interaktiven Fläche, keine gefälschte Rolle.
   Die inneren Zellen tragen dieselben Breiten wie die Kopfzeile, damit die
   Spalten trotz der Knopf-Ebene fluchten (gap 16px wie .ps-row). */
.ps-cil__open { display: flex; align-items: center; gap: 16px; flex: 1; min-width: 0; background: none; border: 0; padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.ps-cil__openText { flex: 1; min-width: 0; }
.ps-cil__open .ps-row__name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-cil__statusCell { width: 100px; flex: 0 0 auto; }
.ps-cil__previewHead { flex: 1; min-width: 0; }
.ps-cil__when { width: 140px; flex: 0 0 auto; font-size: 12px; color: var(--ps--neutral-500); }
.ps-cil__draftPill { background: var(--ps--bg-soft); color: var(--ps--fg-muted); }
.ps-cil__draftPill .ps-pill__dot { background: var(--ps--fg-subtle); }
.ps-cil__rowActions { display: flex; align-items: center; gap: 4px; width: 72px; flex: 0 0 auto; justify-content: flex-end; }
.ps-cil__iconBtn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border: 1px solid var(--ps--border); border-radius: var(--ps--radius-sm); background: var(--ps--neutral-0); color: var(--ps--fg-muted); cursor: pointer; }
.ps-cil__iconBtn:hover:not(:disabled) { color: var(--ps--fg); border-color: var(--ps--border-strong); }
.ps-cil__iconBtn:disabled { opacity: 0.45; cursor: not-allowed; }
.ps-cil__iconBtn--danger { color: var(--ps--danger); }
.ps-cil__iconBtn--danger:hover:not(:disabled) { color: var(--ps--danger); border-color: var(--ps--danger); }
.ps-cil__selectToggle.is-active { border-color: var(--ps--primary); color: var(--ps--primary); }
.ps-cil__bulk { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 14px; margin-bottom: 12px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-md); background: var(--ps--bg-soft); }
.ps-cil__bulkCount { font-size: 13px; color: var(--ps--fg); }
.ps-cil__bulkSpacer { flex: 1; }
.ps-cil__checkCell { width: 28px; height: 34px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.ps-cil__check { width: 16px; height: 16px; margin: 0; cursor: pointer; accent-color: var(--ps--primary); }
/* Auswahl ist ein Akzent-Zustand, keine neutrale Fläche: --ps--bg-soft lag im
   Dunkelmodus nur 3 % über dem Zeilenuntergrund (gemessen) und war praktisch
   unsichtbar. --ps--primary-soft ist in beiden Modi definiert (hell ein Tint,
   dunkel transluzent über der Fläche). */
.ps-cil__row.is-selected { background: var(--ps--primary-soft); }
.ps-cil__preview { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ps--neutral-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-cil__more { margin-top: 16px; text-align: center; }
@media (max-width: 720px) { .ps-cil__hideSm { display: none !important; } }
/* Zeilen-Thumbnail: Bild-Feld des Eintrags, sonst dezenter Verlaufs-Platzhalter */
.ps-cil__thumb { width: 40px; height: 30px; border-radius: 6px; flex: 0 0 auto; overflow: hidden; background: linear-gradient(135deg, var(--ps--neutral-200), var(--ps--neutral-300)); }
/* Platzhalter-Vorschaubilder der Collection-Liste: drei dekorative Verläufe,
   die ein fehlendes Bild andeuten. Bleiben literal (PS-88) — es sind Bildinhalte,
   keine Oberflächenfarben, und es gibt keine Rolle, die sie tragen könnte. */
.ps-cil__thumb--a { background: linear-gradient(135deg, #bfd8ce, #8db9a8); }
.ps-cil__thumb--b { background: linear-gradient(135deg, #d9cbb8, #b09a7d); }
.ps-cil__thumb--c { background: linear-gradient(135deg, #c4ccd8, #8e9bb4); }
.ps-cil__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Editor (Redesign „1a": Kopfleiste + einspaltiges Formular mit 2-spaltigem Feld-Grid) */
/* Der Eintrag sitzt als weiße Karte auf dem neutral-50-Seitenhintergrund
   (Referenz-Mockup) — erst dadurch heben sich die „gefüllten" neutral-100-
   Eingabefelder ab. Dezenter Schatten, kein hartes Chrome. */
.ps-cee { max-width: 980px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; padding: 22px 30px 26px; box-shadow: var(--ps--shadow-sm); }
.ps-cee__headerbar { display: flex; align-items: center; gap: 12px; padding: 12px 18px; border: 1px solid var(--ps--border); border-radius: 14px; background: var(--ps--neutral-50); margin: 0 0 22px; flex-wrap: wrap; }
.ps-cee__headerbar .ps-dc__back { margin: 0; }
.ps-cee__hbTitle { font-size: 15px; font-weight: 900; letter-spacing: -0.01em; color: var(--ps--fg); flex: 1; min-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-cee__saved { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--ps--neutral-400); }
.ps-cee__saved i { color: var(--ps--success-fg); }
.ps-cee__hbStatus { display: inline-flex; gap: 6px; }
/* Kein eigener max-width mehr: Formular füllt die Kartenbreite und ist damit
   links wie rechts bündig mit Kopfleiste (Entwurf/Live) und Fußzeile. Die
   Gesamtbreite steuert die Karte .ps-cee (max-width). */
.ps-cee__form { width: 100%; }
.ps-cee__footer { display: flex; align-items: center; gap: 18px; margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--ps--border); flex-wrap: wrap; }
.ps-cee__footMeta { display: flex; gap: 18px; font-size: 12px; color: var(--ps--neutral-500); flex-wrap: wrap; }
.ps-cee__footMeta b { color: var(--ps--fg); font-weight: 700; }
.ps-cee__titleLabel, .ps-cee__slugLabel { display: block; font-size: 11.5px; font-weight: 700; color: var(--ps--neutral-500); }
/* Titel/Slug erben Fläche + Fokus aus der gemeinsamen „gefüllt"-Regel unten;
   hier nur noch Layout/Typo. */
.ps-cee__titleInput { width: 100%; margin-top: 6px; padding: 10px 13px; font: 800 22px var(--ps--font-sans); letter-spacing: -0.01em; }
.ps-cee__slugRow { display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.ps-cee__slugInput { flex: 1 1 240px; min-width: 180px; height: 34px; padding: 0 12px; font: 400 13px var(--ps--font-mono, monospace); }
.ps-cee__fields { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 18px; margin-top: 24px; align-items: start; }
@media (max-width: 720px) { .ps-cee__fields { grid-template-columns: 1fr; } }
/* Lange Felder + der Leerzustand über die volle Breite (Rich-Text, Bild-Feld
   mit aufklappbarer Inline-Mediathek). */
.ps-cee__fields > [data-field-type="richtext"],
.ps-cee__fields > [data-field-type="image"],
.ps-cee__fields > .ps-dc__collEmpty { grid-column: 1 / -1; }
.ps-cee__field { display: flex; flex-direction: column; gap: 7px; }
.ps-cee__label { font-size: 12px; font-weight: 700; color: var(--ps--fg); }
.ps-cee__req { color: var(--ps--warning, #d97706); font-style: normal; }
.ps-cee__help { font-size: 11.5px; color: var(--ps--neutral-500); margin: 0; }
/* „Gefüllte" Eingabefelder (Redesign): weiche Fläche statt harter Rahmen —
   Ruhezustand neutral-100 + transparenter Rahmen, Fokus wird weiß + Marken-Rahmen
   + Fokus-Ring. Gemeinsame Optik für alle typisierten Text-/Auswahlfelder. */
.ps-cee__titleInput, .ps-cee__slugInput, .ps-cee__input, .ps-cee__textarea, .ps-cee__select, .ps-cee__colorHex {
  border: 1.5px solid transparent; border-radius: 9px; background: var(--ps--neutral-100, #f1f4f3); color: var(--ps--fg); outline: none;
  transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.ps-cee__titleInput:focus, .ps-cee__slugInput:focus, .ps-cee__input:focus, .ps-cee__textarea:focus, .ps-cee__select:focus, .ps-cee__colorHex:focus {
  background: var(--ps--neutral-0); border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring);
}
.ps-cee__input { width: 100%; padding: 9px 12px; font: 400 13.5px var(--ps--font-sans); }
.ps-cee__textarea { width: 100%; padding: 9px 12px; font: 400 13.5px var(--ps--font-sans); resize: vertical; min-height: 96px; }
.ps-cee__select { width: 100%; max-width: 320px; height: 38px; padding: 0 12px; font: 400 13.5px var(--ps--font-sans); cursor: pointer; }
.ps-cee__switch { align-self: flex-start; }
.ps-cee__colorRow { display: flex; align-items: center; gap: 10px; }
.ps-cee__color { width: 44px; height: 34px; padding: 2px; border: 1.5px solid transparent; border-radius: 9px; background: var(--ps--neutral-100, #f1f4f3); cursor: pointer; }
.ps-cee__colorHex { width: 120px; height: 34px; padding: 0 12px; font: 400 13px var(--ps--font-mono, monospace); }
/* Richtext-Feld: Inhouse-Editor (Toolbar + contentEditable-Fläche), kein Drittanbieter. */
.ps-cee__richtext { display: flex; flex-direction: column; border: 1.5px solid transparent; border-radius: 9px; background: var(--ps--neutral-100, #f1f4f3); overflow: hidden; transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast); }
.ps-cee__richtext:focus-within { background: var(--ps--neutral-0); border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cee__rtToolbar { display: flex; align-items: center; gap: 2px; padding: 4px; border-bottom: 1px solid var(--ps--border); }
.ps-cee__rtBtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; border-radius: calc(var(--ps--radius-sm) - 2px); background: transparent; color: var(--ps--neutral-500); cursor: pointer; }
.ps-cee__rtBtn:hover { background: var(--ps--neutral-100); color: var(--ps--fg); }
.ps-cee__rtBtn:focus-visible { outline: 2px solid var(--ps--primary); outline-offset: 1px; }
.ps-cee__rtEditor { min-height: 84px; padding: 8px 10px; font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); outline: none; }
.ps-cee__rtEditor[data-empty]::before { content: attr(data-placeholder); color: var(--ps--neutral-400); pointer-events: none; }
.ps-cee__rtEditor p { margin: 0 0 0.6em; }
.ps-cee__rtEditor p:last-child { margin-bottom: 0; }
.ps-cee__rtEditor ul, .ps-cee__rtEditor ol { margin: 0 0 0.6em; padding-left: 1.4em; }
.ps-cee__rtEditor a { color: var(--ps--primary); text-decoration: underline; }
/* Bild-Feld: kompakte „Ausgewählt"-Karte + aufklappbare Inline-Mediathek.
   Karte und Panel sind „gefüllte" Flächen (neutral-100); die darauf sitzenden
   Bedien-Elemente (Ändern/Entfernen, Suche, Ordner, Kacheln) sind weiß, damit
   sie sich von der Fläche abheben. */
.ps-cee__image { display: flex; flex-direction: column; gap: 10px; }
.ps-cee__imgMissing { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border: 1.5px dashed var(--ps--border-strong); border-radius: 12px; color: var(--ps--warning, #d97706); font-size: 12.5px; }
.ps-cee__imgThumb { display: inline-flex; width: 88px; height: 66px; border-radius: 8px; overflow: hidden; background: var(--ps--neutral-50); border: 1px solid var(--ps--border); }
.ps-cee__imgThumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Kompakte „Ausgewählt"-Karte (Standardzustand mit Auswahl) */
.ps-cee__imgCard { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: 12px; background: var(--ps--neutral-100, #f1f4f3); }
.ps-cee__imgThumb--card { width: 64px; height: 64px; flex: none; border: 0; border-radius: 10px; background: var(--ps--neutral-0); }
.ps-cee__imgCardBody { flex: 1; min-width: 0; }
.ps-cee__imgNameRow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ps-cee__imgName { font-size: 13px; color: var(--ps--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.ps-cee__imgBadge { display: inline-flex; align-items: center; gap: 5px; flex: none; font-size: 10.5px; font-weight: 700; color: var(--ps--primary); background: var(--ps--neutral-0); border-radius: var(--ps--radius-pill); padding: 3px 9px; }
.ps-cee__imgBadgeDot { width: 5px; height: 5px; border-radius: 50%; background: var(--ps--primary); }
.ps-cee__imgMeta { font-size: 11.5px; color: var(--ps--neutral-400); margin-top: 3px; }
.ps-cee__imgChange { flex: none; height: 32px; padding: 0 13px; border: 0; border-radius: 8px; background: var(--ps--neutral-0); font: 700 12px var(--ps--font-sans); color: var(--ps--fg); cursor: pointer; box-shadow: var(--ps--shadow-xs); }
.ps-cee__imgChange:hover { box-shadow: var(--ps--shadow-sm); }
.ps-cee__imgRemove { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; border: 0; border-radius: 8px; background: var(--ps--neutral-0); color: var(--ps--warning, #d97706); cursor: pointer; box-shadow: var(--ps--shadow-xs); }
.ps-cee__imgRemove:hover { box-shadow: var(--ps--shadow-sm); }

/* Leerer Zustand: gestrichelte Auswahl-/Ablage-Schaltfläche (öffnet das Panel) */
.ps-cee__imgChoose { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 84px; padding: 12px; border: 1.5px dashed var(--ps--border-strong); border-radius: 12px; background: var(--ps--neutral-50); color: var(--ps--neutral-400); font: 700 12.5px var(--ps--font-sans); cursor: pointer; transition: border-color var(--ps--duration-fast), color var(--ps--duration-fast), background var(--ps--duration-fast); }
.ps-cee__imgChoose:hover, .ps-cee__imgChoose.is-dragover { border-color: var(--ps--primary); color: var(--ps--primary); background: var(--ps--primary-soft); }
.ps-cee__imgChoose:disabled { cursor: default; opacity: 0.7; }

/* Aufklappbares Inline-Mediathek-Panel */
.ps-cee__imgPanel { border-radius: 12px; background: var(--ps--neutral-100, #f1f4f3); overflow: hidden; }
.ps-cee__imgPanelBar { display: flex; align-items: center; gap: 10px; padding: 12px 14px; flex-wrap: wrap; }
.ps-cee__imgSearch { position: relative; display: flex; align-items: center; flex: 1; min-width: 180px; }
.ps-cee__imgSearch > span { position: absolute; left: 10px; color: var(--ps--neutral-400); }
.ps-cee__imgSearch input { width: 100%; box-sizing: border-box; height: 32px; padding: 0 10px 0 30px; border: 1.5px solid transparent; border-radius: 8px; background: var(--ps--neutral-0); font: 400 12.5px var(--ps--font-sans); color: var(--ps--fg); outline: none; }
.ps-cee__imgSearch input:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cee__imgFolder { height: 32px; padding: 0 12px; border: 0; border-radius: 8px; background: var(--ps--neutral-0); font: 700 12px var(--ps--font-sans); color: var(--ps--fg); cursor: pointer; outline: none; box-shadow: var(--ps--shadow-xs); }
.ps-cee__imgFolder:focus { box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cee__imgUpload { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 13px; border: 0; border-radius: 8px; background: var(--ps--primary); color: var(--ps--primary-fg); font: 700 12px var(--ps--font-sans); cursor: pointer; }
.ps-cee__imgUpload:hover { background: var(--ps--primary-hover); }
.ps-cee__imgUpload:disabled { cursor: default; opacity: 0.7; }
.ps-cee__imgGrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 10px; padding: 0 14px; }
.ps-cee__imgTile { position: relative; padding: 0; border: 2px solid transparent; border-radius: 10px; background: var(--ps--neutral-0); cursor: pointer; }
.ps-cee__imgTile.is-active { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-cee__imgTile:focus-visible { outline: 2px solid var(--ps--primary); outline-offset: 2px; }
.ps-cee__imgTile .ps-cee__imgThumb { width: 100%; height: 64px; border: 0; border-radius: 8px; background: transparent; }
.ps-cee__imgCheck { position: absolute; top: -7px; right: -7px; display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; background: var(--ps--primary); border: 2px solid var(--ps--neutral-0); color: var(--ps--primary-fg); }
.ps-cee__imgEmpty { margin: 0; padding: 4px 14px 0; font-size: 12px; color: var(--ps--neutral-500); }
.ps-cee__imgFoot { display: flex; align-items: center; gap: 10px; margin: 12px 14px 0; }
.ps-cee__imgCount { font-size: 11.5px; color: var(--ps--neutral-500); }
.ps-cee__imgMore { margin-left: auto; border: 0; background: none; font: 700 12px var(--ps--font-sans); color: var(--ps--primary); cursor: pointer; padding: 0; }
.ps-cee__imgMore:hover { color: var(--ps--primary-hover); }
.ps-cee__imgDrop { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 10px 14px 14px; padding: 11px; border: 1.5px dashed var(--ps--border-strong); border-radius: 10px; color: var(--ps--neutral-500); font-size: 12px; background: color-mix(in srgb, var(--ps--neutral-0) 55%, transparent); }
.ps-cee__imgDrop.is-dragover { border-color: var(--ps--primary); color: var(--ps--primary); background: var(--ps--primary-soft); }
.ps-cee__err { font-size: 12px; color: var(--ps--danger, #dc2626); margin: 0; }
/* Referenz-Feld */
.ps-cee__ref { position: relative; max-width: 360px; }
.ps-cee__refBar { display: flex; align-items: center; gap: 8px; }
.ps-cee__refValue { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: 8px; height: 38px; padding: 0 12px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); background: var(--ps--neutral-0); color: var(--ps--fg); font: 400 13.5px var(--ps--font-sans); cursor: pointer; }
.ps-cee__refPlaceholder { color: var(--ps--neutral-400); }
.ps-cee__refMissing { display: inline-flex; align-items: center; gap: 6px; color: var(--ps--warning, #d97706); font-weight: 700; }
.ps-cee__refMenu { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; right: 0; padding: 8px; background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 10px; box-shadow: var(--ps--shadow-md, var(--ps--shadow-sm)); }
.ps-cee__refSearch { width: 100%; height: 34px; padding: 0 10px; margin-bottom: 6px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); font: 400 13px var(--ps--font-sans); outline: none; }
.ps-cee__refList { max-height: 220px; overflow-y: auto; display: flex; flex-direction: column; }
.ps-cee__refOpt { text-align: left; padding: 8px 10px; border: 0; border-radius: 8px; background: none; font: 400 13.5px var(--ps--font-sans); color: var(--ps--fg); cursor: pointer; }
.ps-cee__refOpt:hover, .ps-cee__refOpt.is-active { background: var(--ps--bg-soft); }
/* Meta-Spalte */
.ps-cee__meta { display: flex; flex-direction: column; gap: 18px; padding: 16px; border: 1px solid var(--ps--border); border-radius: 14px; background: var(--ps--neutral-50); }
.ps-cee__metaBlock { display: flex; flex-direction: column; gap: 8px; }
.ps-cee__metaLabel { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ps--neutral-400); }
.ps-cee__metaValue { font-size: 13px; color: var(--ps--fg); }
.ps-cee__status { display: flex; gap: 6px; }
.ps-cee__delete { margin-left: auto; }

/* ---------- NEOS-Extensions als Toggle-Pills (Übersicht, Redesign „1a") ---------- */
.ps-dc__extList { display: flex; flex-wrap: wrap; gap: 10px; }
.ps-dc__extPill { display: inline-flex; align-items: center; gap: 10px; padding: 6px 10px 6px 15px; border: 1px solid var(--ps--border); border-radius: var(--ps--radius-pill); background: var(--ps--neutral-0); font-size: 12.5px; font-weight: 700; color: var(--ps--neutral-500); transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), color var(--ps--duration-fast); }
.ps-dc__extPill.is-on { border-color: color-mix(in srgb, var(--ps--primary) 35%, var(--ps--border)); background: var(--ps--primary-soft); color: var(--ps--primary); }
/* Der geteilte CollectionSwitch sitzt hier kompakt in der Pill — Textlabel aus. */
.ps-dc__extPill .ps-dc__switch { width: auto; }
.ps-dc__extPill .ps-dc__switchText { display: none; }

/* ===========================================================
   Studio-Chrome-Buttons: EIN kanonischer Look (AGENTS.md „Unified studio UI")
   ===========================================================
   Referenz ist der Topbar-Export-Button (.ps-top__export): 40px hoch,
   Radius 9px, fette 14px-Beschriftung; farbige Buttons (grüner Primär,
   roter Danger → .cp-btn--danger in app.css) tragen denselben dezenten
   Glow. .bx-btn ist eigentlich das WEBSITE-Button-Atom (components.css,
   --mp-*) — überall im Studio-Chrome wird es HIER zentral auf das
   Studio-Design (--ps--*) umgezogen. Buttons werden NICHT pro Bereich
   einzeln nachgestylt; Design-Änderungen passieren an dieser einen Stelle
   und gelten damit app-weit.
   Ausgenommen sind die Website-Render-Flächen im selben Dokument — die
   Story-Vorschauflächen (.cp-story__content) zeigen das echte
   Website-Atom. Der Builder-Canvas ist ein eigenes iframe-Dokument ohne
   shell.css und bleibt ohnehin unberührt. */
.bx-btn:not(.cp-story__content *) {
  height: 40px; padding: 0 18px; border-radius: 9px;
  font-family: var(--ps--font-sans); font-size: 14px; font-weight: 700;
}
.bx-btn--icon:not(.cp-story__content *) { padding: 0; }
.bx-btn--primary:not(.cp-story__content *) {
  background: var(--ps--primary); color: var(--ps--primary-fg); border-color: transparent;
  box-shadow: 0 2px 8px rgba(0, 129, 93, 0.28);
}
.bx-btn--primary:not(.cp-story__content *):hover { background: var(--ps--primary-hover); }
.bx-btn--primary:not(.cp-story__content *):active { background: var(--ps--primary-press); }
.bx-btn--secondary:not(.cp-story__content *) {
  background: var(--ps--neutral-0); color: var(--ps--fg); border: 1px solid var(--ps--border-strong);
}
.bx-btn--secondary:not(.cp-story__content *):hover { background: var(--ps--neutral-50); border-color: var(--ps--neutral-400); }
.bx-btn--ghost:not(.cp-story__content *) { background: transparent; color: var(--ps--primary); }
.bx-btn--ghost:not(.cp-story__content *):hover { color: var(--ps--primary-hover); }
.bx-btn:not(.cp-story__content *):focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ps--focus-ring); }
/* Danger-Kombis („bx-btn … cp-btn--danger") behalten ihren ROTEN Fokus-Ring
   (app.css) — sonst gewänne hier der grüne Studio-Ring per Spezifität. */
.bx-btn.cp-btn--danger:not(.cp-story__content *):focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ps--danger) 35%, transparent); }

/* ===========================================================
   KI-Einstellungen (Anbieter + API-Keys) — baut auf ps-dc auf
   =========================================================== */
.ps-ai__h { font-size: 13px; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ps--neutral-500); margin: 0 0 12px; }

/* Marken-Logo-Kachel (Hintergrund/Farbe inline aus dem Akzent des Anbieters) */
/* Fläche und Glyphfarbe kommen aus --sp-hex (der MARKENFARBE des Anbieters,
   ai-settings.jsx) — eigene Regel statt .ps-badge-dyn, weil das eine Pille mit
   eigener Geometrie ist. Der dunkle Modus hebt die Farbe in darkmode.css an;
   ohne das wäre etwa der schwarze xAI-Akzent auf dunklem Grund unsichtbar. */
.ps-ai__logoTile { width: 38px; height: 38px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; background: color-mix(in srgb, var(--sp-hex, var(--ps--fg-muted)) var(--sp-a, 12%), transparent); color: var(--sp-hex, var(--ps--fg-muted)); }
.ps-ai__logoTile--lg { width: 46px; height: 46px; border-radius: 12px; }
.ps-ai__logoTile svg { display: block; }

/* Anbieter-Auswahl (Logo-Kacheln) + aufklappendes Key-Formular */
.ps-ai__picker { background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; padding: 14px; margin-bottom: 6px; max-width: 880px; }
.ps-ai__choices { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 720px) { .ps-ai__choices { grid-template-columns: 1fr; } }
.ps-ai__choice { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--ps--border); border-radius: 10px; background: var(--ps--neutral-0); cursor: pointer; text-align: left; transition: border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast); }
.ps-ai__choice:hover { border-color: var(--ps--fg); }
.ps-ai__choice.is-active { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-ai__choiceText { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ps-ai__choiceName { font-size: 14px; font-weight: 800; color: var(--ps--fg); letter-spacing: -0.01em; }
.ps-ai__choiceTag { font-size: 11.5px; color: var(--ps--neutral-500); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-ai__choiceIcon { width: 16px; height: 16px; color: var(--ps--neutral-400); flex: 0 0 auto; }
.ps-ai__choice.is-active .ps-ai__choiceIcon { color: var(--ps--primary); }

.ps-ai__form { margin-top: 12px; padding: 16px; border: 1px solid var(--ps--border); border-radius: 12px; background: var(--ps--bg-soft); }
.ps-ai__formHead { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.ps-ai__hint { font-size: 11.5px; color: var(--ps--neutral-500); margin-top: 2px; }

/* Eingesetzte Modelle je Rolle in der Anbieter-Karte. Nur Tokens, keine
   literalen Farben — darkmode.css erreicht Inline-Stile strukturell nicht
   (siehe tests/js/views/no-inline-colors.test.js). */
.ps-ai__models { margin-top: 10px; display: grid; gap: 4px; }
.ps-ai__modelRow { display: flex; align-items: baseline; gap: 8px; font-size: 11.5px; }
.ps-ai__modelRow dt { color: var(--ps--neutral-500); flex: 0 0 auto; }
.ps-ai__modelRow dd { margin: 0; min-width: 0; }
.ps-ai__modelRow code { font-size: 11px; color: var(--ps--fg); background: var(--ps--bg-soft); border: 1px solid var(--ps--border); border-radius: 5px; padding: 1px 5px; }
.ps-ai__models--none { color: var(--ps--neutral-500); font-size: 11.5px; }
.ps-ai__fieldLabel { display: block; font-size: 12px; font-weight: 700; color: var(--ps--neutral-600); margin-bottom: 6px; }
.ps-ai__input { width: 100%; min-width: 0; height: 40px; padding: 0 12px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); background: var(--ps--neutral-0); font: 400 13.5px var(--ps--font-mono); color: var(--ps--fg); outline: none; }
.ps-ai__input:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-ai__formActions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; }

.ps-ai__allset, .ps-ai__empty { display: flex; align-items: center; gap: 10px; padding: 16px; border: 1px dashed var(--ps--border-strong); border-radius: 12px; background: var(--ps--bg-soft); color: var(--ps--neutral-500); font-size: 13px; line-height: 1.45; max-width: 880px; }
.ps-ai__allset i { width: 16px; height: 16px; color: var(--ps--success, #1f9d55); flex: 0 0 auto; }
.ps-ai__empty i { width: 20px; height: 20px; color: var(--ps--neutral-400); flex: 0 0 auto; }

/* Karte (erbt ps-dc__card) — Key-Zeile mit Maske / Ersetzen-Inline-Eingabe */
.ps-ai__card .ps-dc__cardTop { align-items: flex-start; }
.ps-ai__keyRow { display: flex; align-items: center; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.ps-ai__keyRow > i { width: 15px; height: 15px; color: var(--ps--neutral-400); flex: 0 0 auto; }
.ps-ai__keyMask { font-family: var(--ps--font-mono); font-size: 13px; letter-spacing: 0.06em; color: var(--ps--neutral-600); flex: 1; min-width: 60px; }
.ps-ai__keyReplace { flex: 0 0 auto; }
.ps-ai__keyActions { display: inline-flex; gap: 12px; flex: 0 0 auto; }
.ps-ai__keyRow .ps-ai__input { flex: 1; height: 34px; font-size: 12.5px; }

/* ===========================================================
   Login / Invite / Reset
   =========================================================== */
.ps-auth {
  position: fixed; inset: 0; z-index: 100;
  display: grid; grid-template-columns: 1fr 1fr;
  font-family: var(--ps--font-sans); background: var(--ps--neutral-50);
}
.ps-auth--splash { grid-template-columns: 1fr; place-items: center; background: var(--ps--bg-inverse); }
.ps-auth--splash .ps-auth__brand span,
.ps-auth--splash .ps-auth__brand b { color: #fff; }
.ps-auth--splash .ps-auth__brand b { color: var(--ps--accent); }
.ps-auth__panel {
  background: var(--ps--bg-inverse);
  color: #fff;
  padding: 48px 56px;
  display: flex; flex-direction: column;
  background-image: radial-gradient(circle at 20% 20%, rgba(255,255,255,.06), transparent 40%);
}
.ps-auth__panelMain { flex: 1; display: flex; align-items: center; }
.ps-auth__by { display: flex; flex-direction: column; gap: 12px; }
.ps-auth__byLogo { width: 250px; height: auto; max-width: 80%; opacity: 0.92; }
.ps-auth__by span { font-size: 11px; line-height: 1.4; color: rgba(255, 255, 255, 0.5); }
.ps-auth__brand { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; }
.ps-auth__brand span { color: #fff; }
.ps-auth__brand b { color: var(--ps--accent); font-weight: 800; }
.ps-auth__logo { width: 420px; height: auto; max-width: 100%; display: block; }
.ps-auth--splash .ps-auth__logo { width: 260px; max-width: 70vw; }
.ps-auth__tag { font-size: 16px; color: rgba(255,255,255,.7); max-width: 360px; line-height: 1.5; margin: 0; }
.ps-auth__formWrap { display: flex; align-items: center; justify-content: center; padding: 40px; }
.ps-auth__form { width: 100%; max-width: 360px; display: flex; flex-direction: column; }
.ps-auth__title { font-size: 26px; font-weight: 900; color: var(--ps--fg); margin: 0 0 6px; letter-spacing: -0.01em; }
.ps-auth__sub { font-size: 14px; color: var(--ps--neutral-500); margin: 0 0 24px; }
.ps-auth__field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.ps-auth__field span { font-size: 12px; font-weight: 700; color: var(--ps--neutral-600); }
.ps-auth__field input {
  height: 44px; padding: 0 14px; border: 1px solid var(--ps--border); border-radius: 10px;
  background: var(--ps--neutral-0); font: 400 14px var(--ps--font-sans); color: var(--ps--fg); outline: none;
}
.ps-auth__field input:focus { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.ps-auth__submit {
  height: 46px; margin-top: 8px; border: 0; border-radius: 10px;
  background: var(--ps--primary); color: #fff; font-weight: 700; font-size: 15px; cursor: pointer;
}
.ps-auth__submit:hover { background: var(--ps--primary-hover); }
.ps-auth__submit:disabled { opacity: .6; cursor: default; }
.ps-auth__passkey {
  height: 44px; margin-top: 10px; border: 1px solid var(--ps--border-strong); border-radius: 10px;
  background: var(--ps--neutral-0); color: var(--ps--fg); font-weight: 700; font-size: 14px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.ps-auth__passkey:hover { border-color: var(--ps--fg); }
.ps-auth__passkey i { width: 16px; height: 16px; }
.ps-auth__links { margin-top: 16px; text-align: center; }
.ps-auth__links button { background: none; border: 0; color: var(--ps--primary); font-size: 13px; font-weight: 600; cursor: pointer; }
.ps-auth__err { background: rgba(220,38,38,.08); color: var(--ps--danger); font-size: 13px; padding: 10px 12px; border-radius: 8px; margin-bottom: 12px; }
.ps-auth__info { background: var(--ps--primary-soft); color: var(--ps--primary); font-size: 13px; padding: 10px 12px; border-radius: 8px; margin-bottom: 12px; }
@media (max-width: 820px) { .ps-auth { grid-template-columns: 1fr; } .ps-auth__panel { display: none; } }

/* ===========================================================
   Benutzer / Profil
   =========================================================== */
.ps-seg {
  height: 34px; padding: 0 12px; border: 1px solid var(--ps--border); border-radius: 8px;
  background: var(--ps--neutral-0); color: var(--ps--neutral-600); font-weight: 700; font-size: 13px; cursor: pointer;
}
.ps-seg.is-active { background: var(--ps--primary); border-color: var(--ps--primary); color: #fff; }
.ps-link { background: none; border: 0; color: var(--ps--primary); font-size: 12px; font-weight: 600; cursor: pointer; text-align: left; }

/* Hübsches Dropdown (Trigger wie ein Eingabefeld, Menü als Karte) */
.ps-select { position: relative; }
.ps-select__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; height: 40px; padding: 0 10px 0 12px;
  border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm);
  background: var(--ps--neutral-0); color: var(--ps--fg);
  font: 400 14px var(--ps--font-sans); text-align: left; cursor: pointer;
  transition: border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.ps-select__btn:hover { border-color: var(--ps--fg); }
.ps-select__btn.is-open { border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring); }
/* Gesperrt (PS-93): muss auch AUSSEHEN wie gesperrt — ein Dropdown, das sich
   nur nicht oeffnet, liest sich als Fehler. :hover darf danach nicht mehr
   greifen, deshalb steht die Regel NACH der Hover-Regel. */
.ps-select__btn:disabled,
.ps-select__btn:disabled:hover {
  border-color: var(--ps--border);
  background: var(--ps--bg-soft);
  color: var(--ps--fg-muted);
  cursor: not-allowed;
}
.ps-select__btn:disabled .ps-select__caret { color: var(--ps--fg-subtle); }
.ps-select__btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-select__ph { color: var(--ps--fg-subtle); }
/* Nur-Lese-Wert in einem Einstellungsformular (PS-93, Kundenrolle sieht die
   Plattform, aendert sie aber nicht). Bewusst KEIN gesperrtes Bedienelement:
   das sieht nach Bedienbarkeit aus und ist keine. Hoehe wie ein Eingabefeld,
   damit die Zeile im Raster nicht springt. */
.ps-set__readonly {
  display: flex; align-items: center;
  min-height: 40px; padding: 0 12px;
  border: 1px dashed var(--ps--border); border-radius: var(--ps--radius-sm);
  background: var(--ps--bg-soft); color: var(--ps--fg);
  font: 600 14px var(--ps--font-sans);
}
.ps-select__caret { width: 16px; height: 16px; color: var(--ps--fg-muted); flex: 0 0 auto; }
.ps-select__menu {
  position: fixed; z-index: 70;
  background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 10px;
  box-shadow: var(--ps--shadow-lg); padding: 6px; max-height: 260px; overflow-y: auto;
  animation: ps-pop-in 0.14s var(--ps--ease-out); transform-origin: top center;
}
.ps-select__opt {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 10px; border: 0; background: transparent; border-radius: 7px;
  font-size: 14px; font-weight: 600; color: var(--ps--fg); text-align: left; cursor: pointer;
}
.ps-select__opt:hover { background: var(--ps--bg-soft); }
.ps-select__heading {
  padding: 8px 10px 3px; margin-top: 2px;
  font-size: 10px; font-weight: 700; letter-spacing: var(--ps--tracking-caps);
  text-transform: uppercase; color: var(--ps--fg-subtle); pointer-events: none;
}
.ps-select__heading:first-child { margin-top: 0; }
.ps-select__opt.is-active { background: var(--ps--primary-soft); color: var(--ps--primary); }
.ps-select__check { width: 15px; height: 15px; flex: 0 0 auto; }

/* Passwort-Feld mit Generator + Stärkeanzeige */
.ps-pw__row { display: flex; gap: 8px; align-items: stretch; }
.ps-pw__input { flex: 1; min-width: 0; }
.ps-pw__gen { height: 40px; flex: 0 0 auto; white-space: nowrap; }
.ps-pw__meter { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.ps-pw__bars { display: flex; gap: 4px; flex: 1; }
.ps-pw__seg { flex: 1; height: 5px; border-radius: 999px; transition: background var(--ps--duration-fast); }
.ps-pw__label { font-size: 12px; font-weight: 700; flex: 0 0 auto; }

.ps-card { background: var(--ps--neutral-0); border: 1px solid var(--ps--border); border-radius: 14px; padding: 22px 24px; margin-bottom: 18px; max-width: 720px; }
.ps-card__h { font-size: 16px; font-weight: 900; color: var(--ps--fg); margin: 0 0 4px; letter-spacing: -0.01em; }
.ps-card__sub { font-size: 13px; color: var(--ps--neutral-500); margin: 0 0 16px; }
.ps-card .cp-modal__field { margin-bottom: 14px; }
/* Breite Karte: für Ansichten mit vierspaltigem Feld-Gitter (Globale
   Einstellungen). Bewusst ein Modifier der gemeinsamen Karte statt einer
   eigenen Karte — Rahmen, Radius und Polster bleiben kanonisch. */
.ps-card--wide { max-width: 980px; }

/* ---------- Globale Einstellungen: gruppiert & verankert ----------
   Umsetzung des Redesigns „1A". Farben, Radien und Schrift kommen aus den
   ps--Tokens; die Maße (Kachel-Gitter, 66ch Textbreite, Chevron-Drehung)
   stammen aus dem Design-Handoff. Buttons bleiben die kanonischen .ps-btn —
   siehe AGENTS.md, „Unified studio-chrome UI". */
.ps-gset__tiles {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
  max-width: 980px; margin: 0 0 18px;
}
.ps-gset__tile {
  display: flex; flex-direction: column; gap: 3px; align-items: flex-start; text-align: left;
  padding: 12px 14px; background: var(--ps--neutral-0);
  border: 1px solid var(--ps--border); border-radius: var(--ps--radius-md);
  cursor: pointer; transition: border-color var(--ps--duration-fast);
}
.ps-gset__tile:hover { border-color: var(--ps--border-strong); }
.ps-gset__tileLabel {
  display: inline-flex; align-items: center; gap: 7px;
  font: 700 11.5px var(--ps--font-sans); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ps--fg-muted);
}
.ps-gset__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ps--primary); flex: none; }
.ps-gset__tile[data-tone="warn"] .ps-gset__dot { background: var(--ps--warning, #d97706); }
.ps-gset__tileValue { font: 700 15px var(--ps--font-sans); color: var(--ps--fg); }

.ps-gset__search {
  display: flex; align-items: center; gap: 10px; height: 44px; padding: 0 14px;
  max-width: 980px; margin: 0 0 22px; background: var(--ps--neutral-0);
  border: 1px solid var(--ps--border); border-radius: var(--ps--radius-md);
}
.ps-gset__search > svg, .ps-gset__search > i { flex: none; color: var(--ps--fg-muted); }
.ps-gset__search input {
  flex: 1; min-width: 0; border: 0; outline: none; background: transparent;
  font: 400 14.5px var(--ps--font-sans); color: var(--ps--fg);
}
.ps-gset__count { flex: none; font-size: 12.5px; color: var(--ps--fg-muted); }

/* Der Sprung setzt scrollTop des Hauptbereichs (.ps-main) — scroll-margin gibt
   der Kategorie oben Luft, damit der Kopf nicht am Rand klebt. */
.ps-gset__cat { margin-bottom: 22px; scroll-margin-top: 16px; }
.ps-gset__catHead { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 0 0 12px; padding-top: 6px; }
.ps-gset__catNum { font: 400 12px var(--ps--font-display); color: var(--ps--border-strong); }
.ps-gset__catTitle { margin: 0; font: 900 19px var(--ps--font-sans); color: var(--ps--fg); }
.ps-gset__catMeta { font-size: 13.5px; color: var(--ps--fg-muted); }

.ps-sec__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; }
.ps-sec__text { display: flex; flex-direction: column; gap: 5px; max-width: 66ch; }
.ps-sec__short { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ps--neutral-500); }
.ps-sec__more {
  margin: 4px 0 0; padding-left: 12px; border-left: 2px solid var(--ps--border);
  font-size: 13.5px; line-height: 1.6; color: var(--ps--neutral-500);
}
.ps-sec__toggle {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 5px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: 700 12.5px var(--ps--font-sans); color: var(--ps--primary);
}
.ps-sec__chevron { transition: transform 160ms cubic-bezier(0.2, 0, 0, 1); }
.ps-sec__chevron.is-open { transform: rotate(180deg); }
.ps-sec__actions { display: flex; gap: 8px; flex: none; }
.ps-sec__body { margin-top: 14px; padding-top: 16px; border-top: 1px solid var(--ps--border); }
.ps-sec__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px 18px; }
.ps-sec__grid .cp-modal__field { margin-bottom: 0; }
.ps-sec__hint { font-size: 12px; line-height: 1.45; color: var(--ps--fg-muted); }
.ps-sec__note { margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--ps--neutral-500); max-width: 76ch; }
@media (max-width: 1200px) {
  .ps-gset__tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ps-sec__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Sprungmarken unter dem aktiven Subnavi-Eintrag. */
.cp-subnav__anchors {
  display: flex; flex-direction: column; gap: 1px;
  margin: 2px 0 6px 10px; padding-left: 10px; border-left: 1px solid var(--ps--border);
}
.cp-subnav__anchor {
  text-align: left; padding: 7px 10px; border: 0; border-radius: var(--ps--radius-sm);
  background: transparent; color: var(--ps--fg); font: 400 13px var(--ps--font-sans);
  cursor: pointer; transition: background var(--ps--duration-fast), color var(--ps--duration-fast);
}
.cp-subnav__anchor:hover { background: var(--ps--bg-soft); color: var(--ps--primary); }
/* Auswahl-Zustand: siehe shell.css, Abschnitt „Auswahl-Zustand“ (eine Quelle). */

.ps-profile__row { display: flex; align-items: center; gap: 18px; margin-bottom: 18px; }
.ps-profile__avatar {
  width: 72px; height: 72px; border-radius: 50%; flex: 0 0 auto;
  background: var(--ps--bg-inverse); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 24px;
  background-size: cover; background-position: center;
}
.ps-profile__keys { display: flex; flex-direction: column; gap: 8px; }
.ps-profile__key { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--ps--border); border-radius: 10px; }
.ps-profile__key i { width: 18px; height: 18px; color: var(--ps--primary); flex: 0 0 auto; }
.ps-profile__nokeys { font-size: 13px; color: var(--ps--neutral-500); padding: 8px 0; }

/* ---- Benachrichtigungseinstellungen (Profil) ---- */
.ps-notifset__master { display: flex; align-items: center; gap: 10px; margin: 4px 0 14px; font-size: 13px; font-weight: 700; cursor: pointer; }
.ps-notifset__table { width: 100%; max-width: 640px; border-collapse: collapse; }
.ps-notifset__table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ps--fg-muted); padding: 6px 10px; border-bottom: 1px solid var(--ps--border); }
.ps-notifset__table th:nth-child(n+2), .ps-notifset__table td:nth-child(n+2) { text-align: center; width: 72px; }
.ps-notifset__table td { padding: 10px; border-bottom: 1px solid var(--ps--border); vertical-align: top; }
.ps-notifset__label { font-size: 13px; font-weight: 700; color: var(--ps--fg); }
.ps-notifset__desc { font-size: 12px; color: var(--ps--fg-muted); }

/* Reduzierte Bewegung: Shell-Animationen aus (Tooltip/Popover/Menü-Einblendung,
   Live-Puls, Lade-Spinner). Der Spinner-Zustand bleibt ohne Drehung erkennbar —
   der Zeilentext zeigt „Prüfung läuft…". */
@media (prefers-reduced-motion: reduce) {
  .ps-tip,
  .ps-popover--float,
  .ps-select__menu,
  .bd-itemdd__panel,
  .ps-sys-dot--live,
  .ps-sys-spin { animation: none; }
}

/* ============================================================
   Hilfe-Bereich (Spec docs/superpowers/specs/2026-07-17-hilfe-bereich-design.md)
   Studio-Chrome: kanonische Karten/Buttons bleiben ps-card/ps-btn.
   ============================================================ */
.ps-help__intro { color: var(--ps--neutral-500); margin: 0 0 20px; max-width: 640px; }
.ps-kbd {
    display: inline-block; min-width: 22px; padding: 2px 7px; text-align: center;
    border: 1px solid rgba(0, 0, 0, .16); border-bottom-width: 2px; border-radius: 6px;
    background: var(--ps--neutral-0); font-weight: 600; font-size: 12px; line-height: 1.5;
    font-family: inherit; color: var(--ps--fg);
}
.ps-help__keys { display: inline-flex; gap: 4px; align-items: center; white-space: nowrap; }
.ps-help__controls { display: flex; gap: 12px; align-items: center; margin: 0 0 20px; flex-wrap: wrap; }
.ps-help__seg { display: inline-flex; border: 1px solid rgba(0, 0, 0, .14); border-radius: 9px; overflow: hidden; }
.ps-help__segBtn { border: 0; background: var(--ps--neutral-0); padding: 9px 16px; font-weight: 700; font-size: 13px; cursor: pointer; color: var(--ps--fg); }
.ps-help__segBtn.is-active { background: var(--ps--primary); color: #fff; }
.ps-help__filter, .ps-help__search {
    height: 40px; border: 1px solid rgba(0, 0, 0, .14); border-radius: 9px;
    padding: 0 14px; font-size: 14px; min-width: 260px; background: var(--ps--neutral-0);
}
.ps-help__search { width: 100%; max-width: 560px; height: 46px; font-size: 15px; }
.ps-help__scope { margin-bottom: 16px; }
.ps-help__scopeH { font-size: 16px; margin: 0 0 10px; }
.ps-help__table { width: 100%; border-collapse: collapse; font-size: 14px; }
.ps-help__table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ps--neutral-500); padding: 6px 10px; border-bottom: 1px solid rgba(0, 0, 0, .08); }
.ps-help__table td { padding: 9px 10px; border-bottom: 1px solid rgba(0, 0, 0, .05); vertical-align: top; }
.ps-help__when { color: var(--ps--neutral-500); }
.ps-help__foot { color: var(--ps--neutral-500); font-size: 13px; margin-top: 16px; }

/* Anleitungen: Master-Detail */
.ps-help__split { display: grid; grid-template-columns: 300px 1fr; gap: 24px; align-items: start; }
@media (max-width: 900px) { .ps-help__split { grid-template-columns: 1fr; } }
.ps-help__list { display: flex; flex-direction: column; gap: 4px; }
.ps-help__groupH { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ps--neutral-500); margin: 14px 0 6px; }
.ps-help__item { display: block; width: 100%; text-align: left; border: 0; background: none; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.ps-help__item:hover { background: rgba(0, 0, 0, .04); }
/* Auswahl-Zustand: siehe shell.css, Abschnitt „Auswahl-Zustand“ (eine Quelle). */
.ps-help__itemT { display: block; font-weight: 700; font-size: 14px; color: var(--ps--fg); }
/* Eigene Schriftstärke, nicht geerbt: die Auswahl-Regel setzt 700 auf die
   Zeile, und die Unterzeile soll davon unberührt bleiben. */
.ps-help__itemSub { display: block; font-size: 12.5px; font-weight: 400; color: var(--ps--neutral-500); }
.ps-help__article h1 { font-size: 26px; margin: 0 0 4px; }
.ps-help__meta { display: flex; gap: 10px; align-items: center; color: var(--ps--neutral-500); font-size: 12.5px; margin-bottom: 18px; flex-wrap: wrap; }
.ps-help__badge { display: inline-block; padding: 2px 8px; border-radius: 999px; background: rgba(0, 0, 0, .07); font-size: 11.5px; font-weight: 700; }
.ps-help__p { margin: 0 0 12px; line-height: 1.6; max-width: 640px; }
.ps-help__step { display: flex; gap: 12px; margin: 0 0 12px; max-width: 640px; }
.ps-help__stepNum { flex: 0 0 26px; height: 26px; border-radius: 999px; background: var(--ps--primary); color: #fff; font-weight: 800; font-size: 13px; display: inline-flex; align-items: center; justify-content: center; }
.ps-help__stepBody { line-height: 1.6; }
.ps-help__note { border-left: 3px solid var(--ps--primary); background: rgba(0, 129, 93, .06); padding: 10px 14px; border-radius: 0 8px 8px 0; margin: 0 0 12px; max-width: 640px; line-height: 1.55; }
.ps-help__note--warn { border-left-color: var(--ps--warning); background: color-mix(in srgb, var(--ps--warning) 7%, transparent); }
.ps-help__link { color: var(--ps--primary); font-weight: 600; }
.ps-help__report { display: inline-block; margin-top: 20px; font-size: 12.5px; color: var(--ps--neutral-500); }

/* Überblick */
.ps-help__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; margin-top: 16px; }
.ps-help__tile { text-align: left; border: 1px solid rgba(0, 0, 0, .1); background: var(--ps--neutral-0); border-radius: 12px; padding: 16px; cursor: pointer; display: flex; gap: 12px; align-items: center; }
.ps-help__tile:hover { border-color: var(--ps--primary); }
.ps-help__tile i { width: 22px; height: 22px; color: var(--ps--primary); flex: 0 0 auto; }
.ps-help__tileT { font-weight: 700; font-size: 14px; display: block; }
.ps-help__tileSub { font-size: 12.5px; color: var(--ps--neutral-500); display: block; }
.ps-help__results { margin-top: 14px; display: flex; flex-direction: column; gap: 4px; max-width: 560px; }
.ps-help__resultH { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ps--neutral-500); margin: 10px 0 4px; }
.ps-help__cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; margin-top: 28px; }

/* Anleitungen: Karten-Übersicht + fokussierter Leser (Redesign) */
.ps-help__back {
    display: inline-flex; align-items: center; gap: 6px;
    color: var(--ps--primary); font-weight: 600; font-size: 14px;
    text-decoration: none; margin: 2px 0 18px;
}
.ps-help__back:hover { text-decoration: underline; }
.ps-help__catHead {
    display: flex; align-items: center; gap: 8px;
    font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--ps--neutral-500); margin: 28px 0 12px;
}
.ps-help__catHead:first-of-type { margin-top: 10px; }
.ps-help__catIcon { color: var(--ps--primary); }
.ps-help__catIcon svg, .ps-help__catIcon i { width: 16px; height: 16px; }
.ps-help__cardgrid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px;
}
.ps-help__card {
    display: flex; flex-direction: column; gap: 8px; padding: 18px;
    border: 1px solid rgba(0, 0, 0, .08); border-radius: 14px; background: var(--ps--neutral-0);
    text-decoration: none; color: inherit;
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.ps-help__card:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .09);
    border-color: rgba(0, 129, 93, .35);
}
.ps-help__card:focus-visible { outline: 2px solid var(--ps--primary); outline-offset: 2px; }
.ps-help__cardIcon {
    width: 38px; height: 38px; border-radius: 11px;
    background: color-mix(in srgb, var(--ps--primary) 10%, transparent); color: var(--ps--primary);
}
.ps-help__cardIcon svg, .ps-help__cardIcon i { width: 20px; height: 20px; }
.ps-help__cardT { font-weight: 700; font-size: 15px; color: var(--ps--fg); }
.ps-help__cardSub { font-size: 13px; color: var(--ps--neutral-500); line-height: 1.45; }
.ps-help__related { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.ps-help__relLink {
    display: inline-block; padding: 7px 12px; border-radius: 999px;
    border: 1px solid rgba(0, 0, 0, .12); background: var(--ps--neutral-0);
    font-size: 13px; font-weight: 600; color: var(--ps--primary); text-decoration: none;
}
.ps-help__relLink:hover { border-color: rgba(0, 129, 93, .45); background: rgba(0, 129, 93, .06); }

/* Tour-Engine: Spotlight-Overlay (z-300 — über den Modals z-200, unter
   Kontextmenü z-1000), Schritt-Karte, „Zeig mir wo"-Puls */
.ps-tour__blocker { position: fixed; inset: 0; z-index: 300; background: transparent; }
.ps-tour__spot {
    position: fixed; z-index: 300; border-radius: 10px; pointer-events: none;
    box-shadow: 0 0 0 9999px rgba(15, 23, 19, .45);
    transition: top .15s ease, left .15s ease, width .15s ease, height .15s ease;
}
.ps-tour__card {
    position: fixed; z-index: 301; width: 320px; max-width: calc(100vw - 24px);
    background: var(--ps--neutral-0); border-radius: 12px; padding: 16px 18px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, .28);
}
.ps-tour__title { font-size: 15px; font-weight: 800; margin: 0 0 6px; }
.ps-tour__body { font-size: 13.5px; line-height: 1.55; color: var(--ps--fg); margin: 0 0 14px; }
.ps-tour__foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ps-tour__count { font-size: 12px; color: var(--ps--neutral-500); margin-right: auto; }
.ps-tour__pulse {
    position: fixed; z-index: 300; border-radius: 10px; pointer-events: none;
    animation: psTourPulse 1s ease-in-out 3;
}
@keyframes psTourPulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(0, 129, 93, .9); }
    50% { box-shadow: 0 0 0 12px rgba(0, 129, 93, .2); }
}
.ps-help__tourHint { font-size: 12.5px; color: var(--ps--neutral-500); margin: 10px 0 0; }
.ps-help__startCard { margin-top: 20px; }
.ps-help__showme { height: 32px; font-size: 13px; padding: 0 12px; }
.ps-tour__srOnly {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* Individuelle Komponenten */
/* Liste im Komponenten-Bereich (StoryCustomComponents, Task 12) — Karten-Zeilen
   mit Name, Status-Badge, Aktionen. Nutzt ausschließlich die kanonischen
   .bx-btn-Klassen (siehe „Studio-Chrome-Buttons" oben) — keine eigenen
   Button-Styles. Die Status-Farben kommen aus den globalen Rollen
   --ps--success/--ps--warning (Signalton) bzw. --ps--*-fg (Text) — bis PS-88
   war es ein eigenes Paar --ps--status-live/--status-draft, wertgleich, aber
   nicht dunkelmodus-tauglich. */
.cc-list__head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 18px; }
.cc-list__head h2 { margin: 0; font-size: 20px; font-weight: 900; color: var(--ps--fg); letter-spacing: -0.01em; }
.cc-list__empty { font-size: 14px; color: var(--ps--neutral-500); margin: 0; }
.cc-list__items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.cc-list__item {
    display: flex; align-items: center; gap: 14px; padding: 14px 16px;
    background: var(--ps--neutral-0, #fff); border: 1px solid var(--ps--border); border-radius: 12px;
}
.cc-list__name { flex: 1; font-weight: 700; font-size: 14.5px; color: var(--ps--fg); }
.cc-list__actions { display: flex; gap: 8px; }
.cc-badge {
    display: inline-flex; align-items: center; font-size: 11px; font-weight: 800;
    letter-spacing: 0.03em; text-transform: uppercase; padding: 4px 10px; border-radius: 999px;
    white-space: nowrap;
}
.cc-badge--draft { color: var(--ps--neutral-500); background: var(--ps--bg-soft); }
.cc-badge--dirty { color: var(--ps--warning-fg); background: color-mix(in srgb, var(--ps--warning) 12%, var(--ps--neutral-0, #fff)); }
.cc-badge--live { color: var(--ps--success-fg); background: color-mix(in srgb, var(--ps--success) 12%, var(--ps--neutral-0, #fff)); }

/* Werkstatt-Workspace (CustomComponentWorkshop, Task 13) — seit
   Werkstatt-Redesign Task 1 EINGEBETTET im Shell-Content-Bereich
   (.ps-content--workshop unten, app-shell.jsx), kein Vollflächen-Overlay mehr
   (siehe design_handoff_werkstatt_redesign/README.md §1
   „Shell-Einbettung"). .cc-workshop bleibt eine flex column, füllt aber nur
   noch ihren Container statt der gesamten Viewport-Fläche. Zwei Spalten:
   links Tab-Leiste + Editor, rechts Vorschau-Platzhalter + Meta-Panels
   (scrollbar). Buttons bleiben ausschließlich .bx-btn (siehe
   „Studio-Chrome-Buttons" oben) — keine eigenen Button-Styles. */
.cc-workshop {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column;
    background: var(--ps--neutral-50); font-family: var(--ps--font-sans);
}
/* Werkstatt-Kopf (Werkstatt-Redesign Task 2, README.md §2): 60px, weiß,
   Rand unten #e3e8e6, padding 0 20px, gap 14px — ersetzt den früheren
   generischen 14px/22px-Kopf. .cc-workshop__head/.cc-workshop__name/
   .cc-workshop__flash bleiben (existierende Tests + workshop-embedding.
   test.jsx greifen darauf zu), bekommen hier aber komplett neue Optik; alle
   neuen Kopf-Bausteine leben unter dem cc-wshead__*-Namespace
   (views/workshop/workshop-header.jsx). */
.cc-workshop__head {
    flex: 0 0 auto; height: 60px; display: flex; align-items: center; gap: 14px;
    padding: 0 20px; background: var(--ps--neutral-0, #fff);
    border-bottom: 1px solid var(--ps--border);
}
.cc-wshead__iconbtn {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ps--border); border-radius: 9px;
    background: var(--ps--neutral-0, #fff); color: var(--ps--fg); cursor: pointer;
}
.cc-wshead__iconbtn:hover { background: var(--ps--neutral-50); }
.cc-wshead__iconbtn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ps--focus-ring); }
.cc-wshead__back { width: 34px; height: 34px; }
.cc-wshead__rollback { width: 36px; height: 36px; }
.cc-wshead__title { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; }
.cc-wshead__crumb {
    flex: 0 0 auto; font: 400 12.5px var(--ps--font-sans); color: var(--ps--neutral-400);
    white-space: nowrap;
}
.cc-workshop__name {
    flex: 1 1 auto; min-width: 0; height: 32px; padding: 0 8px;
    border: none; border-radius: 6px; background: transparent;
    font: 900 15.5px var(--ps--font-sans); color: var(--ps--fg); outline: none;
}
.cc-workshop__name:focus {
    background: var(--ps--neutral-100);
    box-shadow: 0 0 0 3px rgba(0, 129, 93, 0.25);
}
/* Status-Pill (ersetzt den alten .cc-badge im Kopf) — teilt sich die
   statusBadge()-Entscheidung/Klassen (cc-badge--draft/dirty/live) mit der
   Listenansicht (custom-components.jsx: die dortige .cc-badge bleibt
   unverändert), bekommt hier aber über die spezifischere
   .cc-wshead-pill.cc-badge--*-Kombination eine eigenständige Optik. */
.cc-wshead-pill {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 11px; border-radius: 999px;
    font: 800 11px var(--ps--font-sans); text-transform: uppercase; letter-spacing: 0.02em;
    white-space: nowrap;
}
.cc-wshead-pill__dot { flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.cc-wshead-pill.cc-badge--draft { color: var(--ps--neutral-500); background: var(--ps--neutral-100); }
.cc-wshead-pill.cc-badge--dirty { color: var(--ps--warning-fg); background: var(--ps--warning-soft); }
.cc-wshead-pill.cc-badge--dirty .cc-wshead-pill__dot { background: var(--ps--warning); }
.cc-wshead-pill.cc-badge--live { color: var(--ps--brand); background: var(--ps--brand-soft); }
/* Transiente Erfolgs-Bestätigung nach Veröffentlichen/Wiederherstellen. */
.cc-workshop__flash {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
    padding: 5px 11px; border-radius: 999px;
    font: 800 11px var(--ps--font-sans);
    color: var(--ps--brand); background: var(--ps--brand-soft);
    animation: cc-flash-in 160ms ease-out;
}
@keyframes cc-flash-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
/* Code|Visuell Segmented-Control (ersetzt die frühere .cc-workshop__modetoggle-
   Optik — Klassenname mitgezogen auf cc-wshead__toggle, kein Test hing am
   alten Namen). */
.cc-wshead__toggle {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 2px;
    background: var(--ps--neutral-100); border-radius: 10px; padding: 3px;
}
.cc-wshead__toggle button {
    height: 30px; padding: 0 14px; border: none; border-radius: 8px; background: transparent;
    font: 700 12.5px var(--ps--font-sans); color: var(--ps--neutral-500); cursor: pointer;
}
.cc-wshead__toggle button.is-active {
    background: var(--ps--neutral-0, #fff); color: var(--ps--brand-dark);
    box-shadow: 0 1px 3px rgba(31, 71, 60, 0.14);
}
.cc-wshead__autosave { flex: 0 0 auto; font: 400 12px var(--ps--font-sans); color: var(--ps--neutral-400); white-space: nowrap; }
.cc-wshead__divider { flex: 0 0 auto; width: 1px; height: 28px; background: var(--ps--border); }
/* Veröffentlichen bleibt der kanonische .bx-btn--primary (Farbe/Schatten/
   Schrift, siehe „Studio-Chrome-Buttons" oben) — nur Höhe/Innenabstand
   werden im 60px-Kopf auf die Spec-Maße (36px) verengt; 3-Klassen-Selektor
   hält das absichtlich lokal statt den kanonischen Regelsatz selbst
   anzufassen (AGENTS.md „Unified studio-chrome UI"). */
.cc-workshop__head .bx-btn.cc-wshead__publish { flex: 0 0 auto; height: 36px; padding: 0 16px; gap: 6px; }
.cc-workshop__head .bx-btn.cc-wshead__publish:disabled {
    opacity: .45; background: var(--ps--primary); color: var(--ps--primary-fg);
    cursor: not-allowed; box-shadow: none;
}
@media (max-width: 1279px) {
    .cc-wshead__crumb, .cc-wshead-pill__text, .cc-wshead__autosave { display: none; }
}

.cc-workshop__body { flex: 1 1 auto; display: flex; min-height: 0; }
.cc-workshop__code { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; padding: 16px 0 16px 22px; }
/* Desktop/Mobil-Umschalter (Vorschau-Header, workshop-preview.jsx) — eigene,
   helle Segmented-Control-Sprache. Bewusst NICHT mehr mit den Editor-Tabs
   unten zusammengelegt (Werkstatt-Redesign Task 3 macht nur die Editor-Tabs
   dunkel; der Vorschau-Umschalter bleibt Teil der hellen rechten Spalte). */
.cc-workshop__viewport { flex: 0 0 auto; display: flex; gap: 4px; margin-bottom: 10px; }
.cc-workshop__viewport button {
    height: 32px; padding: 0 16px; border: 1px solid var(--ps--border); border-bottom: 0;
    border-radius: 8px 8px 0 0; background: var(--ps--bg-soft); color: var(--ps--neutral-500);
    font: 700 12.5px var(--ps--font-sans); letter-spacing: 0.02em; cursor: pointer;
}
.cc-workshop__viewport button.is-active { background: var(--ps--neutral-0, #fff); color: var(--ps--fg); border-color: var(--ps--border-strong); }

/* ALLE Farbliterale von hier bis zur Statuszeile bleiben literal (PS-88): dieser
   Bereich ist eine der drei dokumentierten Dunkelmodus-Ausnahmen (siehe Kopf von
   darkmode.css). Er ist IMMER dunkel — im hellen Modus genauso. Ein Rollen-Token
   würde ihn im hellen Modus aufhellen und damit genau die Absicht zerstören.
   Dasselbe gilt für die Syntax- und Fehlertöne (#f2a6a0, #e3c878, #e88d67): das
   ist eine Editor-Palette, kein Oberflächen-Vorrat.

   Dunkler Code-Editor-Container (Werkstatt-Redesign Task 3, README §3
   "Code-Modus") — einziger dunkler Bereich der App. Wraps die Tab-Leiste
   (DOM, unten) + die CodeMirror-Fläche (editors/code-editor.jsx liefert ihr
   eigenes dunkles Theme inkl. Zeilennummern/Syntax/Aktivzeile — hier nur der
   Container-Rahmen + die HTML/CSS/JS-Tab-Leiste drumherum). */
.cc-editor {
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
    background: var(--ps--editor-bg, #0e1713); border-radius: 12px;
    box-shadow: 0 4px 16px rgba(13, 23, 18, 0.28); overflow: hidden;
}
.cc-editor__tabs {
    flex: 0 0 auto; display: flex; align-items: flex-end; gap: 4px;
    padding: 8px 10px 0; background: var(--ps--editor-chrome, #132019);
}
.cc-editor__tablist { flex: 1 1 auto; display: flex; gap: 4px; min-width: 0; }
.cc-editor__tab {
    height: 34px; padding: 0 14px; display: inline-flex; align-items: center; gap: 7px;
    border: none; border-radius: 8px 8px 0 0; background: transparent;
    font: 700 12px var(--ps--font-sans); color: var(--ps--editor-muted, #7e938a); cursor: pointer;
}
.cc-editor__tab.is-active { background: var(--ps--editor-bg, #0e1713); color: #e8f0ec; }
.cc-editor__tab-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; }
/* Editor-Chrome-Chips rechts in der Tab-Leiste — gemeinsamer Look über
   `.cc-editor__tool`: „Formatieren" (richtet Struktur + Einrückung des aktiven
   Tabs aus, editors/format-code.js) und „Suchen ⌘F" (öffnet CodeMirrors eigenes
   Suchpanel, openSearchPanel, wired in custom-component-workshop.jsx). */
.cc-editor__tool {
    flex: 0 0 auto; align-self: center; height: 26px; margin-bottom: 6px; padding: 0 10px;
    display: inline-flex; align-items: center; gap: 5px;
    border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 7px; background: transparent;
    font: 700 11px var(--ps--font-sans); color: var(--ps--editor-muted-2, #9fb3aa); cursor: pointer;
    white-space: nowrap;
}
.cc-editor__tool:hover:not([disabled]) { background: rgba(255, 255, 255, 0.06); }
.cc-editor__tool[disabled] { opacity: 0.55; cursor: default; }
.cc-editor__tool-ic { flex: 0 0 auto; opacity: 0.85; }
.cc-editor__search kbd {
    font: 700 10px var(--ps--font-mono, monospace); padding: 1px 4px; border-radius: 4px;
    background: rgba(255, 255, 255, 0.08); color: var(--ps--editor-muted-2, #9fb3aa);
}
/* Dezente Meldung, wenn „Formatieren" den (mitten im Bearbeiten evtl. noch
   fehlerhaften) Quelltext nicht parsen kann — der Code bleibt dann unangetastet. */
.cc-editor__note {
    flex: 0 0 auto; padding: 7px 14px;
    background: var(--ps--editor-chrome, #132019);
    border-top: 1px solid rgba(227, 200, 120, 0.28);
    font: 600 11px var(--ps--font-sans); color: #e3c878;
}
.cc-editor .cc-code-editor { flex: 1 1 auto; min-height: 0; }
.cc-editor .cc-code-editor .cm-editor { height: 100%; }
.cc-editor .cc-code-editor .cm-scroller { overflow: auto; }
/* Scrollbalken nur beim Scrollen (wie Strukturbaum/Inspektor/Viewport) — heller
   Daumen für die dunkle Editor-Fläche; `.is-scrolling` wird von editors/
   code-editor.jsx auf dem Scroller (view.scrollDOM) gesetzt und nach kurzer
   Ruhe wieder entfernt. */
.cc-code-editor .cm-scroller { scrollbar-width: thin; scrollbar-color: transparent transparent; }
.cc-code-editor .cm-scroller.is-scrolling { scrollbar-color: rgba(255, 255, 255, 0.28) transparent; }
.cc-code-editor .cm-scroller::-webkit-scrollbar { width: 10px; height: 10px; }
.cc-code-editor .cm-scroller::-webkit-scrollbar-track { background: transparent; }
.cc-code-editor .cm-scroller::-webkit-scrollbar-thumb { background-color: transparent; border-radius: 6px; border: 2px solid transparent; }
.cc-code-editor .cm-scroller.is-scrolling::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.22); background-clip: padding-box; }
.cc-code-editor .cm-scroller::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.4); background-clip: padding-box; }
/* Lesbare Mehrfach-Auswahl (v0.124.1): das Design-System setzt GLOBAL
   `::selection { background: cyan; color: dunkel }` (colors_and_type.css —
   für die hellen Website-Flächen gedacht, via studio.blade.php app-weit
   geladen). CodeMirror unterdrückt in .cm-line zwar den nativen Auswahl-
   HINTERGRUND (drawSelection zeichnet ihn als eigene Ebene HINTER dem Text),
   aber die globale `color`-Regel griff weiter durch — selektierter Code
   verlor dadurch alle Syntaxfarben und wurde einheitlich dunkel/unlesbar.
   WICHTIG: `color: currentColor`, NICHT `inherit` — seit der „highlight
   inheritance" (Chrome ~105+, CSS Pseudo-4) erbt ::selection nicht vom
   Ursprungs-Element, sondern vom ::selection des ELTERN-Elements; `inherit`
   liefe die Kette also bis zur globalen Regel hoch und landete wieder bei
   deren dunkler Farbe (No-op). `currentColor` ist in Highlight-Pseudos
   definiert als „Farbe des Ursprungs-Elements" — sprich: der Token-Span
   behält seine Syntaxfarbe auch in der Auswahl; sichtbar ist nur CodeMirrors
   gezeichnete Selektions-Ebene (Steel-Ton, editors/code-editor.jsx darkTheme).
   Bewusst auf .cm-line gescoped (wie CodeMirrors eigene Unterdrückung) — das
   Eingabefeld des Suchpanels behält die normale Auswahl-Darstellung. */
.cc-code-editor .cm-line::selection,
.cc-code-editor .cm-line ::selection { background: transparent; color: currentColor; }

/* Fehlerzeile (Werkstatt-Redesign Task 4, README §3 "Fehlerzeile") — Deko-
   Klassen, die editors/code-editor.jsx's `errorLinesField` auf die
   betroffene(n) Zeile(n) setzt (`cm-errorLine` = Decoration.line,
   `cm-errorSquiggle` = Decoration.mark). Bewusst hier statt im
   EditorView.theme() (darkTheme) verdrahtet — anders als die Token-Farben
   oben ist das reine DOM-Klasse + globales Stylesheet, kein CM-Theme-Modul. */
.cc-code-editor .cm-errorLine {
    background: rgba(220, 38, 38, 0.12);
    box-shadow: inset 2px 0 0 #dc2626;
}
.cc-code-editor .cm-errorSquiggle {
    text-decoration: underline wavy #dc2626;
    text-decoration-skip-ink: none;
}
/* Inline-Fehlerpanel unter dem Editor — nur gerendert, wenn der aktive Tab
   Fehler trägt (custom-component-workshop.jsx: activeErrors). */
.cc-editor__errors {
    flex: 0 0 auto; padding: 10px 14px; display: flex; flex-direction: column; gap: 6px;
    background: #2a1a17; border-top: 1px solid rgba(220, 38, 38, 0.4);
}
.cc-editor__errors-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cc-editor__errors-text { font: 400 12px var(--ps--font-sans); color: #f2a6a0; }
.cc-editor__errors-jump {
    flex: 0 0 auto; border: none; background: transparent; padding: 0;
    font: 700 11.5px var(--ps--font-sans); color: #f2a6a0; text-decoration: underline; cursor: pointer;
}
.cc-editor__errors-note { font: 400 11px var(--ps--font-sans); color: var(--ps--editor-muted-2, #9fb3aa); margin: 2px 0 0; }
/* Info-Chips (violett) — je Tab ein Hinweis, was mit dem Quelltext beim
   Speichern/Ausführen passiert. */
.cc-editor__chips {
    flex: 0 0 auto; padding: 8px 14px; background: var(--ps--editor-chrome, #132019);
}
.cc-editor__chip {
    display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px;
    background: var(--ps--editor-chip-bg, #1a2b22); border: 1px solid rgba(183, 157, 255, 0.35);
    font: 400 11px var(--ps--font-sans); color: var(--ps--editor-syntax-token, #b79dff);
}
.cc-editor__chip code { font: 700 11px var(--ps--font-mono, monospace); }
/* Statuszeile — links Cursorposition + Tab-Quelle, rechts globale
   Validierungslage (Publish-Sperre gilt tab-unabhängig). */
.cc-editor__statusline {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
    padding: 6px 14px; background: var(--ps--editor-chrome, #132019);
    font-size: 11px; color: var(--ps--editor-muted, #7e938a);
}
.cc-editor__statusline-pos { font: 400 11px var(--ps--font-sans); color: var(--ps--editor-muted, #7e938a); }
.cc-editor__statusline-validity { font: 700 11px var(--ps--font-sans); }
.cc-editor__statusline-validity.is-ok { color: var(--ps--editor-syntax-tag, #56c890); }
.cc-editor__statusline-validity.is-error { color: #f2a6a0; }

.cc-workshop__meta {
    flex: 0 0 400px; max-width: 40vw; display: flex; flex-direction: column; gap: 14px;
    padding: 16px 22px 16px 16px; overflow-y: auto; border-left: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff);
}
.cc-workshop__preview {
    flex: 0 0 auto; min-height: 160px; border: 1px dashed var(--ps--border-strong);
    border-radius: var(--ps--radius-md); background: var(--ps--bg-soft);
}

/* Werkstatt-Redesign Task 1 fix (Critical, review-confirmed): WorkshopPreview's
   iframe (views/visual/workshop-preview.jsx, both the Code-Modus branch here
   and the Visual-Modus `.cc-visual__stage` branch below) now also carries
   `.bd-iframe` purely so builder/resize-handle.jsx's own drag mechanism —
   which sets pointer-events:none on every `.bd-iframe` in the document while
   dragging — covers it too (without the class, a real mouse drag crossing
   into the preview iframe was swallowed by the iframe's own document and the
   resize never committed). `.bd-iframe`'s border/width rules (app.css) never
   win here — this component's own inline styles are more specific — but its
   `background: var(--ps--neutral-0)` would show through since neither branch
   sets an inline background; restore the previous (transparent) look in
   both mount points so the class buys ONLY the pointer-events behavior. */
.cc-workshop__preview .bd-iframe,
.cc-visual__stage .bd-iframe {
    background: transparent;
}

/* ===========================================================
   Rechte Spalte, Code-Modus (Werkstatt-Redesign Task 5, README §3):
   Live-Vorschau/Inhalts-Schema/Eigenschaften/Regeln/Prüfung sind alle
   .cc-card — ein weißes 12px-Karten-Grundgerüst mit festem Kopf (Titel +
   optionaler Zähl-Pill + optionale Kopf-Aktion rechts). Ersetzt das frühere
   ausklappbare .cc-panel (das GANZE Panel war ein <details>) — jetzt bleibt
   der Karten-Kopf immer sichtbar, nur die einzelne Feld-/Prop-Zeile ist ein
   <details> (.cc-field-row, s. u.).
   =========================================================== */
.cc-card {
    background: var(--ps--neutral-0, #fff); border: 1px solid var(--ps--border);
    border-radius: 12px; flex: 0 0 auto;
}
.cc-card__head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--ps--border); }
.cc-card__title { margin: 0; font: 800 12.5px var(--ps--font-sans); color: var(--ps--fg); }
.cc-card__spacer { flex: 1 1 auto; }
.cc-card__pill {
    flex: 0 0 auto; font: 700 10.5px var(--ps--font-sans); border-radius: 999px; padding: 2px 8px;
}
.cc-card__pill--brand { color: var(--ps--brand); background: var(--ps--brand-soft); }
.cc-card__pill--neutral { color: var(--ps--neutral-500); background: var(--ps--neutral-100); }
/* Spec-driven exception to the canonical .bx-btn look (AGENTS.md "Unified
   studio-chrome UI (buttons)") — README §3 explicitly calls for a small
   green "soft" chip here, distinct from the app-wide primary/secondary
   button chrome; see the code comment at its call sites. */
.cc-card__addbtn {
    display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px; border: none;
    border-radius: 7px; background: var(--ps--brand-soft); color: var(--ps--brand);
    font: 700 11.5px var(--ps--font-sans); cursor: pointer;
}
.cc-card__addbtn:hover { background: color-mix(in srgb, var(--ps--brand) 18%, var(--ps--brand-soft)); }
.cc-card__body { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 6px; }

/* Live-Vorschau-Karte: WorkshopPreview bringt ihr eigenes .cc-workshop__preview
   mit (geteilt mit dem Visual-Modus-Canvas, s. dort weiter unten) — INNERHALB
   dieser Karte wird dessen eigener Rahmen/Hintergrund neutralisiert, die Karte
   selbst übernimmt Rahmen/Radius/Hintergrund. Bewusst nur unter .cc-card--preview
   scoped, damit der Visual-Modus-Canvas (.cc-visual__preview .cc-workshop__preview)
   unangetastet bleibt (aus dem Scope dieses Tasks). */
.cc-card--preview .cc-workshop__preview {
    border: none; border-radius: 0; background: transparent; min-height: 0;
    padding: 10px 12px 12px;
}

/* Feld-/Prop-Zeilen (Inhalts-Schema- + Eigenschaften-Karte): ein <details>
   pro Zeile — die Summary ist der immer sichtbare, kompakte Zeilen-Kopf
   (Drag-Handle, Typ-Chip, Feld-/Prop-ID mono, Meta, Chevron); ein Klick
   öffnet/schließt den Body mit den bestehenden Editoren (unverändertes
   patchDef-Wiring, siehe custom-component-workshop.jsx). */
.cc-field-row { border: 1px solid var(--ps--border); border-radius: 9px; background: var(--ps--neutral-50); }
.cc-field-row__summary { display: flex; align-items: center; gap: 9px; padding: 8px 10px; cursor: pointer; list-style: none; }
.cc-field-row__summary::-webkit-details-marker { display: none; }
.cc-field-row__handle { flex: 0 0 auto; color: var(--ps--border-strong); display: inline-flex; }
.cc-field-row__chip {
    flex: 0 0 auto; width: 24px; height: 24px; border-radius: 7px;
    display: inline-flex; align-items: center; justify-content: center; font: 900 11px var(--ps--font-sans);
}
.cc-field-row__id {
    font: 700 12px var(--ps--font-mono); color: var(--ps--fg);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cc-field-row__meta { margin-left: auto; flex: 0 0 auto; font-size: 11.5px; color: var(--ps--neutral-400); white-space: nowrap; padding-left: 8px; }
.cc-field-row__chevron { flex: 0 0 auto; color: var(--ps--neutral-400); transition: transform 0.12s var(--ps--ease-standard); }
.cc-field-row[open] > .cc-field-row__summary .cc-field-row__chevron { transform: rotate(90deg); }
.cc-field-row__body {
    display: flex; flex-direction: column; gap: 6px;
    padding: 8px 10px 10px; border-top: 1px dashed var(--ps--border);
}
.cc-field-row__body-row { display: flex; align-items: center; gap: 6px; }
.cc-field-row__body-row input[type="text"], .cc-field-row__body-row input:not([type]), .cc-field-row__body-row select {
    flex: 1 1 0; min-width: 0; height: 30px; padding: 0 8px;
    border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm);
    font: 400 12.5px var(--ps--font-sans); color: var(--ps--fg); background: var(--ps--neutral-0); outline: none;
}
.cc-field-row__body-row input:focus, .cc-field-row__body-row select:focus {
    border-color: var(--ps--primary); box-shadow: 0 0 0 2px var(--ps--focus-ring);
}
.cc-field-row__body-row select { flex: 0 1 110px; cursor: pointer; }
.cc-field-row__sub { margin: 2px 0; padding-left: 10px; border-left: 2px solid var(--ps--border); display: flex; flex-direction: column; gap: 6px; }
.cc-field-row__note { margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--ps--fg-subtle); }
.cc-field-row__note code { font-size: 11px; }

/* Repeater-Zeile (schema.items) — gestrichelt, violette „Repeater"-Pill. */
.cc-field-row--repeater { border-style: dashed; border-color: var(--ps--border-strong); background: transparent; }
.cc-field-row__pill--repeater {
    flex: 0 0 auto; font: 700 10.5px var(--ps--font-sans); color: var(--ps--cms);
    background: var(--ps--cms-soft); border-radius: 999px; padding: 2px 8px;
}
.cc-field-row__addrepeater {
    display: flex; align-items: center; gap: 9px; padding: 8px 10px; width: 100%;
    border: 1px dashed var(--ps--border-strong); border-radius: 9px; background: transparent;
    color: var(--ps--neutral-500); font: 700 12px var(--ps--font-sans); cursor: pointer;
}
.cc-field-row__addrepeater:disabled { opacity: 0.5; cursor: not-allowed; }

/* Regeln-Karte: Platzierungs-Select + Toggle-Switches statt Checkboxen. */
.cc-rules__field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 4px; }
.cc-rules__label { font: 700 11px var(--ps--font-sans); color: var(--ps--neutral-500); }
.cc-rules__field select { height: 30px; padding: 0 8px; border: 1px solid var(--ps--border-strong); border-radius: var(--ps--radius-sm); font: 400 12.5px var(--ps--font-sans); }
.cc-rules__row { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--ps--neutral-600); margin: 2px 0; }
.cc-rules__row.is-disabled { opacity: 0.55; }
.cc-rules__warn { flex: 0 0 auto; color: var(--ps--warning); display: inline-flex; }

/* Toggle-Switch (34×19, Task 5) — an var(--ps--brand), aus #ccd4cf/
   var(--ps--border-strong). Der <input type="checkbox"> bleibt der einzige
   Zustandsträger (dieselbe Track/Thumb-Geschwister-Technik wie .ps-dc__switch
   weiter oben), Track/Thumb sind rein optisch. */
.cc-toggle { position: relative; display: inline-flex; flex: 0 0 auto; width: 34px; height: 19px; }
.cc-toggle input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.cc-toggle input:disabled { cursor: not-allowed; }
.cc-toggle__track {
    position: absolute; inset: 0; border-radius: 999px; background: var(--ps--border-strong);
    transition: background var(--ps--duration-base) var(--ps--ease-standard); pointer-events: none;
}
.cc-toggle__thumb {
    position: absolute; top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%;
    background: #fff; box-shadow: var(--ps--shadow-sm); transition: transform var(--ps--duration-base) var(--ps--ease-standard);
}
.cc-toggle input:checked ~ .cc-toggle__track { background: var(--ps--brand); }
.cc-toggle input:checked ~ .cc-toggle__track .cc-toggle__thumb { transform: translateX(15px); }
.cc-toggle input:focus-visible ~ .cc-toggle__track { box-shadow: 0 0 0 3px var(--ps--focus-ring); }

/* Prüfung-Karte: OK-Zeile grün, Fehler-/Warn-Boxen als Soft-Boxen mit
   optionalem „Zur Zeile springen"-Link (Task 4 carry-over: jumpToLine). */
.cc-check__ok { display: flex; align-items: center; gap: 8px; font: 700 12px var(--ps--font-sans); color: var(--ps--brand); }
.cc-check__list { display: flex; flex-direction: column; gap: 6px; }
.cc-check__item { display: flex; align-items: flex-start; gap: 8px; padding: 9px 11px; border-radius: 9px; font: 600 12px var(--ps--font-sans); line-height: 1.5; }
.cc-check__item--error { background: var(--ps--danger-soft); color: var(--ps--danger-fg); }
.cc-check__item--warn { background: var(--ps--warning-soft); color: var(--ps--warning-fg); }
.cc-check__icon { flex: 0 0 auto; margin-top: 1px; }
.cc-check__jump { border: none; background: none; padding: 0; margin: 0; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }

/* Werkstatt-Redesign Task 7 (README §5 "Dialoge") — conflict (409) +
   rollback-confirmation dialogs (views/workshop/workshop-dialogs.jsx). Own
   `.cc-dialog*` chrome rather than the generic `.cp-modal*` (app.css): the
   handoff calls for specific values (rgba(13,23,18,.45) backdrop, 14px
   radius, the 0 24px 64px shadow, a 180ms cubic-bezier(.16,1,.3,1) +
   translateY(8px) entrance) that diverge from the app-wide modal defaults —
   deliberately its own section, not a `.cp-modal` variant. */
.cc-dialog__back {
    position: fixed; inset: 0; z-index: 400;
    background: rgba(13, 23, 18, 0.45);
    display: flex; align-items: center; justify-content: center;
    padding: var(--ps--space-5);
    animation: cc-dialog-fade 120ms ease;
}
@keyframes cc-dialog-fade { from { opacity: 0; } to { opacity: 1; } }
.cc-dialog {
    width: 100%; max-width: 460px;
    background: var(--ps--neutral-0, #fff);
    border-radius: 14px;
    box-shadow: 0 24px 64px rgba(13, 23, 18, 0.35);
    padding: 24px 26px;
    animation: cc-dialog-in 180ms cubic-bezier(0.16, 1, 0.3, 1);
}
.cc-dialog--rollback { max-width: 440px; }
@keyframes cc-dialog-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.cc-dialog__head { display: flex; align-items: center; gap: 10px; }
.cc-dialog__icon {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: 10px;
}
.cc-dialog__icon--warn { background: var(--ps--warning-soft); color: var(--ps--warning); }
.cc-dialog__icon--brand { background: var(--ps--brand-soft); color: var(--ps--brand); }
.cc-dialog__title { margin: 0; font: 900 16px var(--ps--font-sans); color: var(--ps--fg); }
.cc-dialog__sub { margin: 2px 0 0; font-size: 12.5px; color: var(--ps--neutral-500); }
.cc-dialog__info {
    margin-top: 14px; padding: 10px 12px; border-radius: 9px;
    background: var(--ps--neutral-50); font-size: 12px; color: var(--ps--neutral-600); line-height: 1.55;
}
.cc-dialog__text { margin: 12px 0 0; font-size: 13px; color: var(--ps--neutral-600); line-height: 1.6; }
.cc-dialog__foot { display: flex; gap: 8px; margin-top: 18px; justify-content: flex-end; }

/* Neue-Komponente-Dialog (CustomComponentCreateDialog) + Kopieren-Zielprojekt-
   Dialog (CopyToDialog, views/custom-components.jsx) — beide auf dem
   generischen .cp-modal/.cp-modal__* Baukasten (app.css), keine eigenen
   Button-/Modal-Grundstyles. Nur die Platzierungs-Auswahl (Segmented-Radios +
   Checkbox-Zeilen) ist hier neu, mit einer eigenen, aber analogen
   Zeilen-Grammatik zur Regeln-Karte der Werkstatt (.cc-rules__row). */
.cc-create__rules { margin-top: 4px; }
.cc-create__label {
    display: block; font-size: 12.5px; font-weight: 700; color: var(--ps--neutral-600);
    margin-bottom: 6px;
}
.cc-create__kind { display: flex; gap: 8px; margin-bottom: 10px; }
.cc-create__kind label {
    flex: 1; display: flex; align-items: center; gap: 8px; font-size: 13px;
    padding: 8px 12px; border: 1px solid var(--ps--border); border-radius: var(--ps--radius-sm, 8px);
    cursor: pointer; color: var(--ps--neutral-600);
}
.cc-create__kind label.is-active {
    border-color: var(--ps--primary); color: var(--ps--fg); font-weight: 700;
    background: color-mix(in srgb, var(--ps--primary) 6%, var(--ps--neutral-0, #fff));
}
.cc-create__check {
    display: flex; align-items: center; gap: 8px; font-size: 12.5px;
    color: var(--ps--neutral-600); margin: 6px 0;
}
.cc-create__check.is-disabled { opacity: 0.5; }

/* Kopieren-Zielprojekt-Dialog: einfache auswählbare Liste, gleiche
   Zeilen-Optik wie die Vorlagenwahl in views/collection-create-dialog.jsx. */
.cc-copy__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.cc-copy__list label {
    display: flex; align-items: center; gap: 10px; padding: 8px 12px;
    border: 1px solid var(--ps--border); border-radius: var(--ps--radius-sm, 8px); cursor: pointer;
}
.cc-copy__list label.is-active {
    border-color: var(--ps--primary); font-weight: 700;
    background: color-mix(in srgb, var(--ps--primary) 6%, var(--ps--neutral-0, #fff));
}

/* Visual-Modus (Task 4, Individuelle Komponenten v2 „Visual Builder",
   VisualMode in views/visual/visual-mode.jsx) — ersetzt im Werkstatt-Kopf
   umgeschaltet Code-Spalte + Meta-Aside komplett durch eine Dreispalten-
   Ansicht: Struktur-Baum | Vorschau (1fr) | Inspector-Slot (Task 5 füllt
   ihn). Teilt sich .cc-workshop__body als Höhen-Kontext, daher dasselbe
   min-height:0-Grundregel wie die Code-Spalte oben.
   Werkstatt-Redesign Task 1 (Resizable Panels): die drei Spalten sind ein
   Grid statt Flex, damit die beiden Außenspalten per Maus/Pfeiltasten
   verbreiterbar/verschmalbar sind (page-builder ResizeHandle, 1:1
   wiederverwendet — resources/js/builder/resize-handle.jsx). Die konkrete
   grid-template-columns kommt komplett inline aus dem React-State
   (treeW/inspW in visual-mode.jsx) — derselbe Aufbau wie .bd-shell unten
   (Builder-Shell) für die Spaltenbreiten des Page-Builders.
   Fix round (final review Important I1, popover clipping): position:relative
   was added here so .cc-elpanel (below) — now mounted as a DIRECT CHILD of
   THIS shell instead of inside .cc-visual__tree, see that rule's own comment
   — anchors to the shell itself. A grid container's OUT-OF-FLOW children
   (position:absolute, which .cc-elpanel is) are not grid items and do not
   participate in grid track sizing/placement — they're laid out per normal
   absolute-positioning rules against their nearest positioned ancestor, which
   this rule makes THIS element rather than the page. */
.cc-visual { flex: 1 1 auto; display: grid; min-height: 0; position: relative; }
.cc-visual__tree {
    position: relative; min-width: 0; overflow: hidden;
    display: flex; flex-direction: column;
    padding: 14px 10px 10px; border-right: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff);
}
/* Struktur-Baum-Kopf/-Fuß (Werkstatt-Redesign Task 6, README §4): "STRUKTUR"
   Micro-Label oben, ⌘Z/⌘D-Shortcut-Hinweise unten — both flex:0 0 auto so
   only the tree list between them scrolls (.cc-tree__scroll below).
   Werkstatt-Redesign Task 2 (Element-Palette): also hosts the ＋-button that
   toggles the popover — flex row (title left, button right). */
.cc-tree__head {
    flex: 0 0 auto; position: relative;
    display: flex; align-items: center; justify-content: space-between;
    padding: 2px 2px 10px;
}
.cc-tree__head-title {
    font: 800 10px var(--ps--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--ps--neutral-400);
}
.cc-tree__add-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px;
    background: transparent; color: var(--ps--neutral-500); cursor: pointer;
}
.cc-tree__add-btn:hover { background: var(--ps--bg-soft); color: var(--ps--fg); }
.cc-tree__add-btn[aria-expanded="true"] { background: var(--ps--brand-soft); color: var(--ps--brand); }
/* Runde 2 Task 3 (Struktur-Baum ein-/ausklappen): globale "Alle einklappen"/
   "Alle aufklappen"-Steuerung, links vom ＋-Button — gleiche Formsprache wie
   .cc-tree__add-btn oben (22px, transparent, neutral-500), eigener
   Klassenname nur, damit sie NICHT versehentlich [aria-expanded="true"]s
   Popover-Hervorhebung von .cc-tree__add-btn erbt (die beiden Buttons haben
   kein aria-expanded). */
.cc-tree__head-actions { display: flex; align-items: center; gap: 2px; }
.cc-tree__collapse-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px;
    background: transparent; color: var(--ps--neutral-500); cursor: pointer;
}
.cc-tree__collapse-btn:hover { background: var(--ps--bg-soft); color: var(--ps--fg); }

/* Element-Palette-Popover (Task 2, ElementPalette in element-palette.jsx) —
   opened by .cc-tree__add-btn above.
   Fix round (final review Important I1, popover clipping): originally
   mounted INSIDE .cc-tree__head, which sits inside .cc-visual__tree —
   overflow:hidden (see that rule above) clipped the popover's left tile
   column at the tree panel's 220–480px resizable width (~60px cut off at
   the 250px default, worse near the 220px min), and the clipped tiles were
   partly unclickable. The spec requires the popover to OVERLAY the canvas,
   not be boxed in by the tree column's own clip/scroll rect.
   visual-mode.jsx now mounts <ElementPalette> as a DIRECT CHILD of the
   .cc-visual grid shell instead (a sibling of .cc-visual__tree, not a
   descendant) — that shell is NOT overflow-hidden and, since this popover
   is position:absolute, is not a scroll/clip ancestor of anything painted
   above it either. Positioned here (not anchored to .cc-tree__head anymore)
   with fixed px values that reconstruct the same visual anchor point below
   the ＋-button: `top` = .cc-visual__tree's own top padding (14px) + the
   tree header's box height (22px ＋-button + 2px padding-top + 10px
   padding-bottom = 34px) + the original 6px gap = 54px; `left` mirrors the
   tree panel's own left inset (~10px content padding) at a round 8px — the
   popover's 300px width now freely overlaps the canvas column instead of
   being constrained to the tree column's own width. z-index:20 keeps it
   above the canvas (.cc-visual__bp-pills' z-index:5 below) and above the
   tree's resize handle (.bd-resize, z-index:5, app.css) while open — the
   handle is unaffected when the popover is closed (renders null then, as
   before). Category micro-labels reuse .cc-tree__head-title's exact look
   (10px/800/uppercase/.08em/neutral-400 — README §4's Inspector-group-label
   style); tiles are a 3-per-row icon+label grid, same family as
   IconPropertyEditor's picker cells (editors/property-editors.jsx) but its
   own namespace (a different popover, different grid shape). */
.cc-elpanel {
    position: absolute; top: 54px; left: 8px; z-index: 20;
    width: 300px; max-height: 70vh; overflow-y: auto;
    display: flex; flex-direction: column; gap: 12px;
    padding: 12px; border-radius: 10px; border: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff); box-shadow: var(--ps--shadow-md);
}
.cc-elpanel__cat { display: flex; flex-direction: column; gap: 8px; }
.cc-elpanel__cat-label {
    font: 800 10px var(--ps--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--ps--neutral-400);
}
.cc-elpanel__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.cc-elpanel__tile {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 10px 4px; border: 1px solid transparent; border-radius: 8px;
    background: var(--ps--bg-soft); color: var(--ps--fg); cursor: pointer;
}
.cc-elpanel__tile:hover:not(:disabled) { border-color: var(--ps--border); background: var(--ps--neutral-0, #fff); }
.cc-elpanel__tile:disabled { opacity: 0.4; cursor: not-allowed; }
.cc-elpanel__tile-label { font-size: 11px; font-weight: 600; text-align: center; line-height: 1.2; }
.cc-tree__scroll {
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    /* Scrollbalken bündig an der Panel-Kante (User-Feedback v0.125.0): das
       rechte 10px-Padding von .cc-visual__tree rückte den Scroll-Container —
       und damit den Balken — sichtbar von der Trennlinie ab. Das negative
       Margin hebt genau dieses Eltern-Padding wieder auf, das gleich große
       Innen-Padding erhält den bisherigen Abstand der Zeilen: nur der
       Scrollbalken wandert an den Rand, das Layout der Zeilen bleibt. */
    margin-right: -10px; padding-right: 10px;
    /* Runde 2 Task 2: dezente, an macOS angelehnte Show-on-Scroll-Scrollbar,
       1:1 aus dem Seiten-Designer-Canvas portiert (builder/iframe.jsx:29-46)
       — in Ruhe unsichtbar, erscheint per .is-scrolling (visual-mode.jsx
       setzt/entfernt die Klasse über einen Scroll-Listener) und blendet
       danach wieder aus. rgba-Werte exakt übernommen für visuelle Parität;
       alle ::-webkit-scrollbar*-Regeln bewusst auf .cc-tree__scroll
       gescoped, damit sie nicht in andere Scroll-Flächen strahlen. */
    scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.cc-tree__scroll.is-scrolling { scrollbar-color: rgba(20,30,26,.32) transparent; }
.cc-tree__scroll::-webkit-scrollbar { width: 9px; height: 9px; }
.cc-tree__scroll::-webkit-scrollbar-track { background: transparent; }
.cc-tree__scroll::-webkit-scrollbar-thumb {
    background-color: transparent; border: 2px solid transparent; border-radius: 8px;
    background-clip: padding-box; transition: background-color .35s ease;
}
.cc-tree__scroll.is-scrolling::-webkit-scrollbar-thumb { background-color: rgba(20,30,26,.32); background-clip: padding-box; }
.cc-tree__scroll::-webkit-scrollbar-thumb:hover { background-color: rgba(20,30,26,.5); background-clip: padding-box; }
.cc-tree__foot {
    flex: 0 0 auto; display: flex; flex-direction: column; gap: 5px;
    margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--ps--border);
}
.cc-tree__kbd { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ps--neutral-500); }
.cc-tree__kbd kbd {
    font: 700 10px var(--ps--font-mono, monospace); background: var(--ps--bg-soft);
    color: var(--ps--fg); border-radius: 5px; padding: 2px 6px;
}
/* Canvas (Werkstatt-Redesign Task 6, README §4; Runde 2 Task 1 „echter
   Arbeitscanvas"): neutraler Arbeitsflächen-Ton (--ps--workspace, dieselbe
   Farbe wie der Builder-Canvas) — die Komponente sitzt jetzt DIREKT darauf,
   kein weißes Karten-Rechteck mehr (s. .cc-visual__stage weiter unten). */
.cc-visual__preview { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding: 0; background: var(--ps--workspace); }
.cc-visual__inspector {
    position: relative; min-width: 0;
    /* Runde 4 (User-Feedback "10px weniger Seitenpadding + NIE horizontal
       scrollen"): 16px → 12px/8px (siehe .cc-inspector__group/__panel weiter
       unten für die passende Anpassung ihres eigenen 14px-Innenpaddings).
       overflow-x: hidden ist der explizite Killswitch für den H-Scrollbalken
       — OHNE ihn kippt der Browser overflow-x automatisch von 'visible' auf
       'auto', sobald overflow-y einen Nicht-visible-Wert trägt (CSS-Overflow-
       Spec-Sonderfall "computed value of overflow-x/-y: if one is 'visible'
       and the other isn't, 'visible' becomes 'auto'") — DAS war die
       tatsächliche Quelle des Balkens, nicht ein bewusstes overflow-x:auto
       hier. Die STRUKTURELLE Ursache (per Live-Chromium-Messung verifiziert,
       s. .cc-inspector__block-buttons weiter unten für den bestätigten
       Befund) ist ebenfalls behoben; die dortige minmax(0, 1fr)-Härtung an
       .cc-inspector__field u.a. ist zusätzliche Absicherung (per Messung
       unauffällig, aber schadet nicht). Dieses overflow-x:hidden bleibt der
       garantierte Killswitch, falls trotzdem einmal etwas überläuft — dann
       wird sauber geclippt statt einen Balken zu zeigen. */
    overflow-y: auto; overflow-x: hidden;
    padding: 12px 8px; border-left: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff);
    /* Runde 4 Task (Show-on-Scroll-Scrollbar): 1:1 dieselbe dezente
       Scrollbar wie .cc-tree__scroll oben — in Ruhe unsichtbar, erscheint
       per `.is-scrolling` (visual-mode.jsx setzt/entfernt die Klasse über
       einen Scroll-Listener auf genau diesem <aside>, 1:1 aus dem
       treeScrollRef-Effekt gespiegelt) und blendet danach wieder aus. */
    scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.cc-visual__inspector.is-scrolling { scrollbar-color: rgba(20,30,26,.32) transparent; }
.cc-visual__inspector::-webkit-scrollbar { width: 9px; height: 9px; }
.cc-visual__inspector::-webkit-scrollbar-track { background: transparent; }
.cc-visual__inspector::-webkit-scrollbar-thumb {
    background-color: transparent; border: 2px solid transparent; border-radius: 8px;
    background-clip: padding-box; transition: background-color .35s ease;
}
.cc-visual__inspector.is-scrolling::-webkit-scrollbar-thumb { background-color: rgba(20,30,26,.32); background-clip: padding-box; }
.cc-visual__inspector::-webkit-scrollbar-thumb:hover { background-color: rgba(20,30,26,.5); background-clip: padding-box; }

/* Canvas-Innenleben (WorkshopPreview's isVisualCanvas-Zweig,
   workshop-preview.jsx) — schwebende Breakpoint-Pills oben mittig (angeheftet,
   scrollen NICHT mit), darunter der eigentliche Scroll-Viewport mit der
   zentrierten Vorschau-Karte (Breite animiert 280ms beim Breakpoint-Wechsel)
   und dem Hinweis-Chip. `.cc-visual__canvas` selbst scrollt NICHT — es ist nur
   noch der position:relative-Anker für die Pills; würden die Pills stattdessen
   im scrollenden Viewport hängen, wanderten sie beim Scrollen/Pan aus dem
   Bild statt sichtbar zu bleiben. */
.cc-visual__canvas { position: relative; height: 100%; }
/* Werkstatt-Arbeitscanvas (Runde 2, Task 1): echter Arbeits-Canvas statt
   360px-Vorschau-Karte — DIESER Viewport ist jetzt der scrollbare Container
   (volle Höhe der Komponente + Space-Pan schreiben hier scrollLeft/scrollTop,
   workshop-preview.jsx). `.cc-visual__preview`s eigenes `overflow-y:auto`
   bleibt unangetastet (anderer Task/Datei), greift hier aber praktisch nie
   mehr, weil `.cc-visual__canvas` dessen Höhe exakt füllt (100%). `cursor`
   spiegelt den Pan-Zustand: Default in Ruhe, `grab` während Leertaste
   gehalten wird (`.is-panning`), `grabbing` während des tatsächlichen Ziehens
   (reines `:active`, keine weitere Klasse nötig). */
.cc-visual__viewport {
    height: 100%; overflow: auto; display: flex; flex-direction: column;
    /* flex-start statt center: bei Inhalt breiter als der Viewport wäre mit
       align-items:center der linke Rand unerreichbar (unsafe centering in
       Scroll-Containern) — zentriert wird stattdessen über margin-inline:auto
       auf der Stage (zentriert bei Platz, linksbündig/erreichbar bei Überbreite). */
    align-items: flex-start; padding: 56px 22px 22px; cursor: default;
    /* Runde 3 Task 2 (Dezente Canvas-Scrollbar): 1:1 dieselbe show-on-scroll-
       Scrollbar wie der Struktur-Baum (.cc-tree__scroll oben) — in Ruhe
       unsichtbar, erscheint per `.is-scrolling` (workshop-preview.jsx setzt/
       entfernt die Klasse über einen Scroll-Listener auf genau diesem
       Element) und blendet danach wieder aus. rgba-Werte 1:1 übernommen für
       visuelle Parität; alle ::-webkit-scrollbar*-Regeln bewusst auf
       `.cc-visual__viewport` gescoped, damit sie nicht in andere
       Scroll-Flächen strahlen (ein tall component braucht die elegante
       Scrollbar statt der Browser-Default). */
    scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.cc-visual__viewport.is-panning { cursor: grab; }
.cc-visual__viewport.is-panning:active { cursor: grabbing; }
.cc-visual__viewport.is-scrolling { scrollbar-color: rgba(20,30,26,.32) transparent; }
.cc-visual__viewport::-webkit-scrollbar { width: 9px; height: 9px; }
.cc-visual__viewport::-webkit-scrollbar-track { background: transparent; }
.cc-visual__viewport::-webkit-scrollbar-thumb {
    background-color: transparent; border: 2px solid transparent; border-radius: 8px;
    background-clip: padding-box; transition: background-color .35s ease;
}
.cc-visual__viewport.is-scrolling::-webkit-scrollbar-thumb { background-color: rgba(20,30,26,.32); background-clip: padding-box; }
.cc-visual__viewport::-webkit-scrollbar-thumb:hover { background-color: rgba(20,30,26,.5); background-clip: padding-box; }
/* „Visueller Editor Runde 2" Task 5: this wrapper is now ONLY a positioning
   box (absolute, top-center, above the canvas) — the inner switch is the page
   builder's `.cp-vp-switch` (app.css, untouched), which brings its own
   background/padding/border-radius/shadow. The former button-look rules
   (`.cc-visual__bp-pills button[.is-active]`) are gone: dead now that the
   buttons are `cp-vp-switch__btn`, styled globally. */
.cc-visual__bp-pills { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 5; }
/* Werkstatt-Arbeitscanvas (Runde 2, Task 1): kein weißes Karten-Rechteck mehr
   — background/box-shadow sind weg, die Komponente sitzt direkt auf der
   grauen Arbeitsfläche (.cc-visual__preview/.cc-visual__viewport).
   Transition/Radius/Overflow bleiben unverändert; die BREITEN sind seit dem
   Artboard-Fix (Runde 3, User-Feedback) FESTE Breakpoint-Maße — s. die
   width-Kommentare in der Regel selbst und an den --tablet/--mobile-
   Modifiern unten. Runde 3 Task 2 „dünner Artboard-Rahmen": ein 1px, dezenter
   Rahmen (kein Schatten, keine Füllung) markiert die Breakpoint-Grenzen der
   Komponente auf der grauen Fläche — Framer/Webflow-Artboard-Optik. NICHT der
   weiße Kasten aus Runde 1: kein background, kein box-shadow, nur die
   1px-Kontur. */
.cc-visual__stage {
    /* Echtes Artboard (User-Feedback Runde 3): FESTE Breakpoint-Breite statt
       width:100%/max-width — Desktop = 1440px (Standard-Desktop-Artboard wie
       Figma/Framer; >1320px, damit Desktop-Media-Queries realer Websites
       greifen). Ist das Fenster schmaler, wird gescrollt/gepannt (Space),
       nie das Artboard gestaucht — sonst feuern Media-Queries der Komponente
       auf „Desktop" fälschlich mobil.
       User-Feedback „Rechts-Clipping": ist der INHALT breiter als diese
       1440px (z. B. ein Grid mit mehreren 340px-Items + Gaps > 1440px), wird
       das Artboard per Inline-Style (workshop-preview.jsx's
       `stageWidthOverride`, gemessen von measureStageWidth) über diese
       Klassen-Breite hinaus verbreitert, statt den Inhalt abzuschneiden —
       diese Regel bleibt dabei die reine BASIS-/Rückfallbreite. MUSS mit
       `DESKTOP_ARTBOARD_WIDTH` in workshop-preview.jsx synchron gehalten
       werden (die Messung braucht die Basis-Breite als JS-Zahl, ohne sie
       hier aus dem DOM zurückzulesen). */
    width: 1440px; border-radius: 12px; overflow: hidden;
    /* flex-shrink:0: die Stage ist Flex-Kind des scrollbaren Viewports —
       ohne dies STAUCHT flex-shrink:1 sie bei hohem Inhalt auf Viewport-Höhe
       und overflow:hidden schneidet die Komponente unten ab (User-Bug
       „Komponente abgeschnitten"). margin-inline:auto = sichere Zentrierung
       (s. Viewport-Kommentar). */
    flex-shrink: 0; margin-inline: auto;
    /* box-sizing: der 1px-Rahmen soll die Breakpoint-Breite (768px/560px
       weiter unten) exakt einfassen statt sie um 2px zu überschreiten — die
       Stage bildet ein reales Breakpoint-Maß ab, kein beliebiger Kasten. */
    box-sizing: border-box; border: 1px solid var(--ps--border);
    /* Spec (design_handoff_werkstatt_redesign §4): fixed 280ms, not the
       320ms --ps--duration-slow token used elsewhere in the shell. */
    transition: width 280ms var(--ps--ease-standard);
}
/* Feste Artboard-Breiten auch hier — KEIN max-width:100% mehr: ein 768px-
   Tablet-Artboard darf in einem schmalen Fenster nicht auf z. B. 640px
   gestaucht werden (Media-Queries der Komponente würden falsch feuern);
   stattdessen scrollt/pannt man. */
.cc-visual__stage--tablet { width: 768px; }
.cc-visual__stage--mobile { width: 560px; }
.cc-visual__hint {
    /* Runde 4 (User-Feedback "Hint-Pille dezenter + zentriert"): der Viewport
       nutzt align-items:flex-start (s. .cc-visual__viewport Kommentar oben,
       "unsafe centering" bei Überbreite) — dadurch säße dieser flex:0 0 auto-
       Chip seither links statt zentriert. margin-inline:auto zentriert einen
       NICHT-stretch-Flex-Item auch im Cross-Axis einer Column-Flexbox (Auto-
       Margins gewinnen dort über align-items/align-self, exakt wie im
       Block-Kontext) — der bestehende `margin-top` (14px) bleibt unverändert
       erhalten, nur links/rechts kommt margin:auto hinzu.
       Optik dezenter (User-Feedback): kleinere Schrift (11.5px→10.5px),
       gedämpfter Text-Ton (neutral-500→neutral-400), transparenterer
       Hintergrund (fff→halbtransparentes weiß) und kein Schatten mehr
       (shadow-xs war die letzte optische Betonung, die die Pille "wichtiger"
       wirken ließ als der übrige, sehr zurückhaltende Canvas-Chrome). */
    flex: 0 0 auto; margin: 14px auto 0; padding: 6px 12px; border-radius: 999px;
    background: rgba(255, 255, 255, 0.7); box-shadow: none;
    font-size: 10.5px; color: var(--ps--neutral-400); white-space: nowrap;
}

/* Struktur-Baum (StructureTree, views/visual/structure-tree.jsx) — ein Knoten
   pro Element des geparsten Templates (parseTemplate()'s root), Label =
   Tag + erste Klasse, Badges für {{#each}}/{{#if}}/{{else}}/{{slot}}-Marker-
   Knoten. Einrückung kommt inline (paddingLeft je Tiefe) aus dem Baum selbst. */
.cc-tree, .cc-tree__children { list-style: none; margin: 0; padding: 0; }
.cc-tree__children { margin-left: 4px; }
.cc-tree__row {
    display: flex; align-items: center; gap: 6px; width: 100%;
    height: 29px; padding-right: 8px; border: 0; border-radius: 7px;
    background: transparent; color: var(--ps--neutral-600); font: 600 12.5px var(--ps--font-sans);
    text-align: left; cursor: pointer;
}
.cc-tree__row:hover { background: var(--ps--bg-soft); }
.cc-tree__row.is-selected {
    background: var(--ps--brand-soft); color: var(--ps--fg); font-weight: 800;
}
/* Runde 2 Task 3 (Struktur-Baum ein-/ausklappen) — Kollaps-Chevron VOR dem
   Label, nur bei Knoten mit Element-Kindern (structure-tree.jsx's
   `hasElementChildren`); knotenlose Zeilen bekommen stattdessen einen
   leeren, gleich breiten Platzhalter (--leaf), damit alle Labels — mit und
   ohne Chevron — auf derselben Spalte ausgerichtet bleiben. Formsprache 1:1
   aus builder/layers-panel.jsx's `.bd-tree__twist` übernommen (app.css),
   nur im eigenen .cc-tree__-Namensraum. */
.cc-tree__toggle {
    flex: 0 0 auto; width: 16px; height: 16px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 0; padding: 0; border-radius: 4px;
    color: var(--ps--neutral-500); cursor: pointer;
}
.cc-tree__toggle:hover { background: var(--ps--neutral-0); color: var(--ps--fg); }
.cc-tree__toggle--leaf { cursor: default; }
.cc-tree__row.is-selected .cc-tree__toggle:hover { background: rgba(255,255,255,.6); }
.cc-tree__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Tag mono grün + Klasse grau (README §4) — zwei separate Spans innerhalb
   desselben .cc-tree__label (structure-tree.jsx splitLabel()), damit die
   Substring-Assertions bestehender Tests ("div.root" etc. via textContent)
   unverändert bestehen bleiben. */
.cc-tree__tag { font-family: var(--ps--font-mono, monospace); color: var(--ps--brand); }
.cc-tree__cls { color: var(--ps--neutral-400); }
.cc-tree__row.is-selected .cc-tree__tag,
.cc-tree__row.is-selected .cc-tree__cls { font-weight: 800; }
/* Gebundene Elemente: violette {{}}-Pill (README §4) — CMS-Signalfarbe,
   dieselbe wie die Bindung-Karte im Inspector. */
.cc-tree__bind-pill {
    flex: 0 0 auto; font: 800 9px var(--ps--font-mono, monospace);
    color: var(--ps--cms-strong); background: var(--ps--cms-soft);
    padding: 1px 6px; border-radius: 999px;
}
.cc-tree__badge {
    flex: 0 0 auto; font-size: 9.5px; font-weight: 800; letter-spacing: 0.04em;
    padding: 1px 6px; border-radius: 999px; text-transform: uppercase;
    background: var(--ps--bg-soft); color: var(--ps--neutral-500);
}
/* #if/#each Marker-Chips (README §4): mono, Keyword-Farbe auf sanftem
   Amber-Hintergrund, "#"-Präfix rein dekorativ über ::before (zählt nicht
   zum textContent, s. structure-tree.test.jsx-Assertions auf 'IF'/'EACH'). */
.cc-tree__badge--if, .cc-tree__badge--each {
    font-family: var(--ps--font-mono, monospace); text-transform: lowercase;
    color: var(--ps--editor-syntax-keyword, #e88d67); background: #fdf0e9;
}
.cc-tree__badge--if::before, .cc-tree__badge--each::before { content: '#'; }
.cc-tree__row.is-selected .cc-tree__badge { background: var(--ps--neutral-0, #fff); }
.cc-tree__empty { font-size: 13px; color: var(--ps--neutral-500); margin: 0; padding: 4px 2px; }

/* Text-Zeilen (Werkstatt-Redesign „Visueller Editor Runde 2" Task 1) — ein
   rein präsentationaler Eintrag pro sichtbarem Text-Kind (TreeNode's
   childNodes-Iteration, structure-tree.jsx): dieselbe 29px-Zeilen-Grammatik
   wie .cc-tree__row oben, aber optisch zurückgenommen (kursiv, gedämpfte
   Farbe) — kein eigener Selected-/Drag-/Aktionen-Zustand, ein Klick wählt den
   ELTERNKNOTEN aus (kein eigener Pfad). */
.cc-tree__textrow {
    display: flex; align-items: center; gap: 6px; width: 100%;
    height: 29px; padding-right: 8px; border: 0; border-radius: 7px;
    background: transparent; color: var(--ps--neutral-400);
    font: italic 500 12px var(--ps--font-sans);
    text-align: left; cursor: pointer;
}
.cc-tree__textrow:hover { background: var(--ps--bg-soft); }
.cc-tree__textrow-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Zeilen-Aktionen (Werkstatt-Redesign Task 3) — ersetzt die alte
   Struktur-Toolbar (StructureToolbar, Task 9) komplett: ↑/↓/Duplizieren/
   Löschen sitzen jetzt rechtsbündig NUR an der SELEKTIERTEN Baum-Zeile
   (TreeNode, structure-tree.jsx), nicht mehr in einer eigenen Button-Reihe
   über dem Baum. Eigene, sehr kompakte Icon-Buttons (~18px) statt der
   kanonischen .bx-btn — dieselbe Formsprache wie .cc-tree__add-btn oben
   (transparent, kleiner Radius, neutral-500): .bx-btn (40px/9px, s.
   "Studio-Chrome-Buttons" oben) ist für "echte" beschriftete Buttons gedacht
   und wäre in einer 29px-Baumzeile absurd überdimensioniert.
   `margin-left: auto` schiebt die Gruppe an den rechten Rand der ohnehin
   schon flex-row .cc-tree__row (gap dort bleibt für Label/Pill/Badge davor).
   Eine selektierte Zeile hat --ps--brand-soft-Hintergrund — Hover auf einer
   Aktion hellt sie auf denselben "weißes Chip"-Ton auf wie das Badge daneben
   (.cc-tree__row.is-selected .cc-tree__badge oben), statt --ps--bg-soft, das
   auf dem getönten Hintergrund kaum sichtbar wäre. */
.cc-tree__row-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; margin-left: auto; }
.cc-tree__row-action {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; padding: 0; border: 0; border-radius: 5px;
    background: transparent; color: var(--ps--neutral-500); cursor: pointer;
}
.cc-tree__row-action:hover:not(:disabled) { background: var(--ps--neutral-0, #fff); color: var(--ps--fg); }
.cc-tree__row-action:disabled { opacity: 0.35; cursor: not-allowed; }
.cc-tree__row-action--danger:hover:not(:disabled) { color: var(--ps--danger); }

/* Drag & Drop im Struktur-Baum (Werkstatt-Redesign „Visueller Editor Runde
   2" Task 3, structure-tree.jsx) — Zonen-Indikatoren analog dem Seiten-Baum
   (builder/pages-panel.jsx, optisch wie .bd-page.is-drop-* in app.css),
   eigene .cc-tree__row-Regeln hier statt einer app.css-Abhängigkeit. Die
   Klasse wird IMPERATIV per classList gesetzt (kein React-State, s.
   structure-tree.jsx's TreeNode-Kommentar), die Optik selbst ist aber
   dieselbe Marken-Sprache wie überall sonst im Baum (--ps--brand/-soft).
   inside = Inset-Ring + sanfter Ton (verschachteln), before/after = 2px
   Inset-Linie oben/unten (umsortieren auf gleicher Ebene). */
.cc-tree__row.is-drop-inside {
    box-shadow: inset 0 0 0 2px var(--ps--brand);
    background: var(--ps--brand-soft);
}
.cc-tree__row.is-drop-before { box-shadow: inset 0 2px 0 var(--ps--brand); }
.cc-tree__row.is-drop-after { box-shadow: inset 0 -2px 0 var(--ps--brand); }

/* Inspector (Task 5, views/visual/inspector.jsx) — mounts into
   #cc-inspector-slot (.cc-visual__inspector above supplies the column frame:
   width, padding, border, scroll). Own namespace (.cc-inspector__*) for the
   shell Task 5 owns; Tasks 6–8 add their group-controls markup inside it.
   Werkstatt-Redesign Task 6: the Desktop/Tablet/Mobil SWITCHER moved to the
   canvas (.cc-visual__bp-pills, workshop-preview.jsx) — the header below
   only shows a READ-ONLY breakpoint badge now.
   Werkstatt-Redesign Task 3 (spec §"Token map"): a few bespoke literals with
   no existing --ps--* token get ONE local custom-property home here instead
   of scattered hex repeats — later tasks (chips, rename-pencil) consume
   these too. */
.cc-inspector {
    --cc-insp-divider: var(--ps--border);
    /* Diese beiden bleiben literal, weil ihr Gegenstück existiert: darkmode.css
       überschreibt --cc-insp-chip-active-border und --cc-insp-pencil unter
       html.ps-dark. Das Paar ist vollständig, das ist der Maßstab (PS-88). */
    --cc-insp-chip-active-border: #b6d9cc;
    --cc-insp-pencil: #4d9c82;
    /* Task 11 (README §10, Token map): keyword prefix ("#if"/"#each") mono
       orange, binding-card meta text violet-grey — neither has an existing
       --ps--* token. */
    /* Verweist auf den Editor-Token statt denselben Wert ein zweites Mal
       hinzuschreiben (PS-88): es IST dieselbe Schlüsselwortfarbe, und zwei
       Kopien laufen beim nächsten Ändern auseinander. */
    --cc-insp-keyword: var(--ps--editor-syntax-keyword);
    --cc-insp-binding-meta: #8a7fb8;
}
.cc-inspector__hint { font-size: 13px; color: var(--ps--neutral-500); margin: 0; line-height: 1.5; }

/* Kopf (README §4, Framer-artig): Tag-Chip (mono) + Breakpoint-Badge rechts
   (neutral "Basis" / amber "Tablet ≤768"/"Mobil ≤560"). Werkstatt-Redesign
   Task 4: enger gesetzt (Chips 22px hoch, Abstände 8px — Framer-Referenz,
   spec §5). Werkstatt-Redesign Task 3: the class-pill is REMOVED (README
   §"Aufbau des Panels" #1 — classes live directly below in the Klassen
   chip row instead), so only the tag-chip + bp-badge remain here. */
.cc-inspector__header { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.cc-inspector__tag {
    display: inline-flex; align-items: center; height: 22px;
    font: 800 12px var(--ps--font-mono, monospace); text-transform: lowercase;
    padding: 0 8px; border-radius: 6px; background: var(--ps--bg-soft); color: var(--ps--fg);
}
.cc-inspector__bp-badge {
    display: inline-flex; align-items: center; height: 22px;
    margin-left: auto; font-size: 11px; font-weight: 800; padding: 0 9px; border-radius: 999px;
    color: var(--ps--neutral-500); background: var(--ps--bg-soft);
}
.cc-inspector__bp-badge.is-override { color: var(--ps--warning-fg); background: var(--ps--warning-soft); }

/* Klassen-Chip-Zeile (Werkstatt-Redesign Inspector Task 10, README §2):
   die aktive Stil-Klasse ist ein grüner Chip mit ✎ (Umbenennen); weitere
   Klassen sind neutrale Chips (Klick wechselt die Stil-Klasse, × entfernt
   sie bei Hover); "+ Klasse" ist ein eigener Ghost-Chip. .cc-inspector__
   classes-row ist die wrappende Zeile; .cc-inspector__classes selbst bleibt
   `display: contents`, damit seine Chip-<span>s/<input>s direkte Flex-Items
   der Zeile werden (keine eigene Box), während es als echter DOM-Knoten
   bestehen bleibt — die etablierten Test-Queries (`.cc-inspector__chip`)
   funktionieren dadurch unverändert weiter. */
.cc-inspector__classes-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 6px; }
.cc-inspector__classes { display: contents; }
.cc-inspector__chip {
    display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 8px;
    border-radius: 999px; border: 1.5px solid transparent;
    background: var(--ps--neutral-100); color: var(--ps--neutral-500);
    font: 600 12px var(--ps--font-mono, monospace); cursor: pointer;
    transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), color var(--ps--duration-fast);
}
.cc-inspector__chip:hover { background: var(--ps--neutral-200); }
/* Aktive Stil-Klasse (README §2: Soft-Grün, Rahmen, Marken-Text, immer
   sichtbares ✎) — nicht klickbar (kein Wechsel-Ziel für sich selbst). */
.cc-inspector__chip.is-active {
    cursor: default;
    background: var(--ps--brand-soft); border-color: var(--cc-insp-chip-active-border);
    color: var(--ps--brand); font-weight: 700;
}
.cc-inspector__chip.is-active:hover { background: var(--ps--brand-soft); }

/* ✎ (Umbenennen) / × (Entfernen) im Chip — kleine eigene Icon-Buttons
   (gleiche Familie wie .cc-inspector__reset weiter unten), NICHT der
   kanonische 40px-.bx-btn (zu groß für einen 26px-Chip). × bleibt bei Hover/
   Fokus sichtbar (bleibt aber im DOM — s. .cc-inspector__reset-Kommentar
   für dasselbe "immer da, nur per CSS ausgeblendet"-Muster). */
.cc-inspector__chip-rename,
.cc-inspector__chip-remove {
    display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px; padding: 0; border: none; border-radius: 5px;
    background: transparent; cursor: pointer; line-height: 1; flex: 0 0 auto;
    transition: opacity var(--ps--duration-fast), background var(--ps--duration-fast);
}
.cc-inspector__chip-rename { color: var(--cc-insp-pencil); }
.cc-inspector__chip-rename:hover { background: color-mix(in srgb, var(--cc-insp-pencil) 18%, transparent); }
.cc-inspector__chip-remove { color: var(--ps--neutral-500); font-size: 13px; opacity: 0; }
.cc-inspector__chip:hover .cc-inspector__chip-remove,
.cc-inspector__chip-remove:focus-visible { opacity: 1; }
.cc-inspector__chip-remove:hover { background: var(--ps--neutral-300); color: var(--ps--fg); }
.cc-inspector__chip-rename:focus-visible,
.cc-inspector__chip-remove:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring);
}

/* Inline-Inputs: der aktive Chip (Umbenennen) bzw. der Ghost-Chip (Klasse
   hinzufügen) werden während der Bearbeitung zu einem dieser Inputs
   (README §2 "Klick macht den Chip zum Inline-Input") — gleicher Chip-
   Footprint (26px, radius 999px), damit die Zeile nicht springt. */
.cc-inspector__chip-rename-input,
.cc-inspector__chip-add-input {
    height: 26px; padding: 0 10px; border: 1.5px solid var(--ps--primary);
    border-radius: 999px; font: 600 12px var(--ps--font-mono, monospace);
    color: var(--ps--fg); background: var(--ps--neutral-0); outline: none; min-width: 90px;
    box-shadow: 0 0 0 3px var(--ps--focus-ring);
}

/* "+ Klasse"-Ghost-Chip (README §2: gestrichelter Rahmen, gedämpftes Label)
   — EIGENE Klasse (nicht `.cc-inspector__chip`), damit er nie von
   `.cc-inspector__chip`-Test-Queries als echte Element-Klasse mitgezählt
   wird. */
.cc-inspector__chip-add {
    display: inline-flex; align-items: center; height: 26px; padding: 0 10px;
    border-radius: 999px; border: 1.5px dashed var(--ps--neutral-300);
    background: transparent; color: var(--ps--neutral-400);
    font: 700 11px var(--ps--font-sans); cursor: pointer;
    transition: border-color var(--ps--duration-fast), color var(--ps--duration-fast);
}
.cc-inspector__chip-add:hover { border-color: var(--ps--neutral-400); color: var(--ps--neutral-500); }
.cc-inspector__chip-add:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring);
}

.cc-inspector__error { font-size: 11.5px; color: var(--ps--danger, #dc2626); margin: 0 0 8px; }

/* "Stil-Klasse anlegen" is a canonical .bx-btn now (fast-follow T9b) — only
   the full-width layout stays here. */
.cc-inspector__create-class { width: 100%; }

/* Kollisions-Zeile (Werkstatt-Redesign Inspector Task 10, README §2): EINE
   Zeile — Punkt + "N Elemente nutzen .<class>" + rechts der "Entkoppeln"-
   Button (aria-label bleibt "Nur für dieses Element", s. inspector.jsx-
   Kommentar/Test-Vertrag). Ersetzt die vorherige mehrzeilige Warn-Box. */
.cc-inspector__collision { display: flex; align-items: center; gap: 6px; margin: 6px 0 8px; }
.cc-inspector__collision-dot {
    flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--ps--warning);
}
.cc-inspector__collision-text {
    flex: 1 1 auto; min-width: 0; margin: 0; font: 600 11px var(--ps--font-sans); color: var(--ps--neutral-400);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cc-inspector__collision-text strong { color: var(--ps--warning-fg); font-weight: 700; }
.cc-inspector__collision-btn {
    flex: 0 0 auto; height: 22px; padding: 0 8px; border-radius: 6px;
    border: 1px solid var(--ps--border); background: var(--ps--neutral-0); color: var(--ps--fg);
    font: 700 10.5px var(--ps--font-sans); cursor: pointer;
    transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast);
}
.cc-inspector__collision-btn:hover { background: var(--ps--neutral-50); border-color: var(--ps--neutral-400); }
.cc-inspector__collision-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring); }

.cc-inspector__complex-hint {
    font-size: 12px; color: var(--ps--neutral-500); margin: 8px 0; padding: 6px 10px;
    border-radius: 8px; background: var(--ps--bg-soft);
}

/* Inhalt (Task 11, README §10 — replaces the former separate "Bindung" +
   "Block-Aktionen" panels from Task 10 with ONE combined "Inhalt" panel/
   title; inspector.jsx renders exactly one <section class="cc-inspector
   __panel"> now instead of two): a DIFFERENT class (.cc-inspector__panel)
   from the style groups below (.cc-inspector__group), because __group is the
   identity visual-inspector-groups.test.jsx asserts on exclusively for the
   CSS-declaration groups (exact title list, "0 groups without a style
   class"). Inhalt applies regardless of a style class, so it can't share
   that marker — but Werkstatt-Redesign Task 3 gives it the SAME
   always-visible block treatment (spec §"Panel structure"): no
   <details>/<summary>, no expand/collapse, a plain <h4> micro-label title.
   Body/field rows still reuse the shared .cc-inspector__group-body/
   .cc-inspector__field rules below (purely visual, not asserted on as an
   identity). */
.cc-inspector__panel {
    /* Runde 4: 14px → 8px Seitenpadding (User-Feedback "10px weniger",
       zusammen mit .cc-visual__inspector's 16px→8px oben — 30px Gesamtinset
       wird zu 16px). */
    padding: 12px 8px;
    border-bottom: 1px solid var(--cc-insp-divider);
}
/* .cc-inspector__panel-title shares its micro-label styling with
   .cc-inspector__group-title — one combined rule below, next to the style
   groups (spec §"Panel structure": identical treatment for every section
   title, groups and panels alike). */

/* Bindung-Karte (README §10): violette Karte statt schlichter Zeile — ein
   weißer 22×22-Badge mit dem Ketten-Icon (statt eines nackten Icons),
   {{feldId}} mono in CMS-Signalfarbe, Meta-Text in einem eigenen
   Violett-Grau-Ton (--cc-insp-binding-meta, kein bestehendes Token), rechts
   "lösen" (Button-ACCESSIBLE-NAME bleibt exakt "Bindung lösen" — s.
   inspector.jsx-Kommentar an der Stelle — nur das sichtbare Label kürzt
   sich; die .bx-btn-Klasse/-Größe bleibt kanonisch, AGENTS.md "Unified
   studio-chrome UI", statt der 24px-Bespoke-Größe aus dem Mockup — gleiche
   Linie wie die fast-follow-T9b-Entscheidung für die Wrap/Unwrap-Buttons
   unten). */
.cc-inspector__binding-card {
    display: flex; align-items: center; gap: 8px; padding: 8px 10px;
    border-radius: 9px; background: var(--ps--cms-soft);
}
.cc-inspector__binding-badge {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto; width: 22px; height: 22px; border-radius: 6px;
    background: var(--ps--neutral-0, #fff); color: var(--ps--cms);
}
.cc-inspector__binding-icon { color: inherit; }
.cc-inspector__binding-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cc-inspector__binding-code {
    font: 700 12px var(--ps--font-mono, monospace); color: var(--ps--cms-strong);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cc-inspector__binding-meta { font-size: 10.5px; color: var(--cc-insp-binding-meta); }

/* Bild-Picker-Zeile (Task 5, "Bilder — Platzhalter + Mediathek-Picker"):
   thumbnail (28×28 — AuthImg when the bild-field already has a default,
   otherwise a neutral icon tile) + "Bild wählen" button, which opens the SAME
   ImagePickerDialog (Medien + Hochladen) the page-builder's Inhalt-Modus
   already uses (builder/content-edit.jsx). Always rendered ABOVE the
   existing binding-card/bind-select (bound or not, inspector.jsx) — picking
   an asset there works whether or not the <img> is bound yet. */
.cc-inspector__image-pick {
    display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
}
.cc-inspector__image-pick-thumb {
    flex: 0 0 auto; width: 28px; height: 28px; border-radius: 6px;
    overflow: hidden; display: flex; align-items: center; justify-content: center;
    background: var(--ps--bg-soft); border: 1px solid var(--ps--border);
    color: var(--ps--neutral-500);
}
.cc-inspector__image-pick-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Block-Buttons (Task 11, README §10): zwei gleichbreite Sekundär-Buttons
   nebeneinander (ersetzt die alte rechtsbündige Spalte aus Task 4/dem
   {{#if}}-inline-<select> aus Task 10) — `position: relative` verankert das
   Quellen-Popover unten. Button-GRÖSSE bleibt .bx-btn--sm (kanonisch,
   AGENTS.md) statt des 28px-Mockup-Maßes — dieselbe fast-follow-T9b-Linie
   wie die Bindung-Karte oben; `flex: 1 1 0` macht beide Buttons gleich breit. */
.cc-inspector__block-buttons {
    /* flex-wrap (Runde-4-Review, Important 2): schrumpfen die Buttons unter
       ihre nowrap-Label-Breite, liefe das Label über die Buttonränder hinaus
       (min-width:0 unten erlaubt das Schrumpfen bewusst, um den H-Scroll zu
       verhindern). Statt Labels zu kürzen oder ein per-Area-Ellipsis-Snowflake
       einzuführen (AGENTS.md „ein Button-Look"), BRECHEN die Buttons um: passt
       die Zeile nicht, bekommt jeder Button seine eigene volle Zeile — Label
       immer vollständig lesbar, nie Überlauf. */
    display: flex; flex-wrap: wrap; gap: 8px; position: relative;
}
/* Runde 4 (H-Scroll-Fix, TATSÄCHLICHER Übeltäter — bestätigt per Repro-Messung
   in echtem Chromium, siehe insp-polish-report.md): `.bx-btn` trägt
   `white-space: nowrap` aus seiner Basis-Regel (components.css, die
   Website-Button-Atom-Definition — bewusst NICHT hier überschrieben, s.
   AGENTS.md "Atoms are single source"/"Unified studio-chrome UI"). Ein
   nowrap-Button ohne `min-width: 0` bekommt als Flex-Item die klassische
   automatische Mindestgröße = seine VOLLE, unwrapped Textbreite (min-width:
   auto ist der Default) — `flex: 1 1 0` allein verhindert das NICHT (flex-
   shrink:1 darf nur bis zur automatischen Mindestgröße schrumpfen, nicht
   darunter). Mit den beiden echten Labels "#if Bedingung" (122px) und "#each
   Wiederholung" (158px) + 8px gap braucht die Zeile 288px, obwohl das
   umgebende Inhalt-Panel nur ~236–268px Platz hat — GENAU DAS drückt
   `.cc-inspector__panel`, dann `.cc-visual__inspector` über seine 300px-Spur
   hinaus und triggert den H-Scrollbalken, JEDES MAL wenn ein normaler
   (nicht-{{#if}}/{{#each}})-Knoten selektiert ist, nicht nur in einem
   Rand-Fall. Derselbe `min-width: 0`-Kniff, den `.cc-inspector__seg` (README
   §3 "Segmented Control") schon für genau dieses Problem trägt — hier fehlte
   er schlicht. */
/* flex-basis auto + flex-shrink 0 (statt `1 1 0` + Schrumpfen): der Button
   nimmt mindestens seine Label-Breite ein und der Container bricht um (s.
   flex-wrap oben) statt zu quetschen — kein Label-Überlauf, kein H-Scroll
   (das aside-eigene overflow-x:hidden bleibt der Killswitch). */
.cc-inspector__block-buttons > .bx-btn { flex: 1 0 auto; }
/* Keyword-Präfix ("#if"/"#each") — mono, orange, vom übrigen Button-Label
   per Leerzeichen abgesetzt (README §10 "Präfix mono 800 10px #e88d67"). */
.cc-inspector__block-kw {
    font: 800 10px var(--ps--font-mono, monospace); color: var(--cc-insp-keyword);
}

/* {{#if}}-Quellen-Popover (README §10 "öffnet die Quellen-Auswahl als
   Dropdown/Popover") — selbe Karten-Familie wie .cc-inspector__color-popover/
   .cc-elpanel (weiß, Rahmen, Radius, Schatten); hängt unter der Button-Zeile,
   linksbündig zum #if-Button (erstes Kind von .cc-inspector__block-buttons,
   das bereits `position: relative` mitbringt). */
.cc-inspector__if-popover {
    position: absolute; top: 100%; left: 0; z-index: 20; margin-top: 4px;
    min-width: 160px; max-width: 240px;
    display: flex; flex-direction: column; gap: 2px;
    padding: 6px; border-radius: 9px; border: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff); box-shadow: var(--ps--shadow-md);
}
.cc-inspector__if-option {
    text-align: left; padding: 6px 8px; border: 0; border-radius: 6px;
    background: transparent; color: var(--ps--fg); font-size: 12px; font-weight: 600;
    cursor: pointer;
}
.cc-inspector__if-option:hover { background: var(--ps--bg-soft); }
.cc-inspector__if-option:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring);
}
/* Bindung-lösen / {{#if}}-{{#each}}-wrap-unwrap actions are canonical
   .bx-btn (fast-follow T9b, reaffirmed Task 11) — disabled look comes from
   .bx-btn[disabled] (components.css), no bespoke chip style or :disabled
   override left here. */

/* Stil-Gruppen (Task 6, views/visual/inspector-groups.jsx) — one
   <section class="cc-inspector__group"> per INSPECTOR_GROUPS entry, below
   the class/collision/rename UI above. Tasks 7–8 append more groups; this
   section (and the shared .cc-inspector__field/.cc-inspector__linkbox
   rules) is where ALL of them live — no per-group snowflake styling.
   Werkstatt-Redesign Task 3 (spec §"Panel structure") made every section an
   ALWAYS-VISIBLE block (no <details>/<summary>). User-Feedback ("Sektionen
   ein-/ausklappbar wie in Framer") walks that back to per-group +/-
   collapse (inspector.jsx) — but the TITLE ELEMENT keeps its exact prior
   identity: `.cc-inspector__group-title` still holds ONLY the plain title
   text (asserted on in visual-inspector-groups.test.jsx), now on an inner
   <span> rather than the <h4> itself. The <h4> (`.cc-inspector__group-
   header`) instead wraps the whole clickable row — a <button> containing
   the title span AND a separate indicator span — which is the ARIA
   Authoring Practices accordion-header pattern ("the button is the only
   element inside the heading"), and keeps the +/- glyph from ever leaking
   into the title span's textContent. */
.cc-inspector__groups { margin-top: 14px; }
.cc-inspector__group {
    /* Runde 4: 14px → 8px Seitenpadding, gleicher Grund wie .cc-inspector__panel oben. */
    padding: 12px 8px;
    border-bottom: 1px solid var(--cc-insp-divider);
}
.cc-inspector__panel-title {
    margin: 0 0 8px;
    font: 800 10px var(--ps--font-sans);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ps--neutral-400);
}
.cc-inspector__group-header { margin: 0 0 8px; }
.cc-inspector__group-toggle {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; width: 100%; padding: 2px 0; margin: 0; border: 0; border-radius: 4px;
    background: transparent; color: inherit; font: inherit; text-align: left;
    cursor: pointer;
}
.cc-inspector__group-toggle:hover { background: var(--ps--bg-soft); }
.cc-inspector__group-toggle:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring);
}
.cc-inspector__group-title {
    font: 800 10px var(--ps--font-sans);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ps--neutral-400);
}
.cc-inspector__group-indicator {
    font: 800 12px var(--ps--font-mono, monospace);
    line-height: 1;
    color: var(--ps--neutral-400);
}
.cc-inspector__group-body { display: flex; flex-direction: column; gap: 8px; }

/* Shared declaration controls (DeclSelect/DeclInput/DeclColor) — Werkstatt-
   Redesign Task 4 (Framer-Politur, spec §5): two-column grid row, label
   left (88px fixed column, 11px --ps--fg-muted) | control right (1fr,
   fills the row). Same class also carries the "An Feld/Bild-Feld binden"
   and "In {{#if}} wickeln" label+select rows (inspector.jsx) — they get
   this exact same treatment "for free" via the shared class, no separate
   styling needed (spec's "analog" bullet). */
.cc-inspector__field {
    /* Runde 4 (H-Scroll-Fix, Härtung): a plain `1fr` track is an INTRINSIC/
       flexible sizing function — its base size during CSS Grid's track-
       sizing algorithm can be grown to fit the content-based (min-content)
       contribution of whatever sits in it, UNLESS the item opts out
       (min-width:0) or the track's min sizing function is a definite
       length. THEORETICALLY this means a `<select>`/`<input>` with a long
       value could blow this 1fr column past the ~144px it has room for —
       measured empirically in real Chromium (headless repro, aside pinned
       to 300px like the real default inspW), this specific path did NOT
       reproduce: percentage-width selects/inputs truncate/scroll their own
       overflow internally without growing the grid track (the CONFIRMED,
       measured cause was `.cc-inspector__block-buttons` below — see that
       rule's comment). `minmax(0, 1fr)` is kept here anyway as cheap,
       harmless defensive hardening (its min sizing function is the
       definite length `0`, so no item's content-based minimum CAN grow the
       track even in a browser/engine that behaves differently than the one
       measured here) — applies to every DeclSelect/DeclInput/DeclColor/
       DeclSegmented row via this one shared class, not a per-control patch. */
    display: grid; grid-template-columns: 88px minmax(0, 1fr); align-items: center; column-gap: 8px;
    font-size: 12px; color: var(--ps--neutral-600); font-weight: 600; min-height: 26px;
    position: relative; /* anchors the Task-2 hover ×-reset button below */
    min-width: 0; /* the field itself is also a flex item of .cc-inspector__group-body — same auto-min-size story one level up */
}
.cc-inspector__field > * { min-width: 0; } /* label span, select/input, color-row, segmented — none may re-introduce a content-based minimum */
.cc-inspector__field > span:first-child {
    color: var(--ps--fg-muted); font-size: 11px; font-weight: 600;
}
/* Inspector-Redesign Task 2 (README §3 "Label … Gesetzt: #1f473c + grüner
   5px-Punkt vor dem Label"): inspector-groups.jsx adds `.is-set` to the same
   first-child label span the instant the declaration has an explicit value
   — the dot itself is a ::before (no extra DOM node), so it never shows up
   in `span.textContent` (existing tests read the label text off this exact
   span).
   Round-3 Task 3 ("Labels geänderter Eigenschaften einfärben"): the label
   TEXT itself now turns brand-green (`--ps--brand`, was the darker
   near-black `--ps--fg`) and slightly bolder — the user's actual ask, "at a
   glance which properties are customized" — on top of the existing dot,
   which stays (still useful at a glance even once the text itself carries
   the color). One rule, `.cc-inspector__field > span:first-child.is-set`,
   covers EVERY control built on the shared `.cc-inspector__field` label
   grid — DeclSelect/DeclInput/DeclColor/DeclColorRow/DeclSegmented/
   DeclLinkedBox (both coupled and uncoupled)/OpacitySlider all render their
   label as that exact first-child span, so none of them need their own
   copy of this rule. `DeclMiniInput` is the one control that does NOT use
   `.cc-inspector__field` (dense N-up grids, no room for the 88px label
   column) — its own already-green `.cc-inspector__mini.is-set
   .cc-inspector__mini-prefix` rule further down covers it instead. */
.cc-inspector__field > span:first-child.is-set {
    color: var(--ps--brand); font-weight: 700;
}
.cc-inspector__field > span:first-child.is-set::before {
    content: ''; display: inline-block; width: 5px; height: 5px; margin-right: 5px;
    border-radius: 50%; background: var(--ps--brand); vertical-align: middle;
}
/* Amber MUST win over green on a non-Basis-Breakpoint override: `is-set` and
   `is-overridden` are true TOGETHER exactly when the active (non-Basis)
   breakpoint's OWN rule declares this property (see `isOverriddenHere`'s
   header comment above — getDeclarations at a given bp is scoped to just
   that bp's rule, never merged with Basis, so "has an own declaration here"
   and "is overridden here" are the same condition once activeBp is set).
   `is-overridden` sits on the WRAPPER (every control already toggles it
   there for its own control-level amber styling), not on the span like
   `is-set` — so this rule targets the wrapper + descendant span directly,
   independent of whether `.is-set` happens to be present too. Equal
   specificity to the green rule above (2 classes + the `:first-child`
   pseudo-class + the `span` type each) — declared AFTER it, so the tie
   resolves to amber, the exact same technique (and the exact same reason)
   `.cc-inspector__mini.is-overridden` uses further down for the mini-input
   prefix. */
.cc-inspector__field.is-overridden > span:first-child {
    color: var(--ps--warning-fg);
}
/* …and the set-dot follows the label to amber on an override, so text and dot
   never disagree (whole-branch review, round 3): same equal-specificity /
   later-source-order tie-break as the label-color rule above. */
.cc-inspector__field.is-overridden > span:first-child::before {
    background: var(--ps--warning-fg);
}
/* Controls: 26px, radius 6–7px, FILLED (neutral-100 bg, no border) instead
   of outlined — focus turns the fill white + the shared focus ring. Numeric
   fields (DeclInput with unit="px", plus the opacity % field) carry
   inputMode="numeric" already (inspector-groups.jsx, unrelated to this
   redesign) — reused here, attribute-selector only, as the "is this a
   number field" hook for right-aligned text, with zero JSX/prop changes. */
.cc-inspector__field select,
.cc-inspector__field input[type="text"] {
    width: 100%; box-sizing: border-box; height: 26px; padding: 0 8px; border: 1.5px solid transparent;
    border-radius: 7px; font-size: 12px; color: var(--ps--fg); background: var(--ps--neutral-100); outline: none;
    transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.cc-inspector__field select:focus,
.cc-inspector__field input[type="text"]:focus {
    background: var(--ps--neutral-0); border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring);
}
.cc-inspector__field input[inputmode="numeric"] { text-align: right; }
/* .cc-inspector__color-row's own layout (display:flex/gap) is defined ONCE,
   unscoped, further down (Task 7, DeclColorRow) — that rule now covers this
   context too (DeclColor's bare picker+text pair, reached via the popover),
   so the former `.cc-inspector__field--color .cc-inspector__color-row`
   duplicate was removed here (Task 13 consistency pass). */
.cc-inspector__field--color input[type="color"] {
    flex: 0 0 auto; width: 26px; height: 26px; padding: 2px; border: 1.5px solid transparent; border-radius: 7px;
    background: var(--ps--neutral-100); cursor: pointer;
}
.cc-inspector__field--color input[type="color"]:focus-visible {
    outline: none; border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring);
}
/* Amber-Override-Markierung (README §4): ein Wert, der auf dem AKTIVEN
   Nicht-Basis-Breakpoint überschrieben ist — inspector-groups.jsx setzt
   `is-overridden` auf genau den Feldern, wo getDeclarations(css, selector,
   activeBp) das Property tatsächlich enthält. */
.cc-inspector__field.is-overridden select,
.cc-inspector__field.is-overridden input[type="text"] {
    border-color: var(--ps--warning); background: var(--ps--warning-soft);
}
/* Override-Banner (Werkstatt-Redesign Inspector Task 12, README §11): Punkt +
   Hinweistext links, rechtsbündig der "Anzeigen"-Button
   (scrollToFirstOverride, inspector.jsx) — vorher ein reiner <p> ohne
   Aktion, jetzt eine flex-Zeile aus drei Teilen. */
.cc-inspector__override-banner {
    display: flex; align-items: center; gap: 8px;
    /* Runde 4: 14px → 8px Seiten-Margin, damit der Banner (kein
       .cc-inspector__group/__panel, richtet sich per Margin statt Padding
       aus) weiter bündig mit deren neuem 8px-Innenpadding abschließt. */
    margin: 0 8px 14px; padding: 9px 11px; border-radius: 9px;
    background: var(--ps--warning-soft);
}
.cc-inspector__override-dot {
    flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--ps--warning);
}
.cc-inspector__override-text {
    flex: 1 1 auto; min-width: 0; margin: 0;
    font: 700 11px var(--ps--font-sans); color: var(--ps--warning-fg); line-height: 1.4;
}
.cc-inspector__override-btn {
    flex: 0 0 auto; border: 0; background: transparent; padding: 2px 0; margin: 0;
    font: 800 11px var(--ps--font-sans); color: var(--ps--warning-fg); cursor: pointer;
    transition: opacity var(--ps--duration-fast);
}
.cc-inspector__override-btn:hover { opacity: .72; }
.cc-inspector__override-btn:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring); border-radius: 4px;
}
/* "Anzeigen" pulse (Task 12, README §11 "pulst dessen Amber-Markierung
   kurz"): scrollToFirstOverride (inspector.jsx) toggles `is-pulsing` on the
   FIRST `.is-overridden` element it finds (Fix round 1: broadened from a
   `.cc-inspector__field`-only query — `DeclMiniInput`'s Size/Typography
   mini-inputs mark `.cc-inspector__mini`, not `.cc-inspector__field`, so the
   old scoped selector silently found nothing there), removed via setTimeout
   after ~600ms. The animation lives on the pulsing element ITSELF (an
   outline-style box-shadow ring, not a nested select/input rule) because
   `DeclColorRow`/`DeclSegmented` have neither a `select` nor an
   `input[type="text"]` descendant — box-shadow (not border/background) so
   it never shifts layout. */
@keyframes cc-inspector-override-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(217, 119, 6, 0); }
    50% { box-shadow: 0 0 0 3px rgba(217, 119, 6, .55); }
}
.cc-inspector__field.is-pulsing,
.cc-inspector__mini.is-pulsing {
    border-radius: 7px;
    animation: cc-inspector-override-pulse 600ms ease-in-out;
}
/* Hex/CSS free-text field next to the color swatch stays a fixed compact
   width (not the general 100%-fill rule above) — plain hex/var() text,
   left-aligned (no inputMode="numeric" on it, so the general right-align
   rule above does not apply here either). */
.cc-inspector__field--color input[type="text"] { width: 96px; flex: 0 1 auto; text-align: left; }

/* Inspector-Redesign Task 2 (README §3 "Default-Werte NEU" + "Gesetzte Werte
   … 700 12px #1f473c"): an entered value renders bold; the grey computed-
   default placeholder (inspector-groups.jsx `defaultDisplay()`) is the
   lighter, non-bold hint shown instead while the field is unset. */
.cc-inspector__field input[type="text"] {
    font-weight: 700;
}
.cc-inspector__field input[type="text"]::placeholder {
    color: var(--ps--neutral-400); font-weight: 600; opacity: 1;
}

/* Hover ×-reset (README §3 "×-Reset-Affordanz bei Hover"): absolutely
   positioned over the field's own row so it needs no grid-column of its own
   — rendered by inspector-groups.jsx (DeclInput/DeclSelect/DeclColor) only
   while the prop IS set; visibility itself (hidden until row hover/focus) is
   pure CSS, so it stays in the DOM (and findable by tests) regardless of the
   mouse. */
.cc-inspector__reset {
    position: absolute; top: 50%; right: 2px; transform: translateY(-50%);
    width: 18px; height: 18px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
    border: none; border-radius: 5px; background: transparent; color: var(--ps--neutral-400);
    cursor: pointer; opacity: 0;
    transition: opacity var(--ps--duration-fast), background var(--ps--duration-fast), color var(--ps--duration-fast);
}
.cc-inspector__field:hover .cc-inspector__reset,
.cc-inspector__field:focus-within .cc-inspector__reset,
.cc-inspector__reset:focus-visible {
    opacity: 1;
}
.cc-inspector__reset:hover { background: var(--ps--neutral-200); color: var(--ps--fg); }
.cc-inspector__reset:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring); }

/* Segmented control (README §3 "Segmented Control" + DeclSegmented,
   Inspector-Redesign Task 2): reuses `.cc-inspector__field`'s 2-column grid
   (label | control) — `.cc-inspector__field--segmented` needs no layout
   rules of its own, only the segmented row itself. */
.cc-inspector__segmented {
    /* Runde 4 (H-Scroll-Fix): min-width:0 — flex containers get the same
       auto-content-based-minimum treatment as grid items; already covered by
       .cc-inspector__field > * above, restated here since .cc-inspector__seg
       children already opt out (flex:1 1 0; min-width:0) but the row itself
       didn't. */
    display: flex; gap: 2px; padding: 2px; border-radius: 8px; background: var(--ps--neutral-100);
    min-width: 0;
}
.cc-inspector__seg {
    flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center; justify-content: center;
    height: 22px; padding: 0 4px; border: none; border-radius: 6px; background: transparent;
    color: var(--ps--neutral-400); font: 700 10.5px var(--ps--font-sans); cursor: pointer;
    transition: background var(--ps--duration-fast), color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.cc-inspector__seg[aria-pressed="true"] {
    background: var(--ps--neutral-0); color: var(--ps--fg); box-shadow: 0 1px 3px rgba(31, 71, 60, .14);
}
.cc-inspector__seg:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring); }
.cc-inspector__field--segmented.is-overridden .cc-inspector__segmented {
    background: var(--ps--warning-soft); box-shadow: inset 0 0 0 1.5px var(--ps--warning);
}
/* Rahmen/border-style (Inspector-Redesign Task 8, README §8 "Icon-Segmented
   `Kein | — | ┄ | ┈`"): the segment CONTENT is a plain text glyph standing in
   for an icon (DeclSegmented's `glyph` prop) — larger and lighter than the
   default 10.5px/700 word labels (Block/Flex/…, Links/Mitte/…) so the glyphs
   themselves read clearly at a glance. */
.cc-inspector__segmented--glyph .cc-inspector__seg {
    font-size: 15px; font-weight: 600;
}

/* Mini-Input mit Präfix-Buchstabe (README §3, DeclMiniInput — Inspector-
   Redesign Task 2): dense N-up grids (Size/Spacing/Typography, spätere
   Tasks) reihen mehrere davon nebeneinander; hier nur das EINZELNE Control. */
.cc-inspector__mini {
    display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 7px;
    border-radius: 7px; background: var(--ps--neutral-100); border: 1.5px solid transparent;
    transition: background var(--ps--duration-fast), border-color var(--ps--duration-fast), box-shadow var(--ps--duration-fast);
}
.cc-inspector__mini:focus-within {
    background: var(--ps--neutral-0); border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring);
}
.cc-inspector__mini-prefix {
    font: 800 9px var(--ps--font-sans); color: var(--ps--neutral-400); letter-spacing: .02em;
}
/* Gesetztes Feld (README §3/§6): grüner Präfix + #b6d9cc-Outline — dieselbe
   Rand-Farbe wie die aktive Stil-Klassen-Chip (--cc-insp-chip-active-border,
   s. .cc-inspector-Block oben). is-overridden (Amber) kommt bewusst NACH
   is-set im Quelltext, damit der Override bei gleicher Spezifität gewinnt. */
.cc-inspector__mini.is-set { border-color: var(--cc-insp-chip-active-border); }
.cc-inspector__mini.is-set .cc-inspector__mini-prefix { color: var(--ps--brand); }
.cc-inspector__mini.is-overridden { background: var(--ps--warning-soft); border-color: var(--ps--warning); }
.cc-inspector__mini.is-overridden .cc-inspector__mini-prefix { color: var(--ps--warning-fg); }
.cc-inspector__mini-input {
    flex: 1 1 auto; width: 100%; min-width: 0; height: 100%; border: none; background: transparent;
    outline: none; padding: 0; font-size: 12px; font-weight: 700; color: var(--ps--fg); text-align: right;
}
.cc-inspector__mini-input::placeholder { color: var(--ps--neutral-400); font-weight: 600; opacity: 1; }

/* Größe (Size group, Inspector-Redesign Task 5, README §6): 2×2-mini-input
   grid — B/H, Min B/Max B, Min H/Max H — two equal columns; each
   DeclMiniInput stretches to fill its cell (it's inline-flex by default). */
.cc-inspector__size-grid {
    /* Runde 4 (H-Scroll-Fix): minmax(0, 1fr) statt plain 1fr — same reasoning
       as .cc-inspector__field above, applied to this grid's own two tracks;
       min-width:0 since this grid is itself a flex item of
       .cc-inspector__group-body (column flex, auto-min-size story one level
       up again). */
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px;
    min-width: 0;
}
.cc-inspector__size-grid .cc-inspector__mini { width: 100%; box-sizing: border-box; min-width: 0; }

/* Abstände (Spacing group, Inspector-Redesign Task 6, README §5) — ersetzt
   das alte Box-Model-Rechteck: EIN gekoppeltes Input + Link-Toggle pro Box
   (Innen/Außen), Toggle klappt auf ein 2×2-Grid aus vier Mini-Inputs
   (O/R/U/L) um. `.cc-inspector__linkbox` bleibt ein `.cc-inspector__field`
   (label 88px | control 1fr, s. o.) — nur die control-Spalte bekommt hier
   zusätzlich `-row`, das Input-oder-Grid und den Toggle nebeneinander legt. */
.cc-inspector__linkbox-row {
    display: flex; align-items: center; gap: 6px; min-width: 0;
}
.cc-inspector__linkbox-row > input[type="text"] { flex: 1 1 auto; min-width: 0; }
.cc-inspector__linkbox-grid {
    /* Runde 4: minmax(0, 1fr) tracks, same reasoning as .cc-inspector__field/
       .cc-inspector__size-grid above — min-width:0 on the grid itself was
       already present. */
    flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px;
}
.cc-inspector__linkbox-grid .cc-inspector__mini { width: 100%; box-sizing: border-box; min-width: 0; }
/* Radius corner-link (Inspector-Redesign Task 8, README §8 "Radius … gleiches
   O/R/U/L-Muster sinngemäß mit Ecken-Präfixen"): BordersGroup's Eckenradius
   reuses DeclLinkedBox (generalized this task) with the four border-radius
   corner longhands instead of padding/margin sides — same coupled input +
   link-toggle + 2×2 uncoupled grid, so it needs none of its own selectors
   here, only this note that the corner grid IS `.cc-inspector__linkbox-grid`
   above (OL/OR/UR/UL prefixes instead of O/R/U/L, via `.cc-inspector__mini`,
   also unchanged). */
/* Link-Toggle (README §5): 26×26px, radius 7px — gekoppelt grün/brand-soft,
   entkoppelt neutral-grau; reiner UI-State (inspector-groups.jsx `linked`),
   nie persistiert. */
.cc-inspector__link-toggle {
    flex: 0 0 auto; width: 26px; height: 26px; padding: 0; border: none; border-radius: 7px;
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    background: var(--ps--neutral-100); color: var(--ps--neutral-400);
    transition: background var(--ps--duration-fast), color var(--ps--duration-fast);
}
.cc-inspector__link-toggle.is-linked { background: var(--ps--brand-soft); color: var(--ps--brand); }
.cc-inspector__link-toggle:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ps--focus-ring); }

/* Typografie (Typography group, Inspector-Redesign Task 7, README §7): GR/LH/
   LS as a dense 3-up mini-input grid — same family as .cc-inspector__size-
   grid above, just three equal columns instead of two. */
.cc-inspector__typo-grid {
    /* Runde 4: minmax(0, 1fr) tracks + min-width:0, same reasoning as
       .cc-inspector__size-grid above. */
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px;
    min-width: 0;
}
.cc-inspector__typo-grid .cc-inspector__mini { width: 100%; box-sizing: border-box; min-width: 0; }

/* Farb-Zeile (DeclColorRow, Inspector-Redesign Task 7, README §7 "Farbe" —
   Task 8 reuses this component verbatim for Hintergrund-/Rahmenfarbe, README
   §8 "Farb-Zeile wie oben"): swatch (18×18, radius 5) + value text, replacing
   the bare DeclColor picker+text pair as the default in-panel look. This
   base `.cc-inspector__color-row` rule now covers BOTH contexts — the new
   swatch+value row here, and DeclColor's own (unchanged) picker+text pair
   once it's opened inside the popover below, which used to be reachable only
   via the narrower `.cc-inspector__field--color .cc-inspector__color-row`
   selector further up. */
.cc-inspector__color-row { display: flex; align-items: center; gap: 6px; }
.cc-inspector__color-swatch {
    flex: 0 0 auto; width: 18px; height: 18px; padding: 0; border-radius: 5px;
    border: 1.5px solid var(--ps--border); background: var(--ps--neutral-100); cursor: pointer;
}
.cc-inspector__color-swatch:focus-visible {
    outline: none; border-color: var(--ps--primary); box-shadow: 0 0 0 3px var(--ps--focus-ring);
}
/* Value text (README §7): Theme-Token mono violett, Hex mono neutral,
   ungesetzt grau (nicht-mono, wie die übrigen Default-Platzhalter). */
.cc-inspector__color-value {
    font-family: var(--ps--font-mono, monospace); font-size: 11.5px; font-weight: 700;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cc-inspector__color-value--unset {
    font-family: var(--ps--font-sans); font-size: 12px; font-weight: 600; color: var(--ps--neutral-400);
}
.cc-inspector__color-value--hex { color: var(--ps--fg); }
.cc-inspector__color-value--token { color: var(--ps--cms-strong); }
/* Popover hosting the existing DeclColor (README §7 "Klick auf Swatch öffnet
   … als Popover") — same card family as .cc-elpanel (white, border, radius,
   shadow) but anchored to its own field row, which is already `position:
   relative` (s. .cc-inspector__field above), so no extra positioning
   context is needed. `left: 88px` lines up with the field grid's own label
   column width, so the popover starts under the control column, not the
   label. The nested DeclColor loses its own label column (redundant here —
   the popover already sits right under the labelled swatch row) and its
   picker+text pair simply fills the popover's width. */
.cc-inspector__color-popover {
    position: absolute; top: 100%; left: 88px; z-index: 20; margin-top: 4px;
    padding: 10px; border-radius: 9px; border: 1px solid var(--ps--border);
    background: var(--ps--neutral-0, #fff); box-shadow: var(--ps--shadow-md);
}
.cc-inspector__color-popover .cc-inspector__field { grid-template-columns: minmax(0, 1fr); min-height: 0; }
.cc-inspector__color-popover .cc-inspector__field > span:first-child { display: none; }
/* DeclColorRow already renders its OWN reset button outside the popover
   (same `label`, so same aria-label) — the nested DeclColor inside the
   popover would otherwise render a second, visually identical "…
   zurücksetzen" button when a value is set (Task 13 Minor finding). Hide it
   here, mirroring the label-span hiding rule above; both DOM nodes stay
   mounted (existing tests still find/click the outer one), only the inner
   one is visually suppressed. */
.cc-inspector__color-popover .cc-inspector__reset { display: none; }

/* Deckkraft (Effects group, Inspector-Redesign Task 9, README §9): native
   `<input type="range">` + a 46px `%`-field, sharing the row via
   .cc-inspector__slider-row (same family as .cc-inspector__linkbox-row —
   control(s) + a fixed-width companion side by side). There is no
   cross-browser selector for "the track up to the thumb", so
   inspector-groups.jsx writes the current value as an inline
   `--cc-slider-pct` custom property every render, and this rule paints the
   FILLED portion (0…pct) with `--cc-slider-fill` up to that stop, then the
   flat `#e3e8e6` track color for the remainder — `--cc-slider-fill` itself
   has no inline value; it only gets one from the `.is-set` override below,
   so the *color* switch (grey -> green) is pure CSS off the class the
   component already computes for the label dot. */
.cc-inspector__slider-row { display: flex; align-items: center; gap: 8px; }
.cc-inspector__slider {
    -webkit-appearance: none; appearance: none;
    flex: 1 1 auto; min-width: 0; height: 4px; border-radius: 99px; margin: 0;
    background: linear-gradient(to right,
        var(--cc-slider-fill, var(--ps--neutral-300)) 0%,
        var(--cc-slider-fill, var(--ps--neutral-300)) var(--cc-slider-pct, 100%),
        var(--ps--neutral-200) var(--cc-slider-pct, 100%),
        var(--ps--neutral-200) 100%);
    outline: none; cursor: pointer;
}
.cc-inspector__slider.is-set { --cc-slider-fill: var(--ps--brand); }
/* Track pseudo-elements themselves stay transparent — the gradient on the
   input's own `background` above (visible through the track) is what
   actually renders the two-tone fill/track look. */
.cc-inspector__slider::-webkit-slider-runnable-track { height: 4px; background: transparent; }
.cc-inspector__slider::-moz-range-track { height: 4px; border-radius: 99px; background: transparent; }
/* Daumen: 12px weiß mit Rahmen (README §9) — Rahmenfarbe folgt derselben
   --cc-slider-fill-Variable wie die Füllung (grau unset / grün gesetzt). */
.cc-inspector__slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 12px; height: 12px; border-radius: 99px; margin-top: -4px;
    background: #fff; border: 1.5px solid var(--cc-slider-fill, var(--ps--neutral-300));
    box-shadow: 0 1px 2px rgba(31, 71, 60, .2); cursor: pointer;
}
.cc-inspector__slider::-moz-range-thumb {
    width: 12px; height: 12px; border-radius: 99px; border: 1.5px solid var(--cc-slider-fill, var(--ps--neutral-300));
    background: #fff; box-shadow: 0 1px 2px rgba(31, 71, 60, .2); cursor: pointer;
}
.cc-inspector__slider:focus-visible { box-shadow: 0 0 0 3px var(--ps--focus-ring); }
/* %-Feld: fixe 46px-Breite statt der generischen 100%-Fill-Regel — Text/
   Placeholder-Farben, Fettung, Fokus-Ring etc. kommen bereits „for free" von
   der bestehenden `.cc-inspector__field input[type="text"]`-Regel weiter
   oben (nur die Breite ist hier abweichend). */
.cc-inspector__slider-pct { flex: 0 0 46px; width: 46px; text-align: right; }

/* =========================================================================
   Auswahl-Zustand — EINE projektweite Definition
   =========================================================================
   „Dieses Element ist ausgewählt“ gab es fünfmal verschieden: der Seitenaufbau
   trug eine Kante, die es nur LINKS gab (inset 2px 0 0), der Seitenbaum keine,
   die Verwaltung eine weiße Fläche mit Ring rundum, die Sprungmarken eine
   Tönung, die Hilfe eine Tönung ohne Textwechsel. Vier davon sahen zufällig
   ähnlich aus, keine zwei gleich.

   Erhoben wurden SIEBEN Orte, nicht fünf: dazu kamen die Medien-Ordner-
   Navigation (.da-foldernav) und der Projektwechsler (.ps-switchMenu__item),
   beide auf --ps--primary-soft, der Ordnername sogar auf --ps--brand-dark
   bei Gewicht 600. Wer „einheitlich“ behauptet, muss die Liste erheben —
   der Wächter tut das jetzt und fordert für jede Ausnahme eine Begründung.

   Ab hier gilt für Listen, Bäume und Subnavigationen genau diese Regel:
   getönte Fläche + Akzentrahmen RUNDUM + weicher Akzent-Glow. Der Glow ist
   derselbe Gedanke wie bei den farbigen Studio-Buttons (0 2px 8px), damit die
   Auswahl zur bestehenden Formensprache gehört statt daneben zu stehen.

   Wer einen neuen Bereich mit Auswahl baut, hängt seinen Selektor HIER an —
   nicht daneben, mit eigenen Werten. tests/js/styles/selected-state.test.js
   fällt um, wenn eine Regel andernorts wieder eine eigene Auswahl-Fläche setzt.

   NICHT hier drin, mit Absicht:
   • das Hauptmenü (.cp-side__item/.ps-side__item) — eine Ebene höher, voll
     gefüllt, und soll sich vom Auswahl-Zustand darunter unterscheiden;
   • Segment-Schalter, Chips und Tabs — andere Bauteile, kein Listen-Element;
   • der Element-Baum der Werkstatt (.cc-tree__row) — trägt eigene Badges und
     Tags, die auf seine Auswahl-Fläche abgestimmt sind.
   ========================================================================= */
.ps-selected,
.bd-layer.is-selected,
.bd-page.is-current,
.cp-subnav__item.is-active,
.cp-subnav__anchor.is-active,
.ps-help__item.is-active,
.da-foldernav.is-active,
.ps-switchMenu__item.is-active,
.ph-item.is-selected {
  background: var(--ps--sel-bg);
  color: var(--ps--primary);
  font-weight: 700;
  box-shadow: inset 0 0 0 1px var(--ps--sel-border), var(--ps--sel-glow);
}
/* Kind-Elemente, die ihre eigene Farbe tragen und deshalb mitziehen müssen. */
.bd-layer.is-selected .bd-layer__name,
.bd-page.is-current .bd-tree__name,
.bd-page.is-current .bd-tree__icon,
.ps-help__item.is-active .ps-help__itemT,
.da-foldernav.is-active .da-foldernav__name,
.da-foldernav.is-active .da-foldernav__main > i {
  color: var(--ps--primary);
}
