/* Layout der neuen Shell-Regionen. Nutzt ausschliesslich die Tokens aus tokens.css —
   in dieser Datei steht kein einziger Hex-Wert. */

/* viewer.html setzt kein globales box-sizing. Ohne diesen auf die Shell begrenzten Reset
   addiert sich jedes Padding zur Breite — die Bodenleiste lief dadurch 16 px ueber den
   Bildschirmrand hinaus. Bewusst NICHT global: die alte Shell rechnet mit content-box. */
.shell-topbar-host, .shell-topbar-host *,
.shell-rail-host, .shell-rail-host *,
.shell-dock, .shell-dock *,
.shell-chip, .shell-chip *,
.more-menu, .more-menu *,
.share-menu, .share-menu *,
.shell-workshop, .shell-workshop *,
.shell-help-backdrop, .shell-help-backdrop *{ box-sizing:border-box }

/* ---------- Topbar: die eine Navigationsebene ---------------------------- */

/* Container-Kontext. Die Shell reagiert auf IHRE eigene Breite, nicht auf die des
   Fensters — sonst stimmt das Layout nicht mehr, sobald das Dock Platz nimmt. */
.shell-topbar-host{ container-type:inline-size; container-name:topbar; width:100% }

.shell-topbar{
  display:flex; align-items:center; gap:var(--sp-2);
  height:var(--topbar-h); min-height:var(--topbar-h);
  padding:0 var(--sp-2);
  background:var(--surface); color:var(--ink);
  border-bottom:1px solid var(--line);
  font:var(--font-ui);
  /* Die Leiste selbst darf nicht schrumpfen; ihre Gruppen tun es (s. u.). */
  flex:0 0 auto;
}

.shell-topbar .tb-group{ display:flex; align-items:center; gap:var(--sp-1) }
/* Drei Zonen, und die beiden aeusseren sind IMMER gleich breit — `flex:1 1 0` verteilt
   den Platz nach Wachstum, nicht nach Inhalt. Das ist der Kern gegen das Flackern: die
   Avatarleiste aendert ihre Breite bei jedem Praesenz-Ereignis, und in einer normalen
   Flex-Zeile schoebe das das Modus-Segment jedes Mal zur Seite (gemessen: 175 px Wanderung).
   So bleibt das Segment stehen, egal was links oder rechts passiert.

     .tb-left   Marke, Modellname, Undo/Redo — schrumpft (Name hat eine Ellipse)
     .tb-segment die Modus-Achse — feste Breite, fester Platz
     .tb-end    Live-Anzeige und Knoepfe; darin schrumpfen nur Text und Avatare,
                die Knoepfe nie (sonst laufen sie unter das Segment) */
.shell-topbar .tb-left{ flex:1 1 0; min-width:0 }
.shell-topbar .tb-segment{ flex:0 0 auto }
.shell-topbar .tb-end{ display:flex; align-items:center; gap:var(--sp-2);
  flex:1 1 0; min-width:0; justify-content:flex-end }
.shell-topbar .tb-live{ display:flex; align-items:center; gap:var(--sp-2);
  flex:0 1 auto; min-width:0; justify-content:flex-end }
.shell-topbar .tb-live:empty{ display:none }
.shell-topbar .tb-right{ flex:0 0 auto; justify-content:flex-end }

.shell-topbar .tb-brand{ display:flex; align-items:center; flex:0 0 auto; padding:0 var(--sp-1) }
.shell-topbar .tb-mark{ width:20px; height:20px; display:block }

/* Dokument: Name mit Dirty-Punkt. Der Name weicht als Erster, mit Ellipse statt Umbruch. */
/* NICHT wachsen: sonst dehnt sich der Namensbereich ueber die freie Breite und Undo/Redo
   schwimmen mitten in der Leiste statt neben dem Namen zu stehen. */
.shell-topbar .tb-doc{ display:flex; align-items:center; gap:var(--sp-1); min-width:0; flex:0 1 auto }
.shell-topbar .tb-docname{
  font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.shell-topbar .tb-docname.muted{ color:var(--ink-mut); font-weight:400 }
.shell-topbar .tb-dirty{
  width:8px; height:8px; border-radius:50%; flex:0 0 auto;
  background:transparent; transition:background .15s;
}
.shell-topbar .tb-dirty.on{ background:var(--q-yellow) }

/* Trefferflaechen: --hit ist Abnahmekriterium (Ticket 01), auch auf dem Desktop. */
.shell-topbar button{
  font:inherit; color:inherit; background:none; border:0; cursor:pointer;
  min-width:var(--hit); min-height:var(--hit);
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-1);
  border-radius:var(--r-md); padding:0 var(--sp-2);
}
.shell-topbar button:hover{ background:var(--surface2) }
.shell-topbar button:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }

.shell-topbar .tb-icon{ font-size:16px; flex:0 0 auto; padding:0 }
.shell-topbar .tb-text{ white-space:nowrap; flex:0 0 auto }

/* Modus-Segment: genau zwei Modi, mittig, weicht als Letztes. */
.shell-topbar .tb-segment{
  display:flex; align-items:center; gap:2px; flex:0 0 auto;
  background:var(--surface2); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:2px;
}
.shell-topbar .tb-mode{ white-space:nowrap; border-radius:var(--r-md) }
.shell-topbar .tb-mode.on{ background:var(--accent); color:var(--on-accent) }
.shell-topbar .tb-mode.on:hover{ background:var(--accent) }
.shell-topbar .tb-mode-glyph{ font-size:14px }

.shell-topbar .tb-share{
  background:var(--accent); color:var(--on-accent); white-space:nowrap; flex:0 0 auto; font-weight:600;
}
.shell-topbar .tb-share:hover{ background:var(--accent); filter:brightness(1.08) }

/* Umgekehrt als zunaechst gedacht — die Messung hat es entschieden: die AVATARE weichen
   zuerst. Sie haben mit dem Sammel-Chip "+N" eine ehrliche Verkleinerung und verschwinden
   notfalls ganz, ohne dass Information verloren geht, denn die Teilnehmerzahl steht im
   Text. Der Text dagegen hat keine Verkleinerung: er wurde auf 24 px zusammengequetscht
   und war damit unlesbar — ein Schnipsel ist schlechter als gar nichts. */
.shell-topbar .tb-livestatus{
  color:var(--ink-mut); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  /* Der Status nimmt den Restplatz; ein kuerzerer Avatar-Streifen darf ihn
     nicht wieder vergroessern und den eigenen Namensknopf verdrängen. */
  flex:1 1 0; min-width:9ch; max-width:30ch;
}
.shell-topbar .tb-livestatus:empty{ display:none }

/* Avatarleiste: schrumpft mit hoher Prioritaet, damit sie nie die Leiste sprengt. */
/* ACHTUNG Spezifitaet: liveEnsureCss() injiziert zur Laufzeit eine Regel auf #live-avatars
   (ID, 1-0-0). Ein Klassen-Selektor wie .tb-avatars (0-1-0) verliert dagegen — jede
   Anpassung hier waere wirkungslos und man sucht den Fehler lange woanders. Deshalb ID
   plus Klasse.

   Die Leiste darf so gross bleiben wie moeglich: seit die Aussenzonen gleich breit sind,
   wandert durch eine Breitenaenderung hier nichts mehr. liveFitAvatars() entscheidet dann
   ehrlich, wie viele Gesichter hineinpassen und was in den Sammel-Chip wandert. */
.shell-topbar .tb-avatars{ display:flex; align-items:center; gap:3px; min-width:0; overflow:hidden }
.shell-topbar #live-avatars{ flex:0 1 auto; min-width:0; padding:0 }
.shell-topbar .tb-avatars:empty{ display:none }

/* ---------- schmale Breiten -------------------------------------------------
   Abnahmekriterium aus Ticket 01: jede Funktion bei 768 und 375 px erreichbar.
   Beschriftungen weichen vor Funktionen; was ganz verschwindet, meldet topbar.js ueber
   overflowActions() an — es MUSS dann im Mehr-Menue auftauchen. */

@container topbar (max-width:820px){
  .shell-topbar .tb-text .tb-label,
  .shell-topbar .tb-share .tb-label{ display:none }     /* nur noch das Symbol */
  .shell-topbar .tb-text,
  .shell-topbar .tb-share{ min-width:var(--hit); padding:0 }
}

@container topbar (max-width:520px){
  .shell-topbar{ padding:0 var(--sp-1); gap:var(--sp-1) }

  /* Die gleich breiten Aussenzonen sind hier kontraproduktiv: die Endzone bekaeme nur die
     Haelfte, ihre Knoepfe brauchen aber mehr — sie liefen unter das Segment. Auf schmalen
     Breiten ist die Live-Anzeige ohnehin ausgeblendet, also gibt es auch nichts, was
     wandern koennte. Daher hier wieder nach Inhalt. */
  .shell-topbar .tb-left{ flex:1 1 auto }
  .shell-topbar .tb-end{ flex:0 0 auto }
  .shell-topbar .tb-brand{ display:none }
  .shell-topbar .tb-mode-label{ display:none }          /* Modus-Segment: nur Symbole */
  .shell-topbar .tb-mode{ min-width:var(--hit); padding:0 }
  .shell-topbar .tb-livestatus{ display:none }          /* Zustand steht im Buehnen-Chip */

  /* Was hier verschwindet, MUSS das Mehr-Menue anbieten — siehe overflowActions() in
     topbar.js. Verstecken ohne Ersatz waere ein stiller Funktionsverlust. */
  .shell-topbar .tb-collapsible{ display:none }
}

/* ---------- Rail: Werkzeuge und Bauteil-Faecher --------------------------- */

/* Die Breite MUSS hier stehen: container-type:inline-size nimmt einem Element die
   Groesse nach Inhalt (das ist der Sinn von Containment). Ohne sie fiel der Container auf
   0 zusammen, und die Rail lag ueber der Buehne statt neben ihr. */
.shell-rail-host{ display:flex; align-items:stretch; position:relative;
  width:var(--rail-w); flex:0 0 auto;
  container-type:inline-size; container-name:rail }

.shell-rail{
  display:flex; flex-direction:column; justify-content:space-between;
  width:var(--rail-w); min-width:var(--rail-w); flex:0 0 auto;
  padding:var(--sp-2) 0; gap:var(--sp-2);
  background:var(--surface); border-right:1px solid var(--line);
  overflow-y:auto; overflow-x:hidden;
}
.shell-rail .rail-group{ display:flex; flex-direction:column; gap:var(--sp-1); align-items:center }

/* Jeder Eintrag traegt SICHTBAREN Text — nie nur ein Icon. Der Review fand echte
   Duplikate, die ohne Beschriftung nicht unterscheidbar waren. */
.shell-rail .rail-item{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
  width:calc(var(--rail-w) - var(--sp-2) * 2); min-height:var(--hit);
  padding:var(--sp-1) 2px; border:0; border-radius:var(--r-md);
  background:none; color:var(--ink); font:var(--font-ui); cursor:pointer;
}
.shell-rail .rail-item:hover{ background:var(--surface2) }
.shell-rail .rail-item:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.shell-rail .rail-item.on{ background:var(--accent); color:var(--on-accent) }
.shell-rail .rail-glyph{ font-size:18px; line-height:1 }
.shell-rail .rail-label{ font-size:10px; line-height:1.15; text-align:center; hyphens:auto; overflow-wrap:anywhere }

/* ---------- Katalog-Flyout ------------------------------------------------- */

.rail-flyout{
  position:absolute; left:var(--rail-w); top:var(--sp-2); z-index:20;
  width:min(320px, calc(100vw - var(--rail-w) - var(--sp-4)));
  max-height:calc(100% - var(--sp-4));
  display:flex; flex-direction:column;
  background:var(--surface); color:var(--ink);
  border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow);
}
.rail-flyout[hidden]{ display:none }
.rail-flyout .fly-head{ display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2); padding:var(--sp-3) }
.rail-flyout .fly-title{ font:var(--font-ui); font-size:15px; font-weight:700; margin:0 }
.rail-flyout .fly-close{
  border:0; background:none; color:var(--ink-mut); cursor:pointer; font-size:15px;
  min-width:var(--hit); min-height:var(--hit); border-radius:var(--r-md);
}
.rail-flyout .fly-close:hover{ background:var(--surface2); color:var(--ink) }
.rail-flyout .fly-body{ padding:0 var(--sp-3) var(--sp-3); overflow-y:auto }

/* ---------- Karten-Katalog -------------------------------------------------
   Das ist der Kern des Umbaus: Bild plus Name plus Bestand statt eines 22-px-Icons. */

.cat-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(130px,1fr)); gap:var(--sp-2) }
.cat-card{
  display:flex; flex-direction:column; align-items:center; gap:var(--sp-1);
  padding:var(--sp-3) var(--sp-2); min-height:96px;
  background:var(--surface2); border:1px solid var(--line); border-radius:var(--r-md);
  color:var(--ink); font:var(--font-ui); cursor:pointer; text-align:center;
}
.cat-card:hover{ border-color:var(--accent) }
.cat-card:focus-visible{ outline:2px solid var(--accent); outline-offset:1px }
.cat-card[aria-selected=true]{ border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent) }
.cat-icon{ width:32px; height:32px; display:block }
.cat-name{ font-size:13px; font-weight:600; line-height:1.25 }
.cat-stock{ font:var(--font-num); font-size:11px }
.cat-stock.have{ color:var(--q-green) }
.cat-stock.none{ color:var(--danger) }
/* "Bestand unbekannt" ist eine ehrliche Aussage, keine Warnung — deshalb gedaempft. */
.cat-stock.unknown{ color:var(--ink-mut) }
.cat-note{ margin:var(--sp-3) 0 0; color:var(--ink-mut); font-size:12px; line-height:1.4 }

@container rail (max-width:60px){
  .shell-rail .rail-label{ display:none }   /* Notfall: nur wenn wirklich kein Platz ist */
}

/* ---------- Panel-Dock ----------------------------------------------------
   Loest das stille gegenseitige Verdraengen der alten Panels: ein Tab ist aktiv, die
   anderen behalten ihren Zustand (versteckt, nicht zerstoert). */

.shell-dock{
  display:flex; flex-direction:column;
  width:var(--dock-w); min-width:0; flex:0 0 auto;
  background:var(--surface); border-left:1px solid var(--line);
  font:var(--font-ui); color:var(--ink);
  container-type:inline-size; container-name:dock;
}
.shell-dock[hidden]{ display:none }
.shell-dock .dock-head{ display:flex; align-items:center; gap:var(--sp-2); padding:var(--sp-2) var(--sp-2) 0; border-bottom:1px solid var(--line) }
.shell-dock .dock-tabs{ display:flex; gap:2px; overflow-x:auto; flex:1 1 auto; min-width:0 }
/* Vier Tabs muessen in die Dock-Breite passen, ohne dass der letzte hinter dem
   Schliesskreuz verschwindet. Bei 360 px Dock bleiben nach Schliesskreuz und Innenabstand
   rund 290 px — also gut 70 px je Tab. Der Scrollbalken bleibt als Sicherheitsnetz. */
.shell-dock .dock-tab{
  border:0; background:none; color:var(--ink-mut); cursor:pointer; font:inherit;
  font-size:13px; padding:var(--sp-2) var(--sp-1); min-height:var(--hit); white-space:nowrap;
  border-bottom:2px solid transparent; border-radius:var(--r-sm) var(--r-sm) 0 0;
  flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis;
}
.shell-dock .dock-tab:hover{ background:var(--surface2); color:var(--ink) }
.shell-dock .dock-tab:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.shell-dock .dock-tab.on{ color:var(--ink); font-weight:600; border-bottom-color:var(--accent) }
.shell-dock .dock-close{
  border:0; background:none; color:var(--ink-mut); cursor:pointer;
  min-width:var(--hit); min-height:var(--hit); border-radius:var(--r-md); flex:0 0 auto;
}
.shell-dock .dock-close:hover{ background:var(--surface2); color:var(--ink) }
.shell-dock .dock-body{ flex:1 1 auto; overflow:auto; padding:var(--sp-3) }
.shell-dock .dock-panel[hidden]{ display:none }

/* ---------- Buehnen-Chip ---------------------------------------------------
   Ersetzt die 12-px-Statuszeile, in der der aktive Modus zwar ehrlich, aber praktisch
   unsichtbar stand. */

.shell-chip{
  display:inline-flex; align-items:center; gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-3);
  background:var(--chip-bg); color:var(--ink);
  border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow);
  font:var(--font-ui); backdrop-filter:blur(6px); max-width:min(560px,90cqw);
}
.shell-chip .chip-glyph{ font-size:15px; line-height:1 }
.shell-chip .chip-text{ font-weight:700; white-space:nowrap }
.shell-chip .chip-hint{ color:var(--ink-mut); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0 }
.shell-chip.bauen{ border-color:var(--accent) }
.shell-chip kbd{
  font:var(--font-num); background:var(--surface2); color:var(--ink);
  border:1px solid var(--line); border-bottom-width:2px; border-radius:var(--r-sm); padding:1px 5px;
}

/* ---------- Hilfe-Overlay --------------------------------------------------
   Der alte Legendenblock mass 901 x 139 px und stand DAUERHAFT neben der Buehne.
   Derselbe Inhalt, aber auf Abruf und ueber der Buehne: geschlossen kostet er nichts. */

.shell-help-backdrop{
  position:fixed; inset:0; z-index:60;
  display:flex; align-items:center; justify-content:center; padding:var(--sp-4);
  background:rgba(15,23,32,.45);
}
.shell-help-backdrop[hidden]{ display:none }
.help-dialog{
  width:min(760px,100%); max-height:100%; display:flex; flex-direction:column;
  background:var(--surface); color:var(--ink); font:var(--font-ui);
  border-radius:var(--r-lg); box-shadow:var(--shadow);
}
.help-dialog .help-head{ display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2); padding:var(--sp-3) var(--sp-4); border-bottom:1px solid var(--line) }
.help-dialog .help-title{ margin:0; font-size:17px }
.help-dialog .help-close{ border:0; background:none; color:var(--ink-mut); cursor:pointer; min-width:var(--hit); min-height:var(--hit); border-radius:var(--r-md) }
.help-dialog .help-close:hover{ background:var(--surface2); color:var(--ink) }
.help-dialog .help-body{ padding:var(--sp-4); overflow:auto; display:grid; gap:var(--sp-4) }
.help-dialog .help-h{ margin:0 0 var(--sp-2); font-size:13px; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-mut) }
.help-dialog .help-list{ margin:0; padding:0; list-style:none; display:grid; gap:var(--sp-2) }
.help-dialog .help-key{
  display:inline-block; font:var(--font-num); background:var(--surface2); color:var(--ink);
  border:1px solid var(--line); border-bottom-width:2px; border-radius:var(--r-sm);
  padding:3px 8px; margin:1px;
}
/* Klickbare Chips: auf Touchgeraeten der einzige Weg zu manchen Befehlen. */
.help-dialog .help-key.clickable{ cursor:pointer; color:var(--accent); border-color:var(--accent) }
.help-dialog .help-key.clickable:hover{ background:var(--accent); color:var(--on-accent) }
.help-dialog .help-key.clickable:focus-visible{ outline:2px solid var(--accent); outline-offset:2px }

@container dock (max-width:300px){
  .shell-dock .dock-tab{ padding:var(--sp-2) 2px; font-size:12px }
}

/* ---------- Panels im Dock -------------------------------------------------
   Die vier Panels stammen aus der alten Shell: position:absolute am Rand der Buehne,
   Sichtbarkeit ueber inline style.display, und sie versteckten einander gegenseitig.
   Im Dock uebernimmt der Tab die Sichtbarkeit — deshalb wird beides hier neutralisiert.
   Die !important sind noetig, weil die alte Logik inline schreibt; sie verschwinden mit
   dem Abriss (Task 16), wenn die Panels ihre eigene Anzeige nicht mehr fuehren. */

#shell-dock .dock-panel > #outline-panel,
#shell-dock .dock-panel > #design-panel,
#shell-dock .dock-panel > #lintpanel,
#shell-dock .dock-panel > #partslist{
  position:static !important;
  inset:auto !important;
  width:auto !important; max-width:none !important; height:auto !important; max-height:none !important;
  border:0 !important; border-radius:0 !important; box-shadow:none !important;
  background:transparent !important; z-index:auto !important;
}
#shell-dock .dock-panel > #outline-panel,
#shell-dock .dock-panel > #design-panel{ display:flex !important; flex-direction:column }
#shell-dock .dock-panel > #lintpanel,
#shell-dock .dock-panel > #partslist{ display:block !important }

/* Die Kopfzeilen der alten Panels doppeln jetzt den Dock-Tab — Titel und Schliesskreuz
   sind zweimal da. Beides weicht dem Dock. */
#shell-dock .dock-panel > #outline-panel > .outline-head,
#shell-dock .dock-panel > #design-panel > .design-head{ display:none !important }

/* ---------- Teilen: ein Einstieg fuer Freigabe UND Live-Sitzung ------------- */

.share-menu{
  position:absolute; top:calc(var(--topbar-h) - 4px); right:var(--sp-2); z-index:50;
  width:min(320px, calc(100vw - var(--sp-4)));
  display:flex; flex-direction:column; gap:2px; padding:var(--sp-2);
  background:var(--surface); color:var(--ink); font:var(--font-ui);
  border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow);
}
.share-menu[hidden]{ display:none }
.share-menu .share-state{ margin:0 0 var(--sp-1); padding:var(--sp-2); font-size:12px;
  color:var(--ink-mut); background:var(--surface2); border-radius:var(--r-sm) }
.share-menu .share-state[hidden]{ display:none }
.share-menu .share-item{
  display:flex; flex-direction:column; align-items:flex-start; gap:2px; text-align:left;
  padding:var(--sp-2) var(--sp-3); min-height:var(--hit);
  border:0; border-radius:var(--r-md); background:none; color:var(--ink); font:inherit; cursor:pointer;
}
.share-menu .share-item:hover:not([disabled]){ background:var(--surface2) }
.share-menu .share-item:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.share-menu .share-item[disabled]{ opacity:.5; cursor:not-allowed }
.share-menu .share-item-title{ font-weight:600 }
.share-menu .share-item-desc{ font-size:12px; color:var(--ink-mut); line-height:1.35 }

/* ---------- Mehr-Menue ------------------------------------------------------ */

.more-menu{
  position:absolute; top:calc(var(--topbar-h) - 4px); right:var(--sp-2); z-index:50;
  width:min(300px, calc(100vw - var(--sp-4))); max-height:70vh; overflow-y:auto;
  display:flex; flex-direction:column; gap:var(--sp-2); padding:var(--sp-2);
  background:var(--surface); color:var(--ink); font:var(--font-ui);
  border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow);
}
.more-menu[hidden]{ display:none }
.more-menu .more-group{ display:flex; flex-direction:column; gap:1px }
.more-menu .more-h{ margin:var(--sp-1) var(--sp-2); font-size:11px; text-transform:uppercase;
  letter-spacing:.04em; color:var(--ink-mut) }
.more-menu .more-item{
  display:flex; align-items:center; min-height:var(--hit); padding:var(--sp-1) var(--sp-2);
  border:0; border-radius:var(--r-md); background:none; color:var(--ink); font:inherit;
  cursor:pointer; text-align:left;
}
.more-menu .more-item:hover{ background:var(--surface2) }
.more-menu .more-item:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.more-menu .more-line{ display:flex; align-items:baseline; gap:var(--sp-2); width:100%; min-width:0 }
.more-menu .more-label{ flex:1 1 auto; min-width:0 }
.more-menu .more-hint{ flex:0 0 auto; font:var(--font-num); font-size:11px; color:var(--ink-mut) }
.more-menu .more-item.on .more-label::after{ content:' ✓'; color:var(--accent); font-weight:700 }
/* Was gerade aus der Leiste gewichen ist, steht zuoberst — sonst sucht man es zuletzt. */
.more-menu .more-overflow{ border-bottom:1px solid var(--line); padding-bottom:var(--sp-2) }

/* ---------- Werkstatt ------------------------------------------------------- */

.shell-workshop{
  display:flex; flex-direction:column; gap:var(--sp-3); padding:var(--sp-3);
  background:var(--surface2); border-top:1px solid var(--line); font:var(--font-ui); color:var(--ink);
}
.shell-workshop[hidden]{ display:none }
.shell-workshop .workshop-note{ margin:0; font-size:12px; color:var(--ink-mut); line-height:1.4 }
.shell-workshop .workshop-h{ margin:0 0 var(--sp-1); font-size:12px; text-transform:uppercase;
  letter-spacing:.04em; color:var(--ink-mut) }
.shell-workshop .workshop-row{ display:flex; flex-wrap:wrap; gap:var(--sp-2) }
.shell-workshop .workshop-item,
.shell-workshop .workshop-connect{
  min-height:var(--hit); padding:0 var(--sp-3); border:1px solid var(--line);
  border-radius:var(--r-md); background:var(--surface); color:var(--ink); font:inherit; cursor:pointer;
}
.shell-workshop .workshop-item:hover,
.shell-workshop .workshop-connect:hover{ border-color:var(--accent) }
.shell-workshop .workshop-mcp{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-2) }
.shell-workshop .workshop-mcp .workshop-h{ flex-basis:100% }
.shell-workshop .workshop-input{
  flex:1 1 180px; min-width:0; min-height:var(--hit); padding:0 var(--sp-2);
  border:1px solid var(--line); border-radius:var(--r-md);
  background:var(--surface); color:var(--ink); font:var(--font-num);
}
.shell-workshop .workshop-mcp-state{ flex-basis:100%; font-size:12px; color:var(--ink-mut) }

/* ---------- Schmale Breiten: Rail und Dock weichen -------------------------
   Abnahmekriterium aus Ticket 01: jede Funktion bei 768 und 375 px erreichbar.
   Nebeneinander gehen 72 px Rail + 360 px Dock + Buehne nur auf breiten Fenstern auf;
   darunter wird das Dock zur Schublade und schliesslich zum Bottom-Sheet, die Rail zur
   Bodenleiste. Container Queries, nicht Media Queries: massgeblich ist die Breite der
   Shell-Zeile, nicht die des Fensters — das Dock nimmt selbst Platz weg. */

@container shell (max-width:1100px){
  /* Das Dock legt sich ueber die Buehne, statt sie zu zerquetschen. */
  #shell-dock-mount{ position:absolute; top:0; right:0; bottom:0; z-index:25 }
  #shell-dock-mount .shell-dock{ box-shadow:var(--shadow) }
}

@container shell (max-width:768px){
  /* Dock als Bottom-Sheet: volle Breite, von unten. */
  #shell-dock-mount{ top:auto; left:0; right:0; height:min(62%, 520px) }
  #shell-dock-mount .shell-dock{
    width:100%; border-left:0; border-top:1px solid var(--line);
    border-radius:var(--r-lg) var(--r-lg) 0 0;
  }

  /* Rail als Bodenleiste. Sie behaelt ihre Beschriftungen — das ist der ganze Punkt. */
  .shell-rail-host{ position:absolute; left:0; right:0; bottom:0; width:auto; z-index:26 }
  .shell-rail{
    flex-direction:row; align-items:center; justify-content:flex-start;
    width:100%; min-width:0; height:auto;
    padding:var(--sp-1) var(--sp-2); gap:var(--sp-1);
    border-right:0; border-top:1px solid var(--line);
    overflow-x:auto; overflow-y:hidden;
    /* Sichtbar machen, DASS es weitergeht. Bei 375 px stehen 513 px Inhalt in der Leiste;
       ohne Hinweis sieht man sechs Knoepfe und ahnt die restlichen drei nicht. Der weiche
       Rand ist der einzige ehrliche Weg dafuer, der keinen Platz kostet — eine Scrollleiste
       blendet iOS von selbst aus, sobald der Finger stillsteht. */
    mask-image:linear-gradient(to right, transparent 0, #000 var(--sp-2),
               #000 calc(100% - var(--sp-4)), transparent 100%);
    scroll-snap-type:x proximity;
    scrollbar-width:none;
  }
  .shell-rail::-webkit-scrollbar{ height:0 }
  .shell-rail .rail-item{ scroll-snap-align:start; flex-shrink:0 }
  .shell-rail .rail-label{ white-space:nowrap; overflow-wrap:normal; hyphens:none }
  .shell-rail .rail-group{ flex-direction:row; gap:var(--sp-1); flex-shrink:0 }
  .shell-rail .rail-bottom{ margin-left:auto }
  .shell-rail .rail-item{ width:auto; min-width:var(--hit); padding:var(--sp-1) var(--sp-2) }

  /* Der Katalog oeffnet nach oben, ueber der Bodenleiste. */
  .rail-flyout{
    left:var(--sp-2); right:var(--sp-2); bottom:100%; top:auto;
    width:auto; max-height:min(52vh, 420px); margin-bottom:var(--sp-2);
  }

  /* Der Chip weicht der Bodenleiste, sonst liegt er darunter. */
  #shell-chip-mount{ bottom:calc(var(--hit) + var(--sp-4)) }

  /* ... und dem Flyout, wenn einer offen ist. Gemessen: rund 9 px Ueberlappung, genug,
     dass der Chip angeschnitten aussieht. Der Chip ist die eine Stelle, die sagt, was ein
     Klick bedeutet — der darf nicht halb verdeckt sein. */
  .shell-rail-host:has(.rail-flyout:not([hidden])) ~ * #shell-chip-mount,
  #shell-main:has(.rail-flyout:not([hidden])) #shell-chip-mount{
    bottom:calc(var(--hit) + min(52vh, 420px) + var(--sp-5));
  }
}

/* Live-Zustand in der Topbar. Er ersetzt den farbigen Knopf der alten Menueleiste; der
   Text nennt Zustand UND Teilnehmerzahl, die Klasse macht auf einen Blick erkennbar, ob
   gerade tatsaechlich uebertragen wird. */
.shell-topbar .tb-livestatus.on{ color:var(--ok); font-weight:600 }
.shell-topbar .tb-livestatus.live-blocked{ color:var(--danger); font-weight:600 }
.shell-topbar .tb-livestatus.live-readonly{ color:var(--warn) }
.shell-topbar .tb-livestatus.live-ended{ color:var(--ink-mut); font-weight:600 }

/* ---------- Geerbte Flaechen im Dunkelmodus -------------------------------
   Die Panels und Dialoge stammen aus der alten Shell und tragen ihre Farben als feste
   Hex-Werte. Die grossen Flaechen sind auf Tokens umgestellt; fuer die vielen kleinen
   Details (Trennlinien, Kopfzeilen, gedaempfte Texte) waere ein vollstaendiger Umbau ein
   eigenes Vorhaben. Bis dahin sorgen diese Regeln dafuer, dass im Dunkelmodus nichts
   unlesbar wird — dunkler Text auf dunklem Grund ist schlimmer als ein heller Kasten. */

:root[data-theme=dark] #outline-panel,
:root[data-theme=dark] #design-panel,
:root[data-theme=dark] #lintpanel,
:root[data-theme=dark] #partslist,
:root[data-theme=dark] .dlg,
:root[data-theme=dark] #cmdpal{ color-scheme:dark }

@media (prefers-color-scheme: dark){
  :root:not([data-theme=light]) #outline-panel,
  :root:not([data-theme=light]) #design-panel,
  :root:not([data-theme=light]) #lintpanel,
  :root:not([data-theme=light]) #partslist,
  :root:not([data-theme=light]) .dlg,
  :root:not([data-theme=light]) #cmdpal{ color-scheme:dark }
}

/* Die Buehne selbst: die 3D-Szene bleibt hell (Garten, Himmel — sie ist bewusst NICHT
   Teil dieses Umbaus). Ein leichter Schleier nimmt ihr im Dunkelmodus die Grelle, ohne
   die Farben der Bauteile zu verfaelschen. */
:root[data-theme=dark] #stage::after,
:root:not([data-theme=light]) #stage::after{ content:none }

/* Die Avatare stammen aus der alten Statusleiste, wo sie ueber 800 px Platz hatten und je
   bis zu 80 px breit sein durften. In der 48-px-Topbar ist der Platz knapper — schmaler
   heisst hier ehrlicher: der Name kuerzt sich mit Ellipse, die Zahl steht im Text daneben.
   Auch hier ID-Spezifitaet, aus demselben Grund wie oben. */
.shell-topbar #live-avatars .live-avatar{ max-width:56px }

/* --- Auswahl-Aktionen der Rail -------------------------------------------------
   Verschieben, Duplizieren, Drehen und Eigenschaften sind Aktionen auf der Auswahl,
   keine Modi. Ohne Auswahl sind sie SICHTBAR gesperrt statt versteckt: wer sie sucht,
   soll sehen, dass es sie gibt und was fehlt (der Titel nennt "Erst Teile auswaehlen").
*/
.shell-rail .rail-sep{ display:flex; align-items:center; gap:var(--sp-1);
  margin:var(--sp-2) var(--sp-1) var(--sp-1); }
.shell-rail .rail-sep::after{ content:""; flex:1 1 auto; height:1px; background:var(--line) }
.shell-rail .rail-sep-label{ font-size:10px; letter-spacing:.04em; text-transform:uppercase;
  color:var(--ink-mut) }
.shell-rail .rail-item:disabled{ opacity:.4; cursor:not-allowed }
.shell-rail .rail-item:disabled:hover{ background:transparent }

/* Der Verschiebe-Flyout. Sechs Richtungen als Raster; ohne ihn waeren die Pfeiltasten
   der einzige Weg, eine Auswahl zu bewegen — auf einem Tablet also gar keiner. */
.rail-flyout .move-pad{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--sp-2); }
.rail-flyout .move-dir{ display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:2px; min-height:56px; padding:var(--sp-2); border:1px solid var(--line);
  border-radius:var(--r-md); background:var(--surface2); color:var(--ink);
  font:inherit; cursor:pointer }
.rail-flyout .move-dir:hover{ background:var(--surface) }
.rail-flyout .move-dir:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.rail-flyout .move-glyph{ font-size:18px; line-height:1 }
.rail-flyout .move-label{ font-size:11px; color:var(--ink-mut) }
.rail-flyout .move-hint{ margin:var(--sp-2) 0 0; font-size:11px; color:var(--ink-mut) }

/* Shell-Aktionen in der Trefferliste haben kein Bauteil-Symbol; ein Chevron statt eines
   leeren Kastens haelt die Zeilen buendig. */
#cmdpal-list .ci-glyph{ display:inline-flex; align-items:center; justify-content:center;
  width:100%; height:100%; color:var(--ink-mut); font-size:14px }


/* --- Dunkelmodus fuer die geerbten Panels ---------------------------------------
   Diese Flaechen stammen aus der Zeit vor der Token-Ebene und tragen feste Hex-Werte.
   GEMESSEN im Dunkelmodus: Strukturbaum 1,26 : 1 und das Assistent-Eingabefeld 1,03 : 1 —
   also praktisch unsichtbar, nicht bloss unschoen. Eine vollstaendige Tokenisierung der
   rund 350 Hex-Werte ist ein eigenes Vorhaben; bis dahin heben diese Regeln genau die
   Flaechen an, auf denen man sonst nichts lesen kann.

   Die Selektoren sind absichtlich so schwer wie die Originale (ID + Klasse), sonst
   gewinnt der Inline-<style>-Block von viewer.html. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme=light]) #outline-panel{ color:var(--ink); border-left-color:var(--line) }
  :root:not([data-theme=light]) #outline-panel .outline-head{ background:var(--surface2); border-bottom-color:var(--line) }
  :root:not([data-theme=light]) #outline-panel summary,
  :root:not([data-theme=light]) #outline-panel .outline-item{ color:var(--ink) }
  :root:not([data-theme=light]) #outline-panel .outline-category-title,
  :root:not([data-theme=light]) #outline-panel .outline-empty{ color:var(--ink-mut) }
  :root:not([data-theme=light]) #design-panel textarea,
  :root:not([data-theme=light]) #design-panel select,
  :root:not([data-theme=light]) #design-panel input{
    background:var(--surface2); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #design-panel label{ color:var(--ink-mut) }
  :root:not([data-theme=light]) #cmdpal-backdrop #cmdpal{ background:var(--surface); color:var(--ink) }
  :root:not([data-theme=light]) #cmdpal-list .cmdpal-item .cn{ color:var(--ink) }
  :root:not([data-theme=light]) #cmdpal-list .cmdpal-item .cd,
  :root:not([data-theme=light]) #cmdpal-list .cmdpal-item .cg{ color:var(--ink-mut) }
  :root:not([data-theme=light]) #cmdpal-input{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
}
:root[data-theme=dark] #outline-panel{ color:var(--ink); border-left-color:var(--line) }
:root[data-theme=dark] #outline-panel .outline-head{ background:var(--surface2); border-bottom-color:var(--line) }
:root[data-theme=dark] #outline-panel summary,
:root[data-theme=dark] #outline-panel .outline-item{ color:var(--ink) }
:root[data-theme=dark] #outline-panel .outline-category-title,
:root[data-theme=dark] #outline-panel .outline-empty{ color:var(--ink-mut) }
:root[data-theme=dark] #design-panel textarea,
:root[data-theme=dark] #design-panel select,
:root[data-theme=dark] #design-panel input{
  background:var(--surface2); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #design-panel label{ color:var(--ink-mut) }
:root[data-theme=dark] #cmdpal-backdrop #cmdpal{ background:var(--surface); color:var(--ink) }
:root[data-theme=dark] #cmdpal-list .cmdpal-item .cn{ color:var(--ink) }
:root[data-theme=dark] #cmdpal-list .cmdpal-item .cd,
:root[data-theme=dark] #cmdpal-list .cmdpal-item .cg{ color:var(--ink-mut) }
:root[data-theme=dark] #cmdpal-input{ background:var(--surface2); color:var(--ink); border-color:var(--line) }

/* --- Farb-Palette im Rail-Flyout -----------------------------------------------
   Ohne sie gab es im Faerb-Modus keinen Weg, die Malfarbe zu setzen: der alte Farb-Knopf
   rief den Material-Editor, und der bricht ohne Auswahl ab — waehrend der Buehnen-Chip
   "Farbe waehlen, dann Teile antippen" verlangte. */
.rail-flyout .color-pad{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-2) }
.rail-flyout .color-swatch{ display:flex; flex-direction:column; align-items:center; gap:4px;
  min-height:var(--hit); padding:var(--sp-2); border:1px solid var(--line); border-radius:var(--r-md);
  background:var(--surface2); color:var(--ink); font:inherit; cursor:pointer }
.rail-flyout .color-swatch:hover{ background:var(--surface) }
.rail-flyout .color-swatch:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px }
.rail-flyout .color-swatch.on{ border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent) }
.rail-flyout .color-dot{ width:24px; height:24px; border-radius:50%; border:1px solid var(--line) }
.rail-flyout .color-label{ font-size:11px; color:var(--ink-mut) }
.rail-flyout .color-custom{ display:block; width:100%; margin-top:var(--sp-3); min-height:var(--hit);
  border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface2);
  color:var(--ink); font:inherit; cursor:pointer }
.rail-flyout .color-custom:hover{ background:var(--surface) }

/* Das Umgebungs-Panel ist ein geerbtes fixed-Panel und kennt das Dock nicht. Es weicht
   nach links aus, solange das Dock offen ist — sonst verdeckt es genau den Bericht, den
   man gerade angefordert hat. */
/* WICHTIG: hier keine @container-Query.
   #env-panel haengt an <body> (toggleEnvPanel erzeugt es dort), liegt also AUSSERHALB des
   Containers #shell-main. Eine Container-Query kann darauf nie zutreffen — der erste
   Versuch hatte genau das getan, und der schmale Fall blieb wirkungslos: bei 375 px mit
   offenem Dock stand das Panel gemessen bei left:-299 px, komplett ausserhalb des Bildes.
   Ausweichen lohnt sich ohnehin nur, wenn daneben Platz ist; darunter uebernimmt der
   JS-Wachposten (das Dock schliesst das Panel), wie bei Katalog <-> Dock. */
@media (min-width: 1100px){
  body:has(#shell-dock:not([hidden])) #env-panel{ right:calc(var(--dock-w) + var(--sp-3)) }
}

/* Trennen-Knopf der MCP-Bruecke. Er ersetzt "Verbinden", solange eine Verbindung steht —
   es gab bis zum vierten Review nur den Weg hinein. */
#shell-workshop .workshop-disconnect{ min-height:var(--hit); padding:0 var(--sp-3);
  border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface2);
  color:var(--ink); font:inherit; cursor:pointer }
#shell-workshop .workshop-disconnect:hover{ background:var(--surface) }

/* Eine dauerhafte Warnung im Buehnen-Chip. Sie beschreibt keine Meldung, sondern eine
   Lage — zum Beispiel eine Live-Sitzung ohne Freigabe, in der jeder Bauschritt beim
   naechsten Stand der anderen Seite verloren geht. */
.shell-chip.warnung{ border-color:var(--warn); box-shadow:inset 0 0 0 1px var(--warn) }
.shell-chip.warnung .chip-hint{ color:var(--warn); font-weight:600 }

/* --- Dunkelmodus fuer zwei geerbte Schwebe-Panels -------------------------------
   Zwischenablage-Verlauf und QA-Uebersicht tragen feste helle Hintergruende (#fff,
   #f6f8fb) aus der Zeit vor der Token-Ebene, waehrend ihr Text die Token-Farbe erbt.
   GEMESSEN im Dunkelmodus: 1,11 : 1 — heller Text auf weiss, praktisch unsichtbar.
   Zusammen machten die beiden Flaechen den Loewenanteil der 334 Elemente unter der
   Lesbarkeitsschwelle aus (die QA-Uebersicht allein rund 300 Karten).

   Wie bei den anderen geerbten Flaechen: nur die grossen Flaechen anheben, nicht alle
   341 Hex-Werte tauschen — die tragen im Hellmodus ihr genaues Aussehen. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme=light]) #cliphistory,
  :root:not([data-theme=light]) #modelview{ background:var(--surface); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #cliphistory .ch-head,
  :root:not([data-theme=light]) #modelview .mvbar{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #cliphistory .clip-item,
  :root:not([data-theme=light]) #modelview .card{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #cliphistory .ci-time,
  :root:not([data-theme=light]) #cliphistory .ci-break,
  :root:not([data-theme=light]) #modelview .card .sub,
  :root:not([data-theme=light]) #modelview #mvCount{ color:var(--ink-mut) }
  :root:not([data-theme=light]) #cliphistory button,
  :root:not([data-theme=light]) #modelview button,
  :root:not([data-theme=light]) #modelview select{ background:var(--surface); color:var(--ink); border-color:var(--line) }
}
:root[data-theme=dark] #cliphistory,
:root[data-theme=dark] #modelview{ background:var(--surface); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #cliphistory .ch-head,
:root[data-theme=dark] #modelview .mvbar{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #cliphistory .clip-item,
:root[data-theme=dark] #modelview .card{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #cliphistory .ci-time,
:root[data-theme=dark] #cliphistory .ci-break,
:root[data-theme=dark] #modelview .card .sub,
:root[data-theme=dark] #modelview #mvCount{ color:var(--ink-mut) }
:root[data-theme=dark] #cliphistory button,
:root[data-theme=dark] #modelview button,
:root[data-theme=dark] #modelview select{ background:var(--surface); color:var(--ink); border-color:var(--line) }

/* Nachtrag: die Karten der QA-Uebersicht und die Auswahl-Karte auf der Buehne.
   Paarweise gemessen (dunkel gegen hell, je Element): nach den Regeln oben blieben genau
   34 Stellen im Dunkelmodus deutlich schlechter — 33 davon Kartentexte, die ihre Farbe
   fest mitbringen, plus die Auswahl-Karte mit ihrem halbtransparenten Weiss. Alles andere
   ist in beiden Themen gleich gut (oder gleich mittelmaessig, aber das ist der Zustand des
   Hellmodus und nicht Sache dieses Umbaus). */
@media (prefers-color-scheme: dark){
  :root:not([data-theme=light]) #modelview .card.miss{ background:var(--surface); border-color:var(--warn) }
  :root:not([data-theme=light]) #modelview .ttl,
  :root:not([data-theme=light]) #modelview .ttl .lbl{ color:var(--ink) }
  :root:not([data-theme=light]) #modelview .dbg{ color:var(--ink-mut); border-top-color:var(--line) }
  :root:not([data-theme=light]) #modelview .dbg b{ color:var(--ink) }
  :root:not([data-theme=light]) #modelview .desc{ color:var(--ink-mut) }
  /* Eigener Warn-Hintergrund: nicht nur den Text anheben, sonst bleibt die Flaeche hell. */
  :root:not([data-theme=light]) #modelview .imgs .nomatch{ background:var(--surface); color:var(--warn) }
  :root:not([data-theme=light]) #selcard{ background:var(--chip-bg); border-color:var(--line); color:var(--ink) }
  :root:not([data-theme=light]) #selcard .muted{ color:var(--ink-mut) }
}
:root[data-theme=dark] #modelview .card.miss{ background:var(--surface); border-color:var(--warn) }
:root[data-theme=dark] #modelview .ttl,
:root[data-theme=dark] #modelview .ttl .lbl{ color:var(--ink) }
:root[data-theme=dark] #modelview .dbg{ color:var(--ink-mut); border-top-color:var(--line) }
:root[data-theme=dark] #modelview .dbg b{ color:var(--ink) }
:root[data-theme=dark] #modelview .desc{ color:var(--ink-mut) }
:root[data-theme=dark] #modelview .imgs .nomatch{ background:var(--surface); color:var(--warn) }
:root[data-theme=dark] #selcard{ background:var(--chip-bg); border-color:var(--line); color:var(--ink) }
:root[data-theme=dark] #selcard .muted{ color:var(--ink-mut) }

/* --- Dunkelmodus fuer die drei letzten geerbten Flaechen ------------------------
   Stueckliste, Inventar & Budget und Umgebung & Licht bringen feste helle Hintergruende
   mit. Ihr Text ist dort ebenfalls fest dunkel, also LESBAR — der paarweise Vergleich
   dunkel/hell meldet sie deshalb nicht. Sichtbar sind sie trotzdem: weisse Tafeln in
   einer dunklen Oberflaeche, und fuer ein Kind am Abend schlicht blendend.

   Deshalb sucht die Pruefung im Harness nach der URSACHE statt nach der Wirkung: eine
   Bedienflaeche mit hellem Hintergrund im Dunkelmodus. Farbtupfer und Produktfotos sind
   davon ausgenommen — die SOLLEN hell sein. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme=light]) #partslist,
  :root:not([data-theme=light]) #invpanel,
  :root:not([data-theme=light]) #env-panel{ background:var(--surface); color:var(--ink) }
  :root:not([data-theme=light]) #partslist th,
  :root:not([data-theme=light]) #invpanel .inv-head,
  :root:not([data-theme=light]) #invpanel .inv-tab{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #partslist td,
  :root:not([data-theme=light]) #partslist .name{ background:var(--surface); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #partslist tfoot td{ background:var(--surface2) }
  :root:not([data-theme=light]) #partslist tr:hover td{ background:var(--surface2) }
  :root:not([data-theme=light]) #invpanel .kit-card,
  :root:not([data-theme=light]) #invpanel .cat-chip,
  :root:not([data-theme=light]) #invpanel button,
  :root:not([data-theme=light]) #invpanel input,
  :root:not([data-theme=light]) #env-panel button,
  :root:not([data-theme=light]) #env-panel input{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
  :root:not([data-theme=light]) #invpanel .cat-chip.on,
  :root:not([data-theme=light]) #env-panel button.active{ background:var(--accent); color:var(--on-accent) }
}
:root[data-theme=dark] #partslist,
:root[data-theme=dark] #invpanel,
:root[data-theme=dark] #env-panel{ background:var(--surface); color:var(--ink) }
:root[data-theme=dark] #partslist th,
:root[data-theme=dark] #invpanel .inv-head,
:root[data-theme=dark] #invpanel .inv-tab{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #partslist td,
:root[data-theme=dark] #partslist .name{ background:var(--surface); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #partslist tfoot td{ background:var(--surface2) }
:root[data-theme=dark] #partslist tr:hover td{ background:var(--surface2) }
:root[data-theme=dark] #invpanel .kit-card,
:root[data-theme=dark] #invpanel .cat-chip,
:root[data-theme=dark] #invpanel button,
:root[data-theme=dark] #invpanel input,
:root[data-theme=dark] #env-panel button,
:root[data-theme=dark] #env-panel input{ background:var(--surface2); color:var(--ink); border-color:var(--line) }
:root[data-theme=dark] #invpanel .cat-chip.on,
:root[data-theme=dark] #env-panel button.active{ background:var(--accent); color:var(--on-accent) }
