/* Die Themen-Tokens stehen seit AP-44 im DOKUMENT, nicht hier.
   Diese Datei wird statisch und zwischengespeichert ausgeliefert;
   ein Platzhalter darin bliebe stehen und waere ein Syntaxfehler.
   Gesetzt werden sie in der Huelle, in einem eigenen `style`-Block
   ueber den Token-Platzhalter (der hier bewusst nicht woertlich
   steht: `test_theme` sucht danach und wuerde an dieser Erklaerung
   anschlagen — dieselbe Falle wie bei B-57),
   damit ein Themenwechsel nicht am Zwischenspeicher haengt. */

:root{color-scheme:light dark}*{box-sizing:border-box}
body{margin:0;font:14px/1.5 var(--font-sans);background:var(--surface-0);color:var(--text-primary)}
header{padding:12px 18px;background:var(--surface-1);border-bottom:1px solid var(--border);display:flex;gap:10px;align-items:center;flex-wrap:wrap}
header h1{margin:0;font-size:15px;margin-right:4px}
/* B-219: Im Kundenlink führt die Marke zur Einstiegsseite — sie bleibt Marke, kein blauer Link. */
header h1 a.marke{color:inherit;text-decoration:none}
header h1 a.marke:hover{text-decoration:underline}
header #defs{max-width:230px}
header #acc{width:110px}
header nav a{color:var(--accent);text-decoration:none;margin-right:8px;padding:4px 8px;border-radius:var(--radius-lg)}
header nav a.active{background:var(--accent-subtle);color:var(--on-accent-subtle)}
header .sp{flex:1}
input,select,button,textarea{font:13px var(--font-sans)}
input,select,textarea{background:var(--field);color:var(--text-primary);border:1px solid var(--border-strong);border-radius:var(--radius-lg);padding:6px 9px}
button{cursor:pointer;background:var(--surface-2);color:var(--text-primary);border:1px solid var(--border-strong);border-radius:var(--radius-lg);padding:6px 11px}
/* Die Primaeraktion traegt die MARKE, nicht die Erfolgsfarbe — im Portal ist
   bg-primary der Akzent; Gruen bleibt fuer Zustaende. Die Schriftfarbe kippt
   mit dem Thema (dunkel auf hellem Violett, weiss auf tiefem Violett) und
   nutzt dafuer vorerst die Kartenfarbe; mit semantischen Namen wird daraus
   --on-accent. */
button.primary{background:var(--accent);border-color:var(--accent);
  color:var(--on-accent);font-weight:600}
button:disabled{opacity:.5;cursor:not-allowed}
.toggle button.active{background:var(--accent-subtle);border-color:var(--accent-muted);color:var(--accent)}
/* Dock-Layout: zwei Andockspalten, der Konfigurator immer in der Mitte.
   Bewusst CSS-Grid statt verschachtelter Container — ein Seitenwechsel ändert
   nur `grid-column`. Würde man die Panels im DOM umhängen, lüde der Browser
   das 3D-iframe neu und der Viewer verlöre Kamera und Modell. */
.wrap{display:grid;height:calc(100vh - 52px);
      grid-template-columns:var(--wl,400px) var(--sl,6px) minmax(320px,1fr) var(--sr,6px) var(--wr,430px);
      grid-auto-rows:1fr}
.panel{display:flex;flex-direction:column;overflow:hidden;background:var(--surface-raised);
       border-left:1px solid var(--border);min-height:0}
.panel[data-dock="L"]{grid-column:1;border-left:none;border-right:1px solid var(--border)}
.panel[data-dock="R"]{grid-column:5}
.panel[hidden]{display:none}
.main{grid-column:3;grid-row:1/-1;min-width:0;padding:12px 20px;overflow:auto}
.split{grid-row:1/-1;background:var(--border);cursor:col-resize}
.split:hover{background:var(--accent-muted)}
.dragveil{position:fixed;inset:0;z-index:200;cursor:col-resize;user-select:none}
.panel:fullscreen{width:100vw;height:100vh;border:none;background:var(--surface-0)}
.panel:fullscreen .panel-body{height:calc(100vh - 34px)}
#splitL{grid-column:2}
/* B-202: Ansicht „Assistent“ — nur der Chat, mittig, darüber der Kurzstand. */
.wrap.assistent{grid-template-columns:minmax(0,1fr)}
.wrap.assistent .main,.wrap.assistent .split{display:none}
.wrap.assistent #pnl-chat{grid-column:1;grid-row:1/-1;width:min(980px,100%);justify-self:center;
  border-left:1px solid var(--border);border-right:1px solid var(--border)}
.kurzstand{border-bottom:1px solid var(--border);background:var(--surface-1);padding:8px 12px;font-size:13px;
  display:flex;flex-direction:column;gap:5px}
.kurzstand[hidden]{display:none}
.ks-kopf{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.ks-teile{display:flex;gap:4px 14px;flex-wrap:wrap}
.ks-offen{color:var(--error-text);font-size:12.5px}
.ks-aktion button{font-size:12.5px}
#splitR{grid-column:4}
.panel-head{display:flex;gap:6px;align-items:center;padding:6px 8px;font-size:12.5px;
            border-bottom:1px solid var(--border);background:var(--surface-1)}
.panel-head b{flex:1;font-weight:600}
.panel-head button{padding:1px 6px;font-size:12px;line-height:1.5}
.panel-body{flex:1;overflow:auto;padding:14px;min-height:0}
.panel-body.v3dbody{padding:0;position:relative;overflow:hidden}
.panel .k{color:var(--text-muted);font-size:11px;text-transform:uppercase;letter-spacing:.05em;margin:14px 0 4px}
/* chat left */
.chat-head{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;gap:8px;align-items:center;font-size:12px}
.msgs{flex:1;overflow:auto;padding:14px 14px 4px}
.msg{margin-bottom:10px;padding:8px 11px;border-radius:var(--radius-xl);max-width:92%;white-space:pre-wrap}
.msg.user{background:var(--accent-subtle);margin-left:auto;color:var(--on-accent-subtle-soft)}
.msg.assistant{background:var(--surface-1);border:1px solid var(--border)}
.msg.sys{background:transparent;color:var(--text-secondary);font-size:12px;text-align:center;max-width:100%}
.composer{border-top:1px solid var(--border);padding:10px;display:flex;gap:8px}
.composer textarea{flex:1;resize:none;height:44px}
/* config right */
.bar{display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap;padding-bottom:10px;margin-bottom:8px;border-bottom:1px solid var(--border)}
.bar .col{min-width:150px}
h4{margin:0 0 4px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted)}
.tag{display:inline-block;background:var(--accent-subtle);color:var(--accent);border-radius:var(--radius-lg);padding:2px 9px;font-size:12px;margin:2px}
.tag.bad{background:var(--error-surface);color:var(--error-text)}
/* Stepper als festes Raster: −, Feld, + und Einheit haben eigene Spuren, damit
   sie zeilenübergreifend fluchten (Nutzer 21.08.). */
.qty{display:inline-grid;grid-template-columns:26px 58px 26px minmax(0,1fr);
     gap:5px;align-items:center;font-size:12px;color:var(--text-secondary)}
.qty button{padding:0;line-height:1.6}
.qty b{min-width:14px;text-align:center;color:var(--text-primary)}
.qty .qin{width:100%;padding:2px 4px;text-align:center;font-size:12px}
.qty i{font-style:normal;color:var(--text-secondary);justify-self:start;
     overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip{display:inline-block;background:var(--success-surface);color:var(--success-text);border-radius:var(--radius-lg);padding:2px 9px;font-size:12px;margin:2px}
.status{padding:6px 10px;border-radius:var(--radius-lg);font-size:13px}
.ok{background:var(--success-surface-soft);color:var(--success-text)}.bad{background:var(--error-surface);color:var(--error-text)}
.muted{color:var(--text-secondary)}
.card{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--radius-xl);padding:12px 14px;margin-bottom:12px}
.card h3{margin:0 0 2px;font-size:14px}
.badge{display:inline-block;font-size:11px;padding:1px 7px;border-radius:var(--radius-xl);background:var(--surface-2);color:var(--text-secondary);margin-left:6px}
.req{background:var(--error-surface);color:var(--error-strong)}
.variants{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
button.v{text-align:left;min-width:150px;padding:8px 12px}
button.v .art{display:block;font-size:11px;color:var(--text-muted)}
button.v.sel{background:var(--success-surface);border-color:var(--success);box-shadow:0 0 0 1px var(--success) inset}
button.v.disabled{opacity:.4;cursor:not-allowed;text-decoration:line-through}
button.v.auto{border-style:dashed;cursor:not-allowed}
.tree{font:13px/1.7 var(--font-sans)}
.tnode{padding:2px 0}
.tcomp{font-weight:600}
/* Artikelzeile mit Toggle-Switch statt Checkbox-Zeichen: Pille (::before) +
   Knopf (::after), rein CSS — das Markup (klickbarer Span) bleibt gleich.
   Zustände: aus = grau links, gewählt = grün rechts, automatisch = blau
   rechts (gesperrt), nicht wählbar = ausgegraut links. */
.tvar{margin-left:20px;cursor:pointer;border-radius:var(--radius-md);padding:2px 8px 2px 42px;
      display:inline-block;position:relative;font-size:14px}
.tvar:hover{background:var(--field)}
.tvar::before{content:"";position:absolute;left:8px;top:50%;transform:translateY(-50%);
      width:26px;height:15px;border-radius:var(--radius-lg);background:var(--border-strong);
      transition:background .15s ease}
.tvar::after{content:"";position:absolute;left:10px;top:50%;transform:translateY(-50%);
      width:11px;height:11px;border-radius:50%;background:#fff;
      box-shadow:var(--shadow-sm);transition:left .15s ease}
.tvar.sel{color:var(--success-text)}
.tvar.sel::before{background:var(--success)}
.tvar.sel::after{left:23px}
.tvar.disabled{opacity:.4;cursor:not-allowed}
.tvar.auto{cursor:not-allowed;color:var(--accent)}
.tvar.auto::before{background:var(--accent-muted)}
.tvar.auto::after{left:23px}
.tvar .art{color:var(--text-muted);font-size:11px}
.tree .gnode{margin-left:16px;padding:2px 0;color:var(--on-accent-subtle);display:flex;align-items:center;gap:5px}
/* shared icons */
.legend{font-size:11.5px;color:var(--text-muted);margin:0 0 10px;display:flex;gap:14px;flex-wrap:wrap}
.legend span b{color:var(--accent);font-weight:normal;font-size:14px;margin-right:2px}
.icon{display:inline-block;margin-left:6px;font-size:15px;cursor:default;vertical-align:middle}
.icon.req{color:var(--error)}.icon.opt{color:var(--text-muted)}
.info-btn{cursor:pointer;border:none;background:transparent;color:var(--accent);font-size:15px;padding:0 4px;line-height:1}
.info-btn:hover{color:var(--on-accent-subtle)}
.vwrap{display:inline-flex;align-items:center;gap:2px}
/* image tiles: gallery + step view */
.gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(178px,1fr));gap:12px;margin-top:9px}
.gallery.big{grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:16px}
.g{position:relative;margin:0;background:var(--field);border:1px solid var(--border-strong);border-radius:var(--radius-2xl);padding:8px;cursor:pointer;transition:transform .12s,border-color .12s}
.g:hover{transform:translateY(-2px);border-color:var(--accent-muted)}
.g img,.g .noimg{display:block;width:100%;aspect-ratio:12/7;border-radius:var(--radius-lg);background:var(--surface-2)}
.g .noimg{display:flex;align-items:center;justify-content:center;color:var(--text-muted);font-size:12px}
.g figcaption{padding:7px 3px 1px;line-height:1.35}
.g figcaption b{display:block;font-size:13px}
.g .art{color:var(--text-muted);font-size:11px}
.g .price{display:block;color:var(--success-text);font-size:13px}
.g.sel{background:var(--success-surface);border-color:var(--success);box-shadow:0 0 0 1px var(--success) inset}
.g.auto{border-style:dashed;cursor:not-allowed}
.g.disabled{opacity:.45;cursor:not-allowed;filter:grayscale(1)}
.g.disabled:hover,.g.auto:hover{transform:none;border-color:var(--border-strong)}
.gmark{position:absolute;top:14px;left:14px;background:var(--surface-1);border:1px solid var(--border-strong);border-radius:20px;padding:0 7px;font-size:13px;line-height:1.7}
.gmark.ok{color:var(--success-text);border-color:var(--success)}
.g .info-btn{position:absolute;top:12px;right:10px;background:var(--surface-1);border:1px solid var(--border-strong);border-radius:20px;padding:0 6px;line-height:1.7}
.g .qty{margin:3px 0 0}
/* form view */
.form{max-width:900px;background:var(--surface-1);border:1px solid var(--border);border-radius:var(--radius-xl);padding:4px 14px}
.frow{display:grid;grid-template-columns:220px minmax(0,1fr);gap:14px;align-items:start;padding:9px 4px;border-bottom:1px solid var(--surface-2)}
.frow:last-child{border-bottom:none}
.frow:hover{background:var(--surface-raised)}
.flab{font-size:13px;font-weight:600;display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding-top:3px}
/* Auskunft unter der Zeile: welche Ressource die Stueckzahl deckelt
   (Nutzerwunsch 23.08.). Ueber die ganze Zeilenbreite, damit sie nicht in die
   Beschriftungsspalte rutscht. */
.fnote{grid-column:1/-1;margin:2px 0 0;font-size:11.5px;color:var(--text-muted);
       display:flex;gap:6px;align-items:baseline}
.fnote b{color:var(--text-secondary);font-weight:600}
.flab .miss{font-weight:normal;font-size:11px;color:var(--error-text);margin-left:4px}
.frow.open .flab{color:var(--error-strong)}
/* Preis, Info-Knopf und Menge stehen in FESTEN Spalten (Nutzer 21.08.):
   vorher war jede Zeile ihr eigenes Raster mit auto-Spalten, dadurch sprangen
   Preise, Stepper-Knöpfe und Einheit von Zeile zu Zeile. Die beiden Zeilentypen
   (Einfachauswahl hier, Mehrfachauswahl in .fitem) enden auf denselben
   Spurbreiten, damit ihre Stepper untereinander fluchten. */
.fctl{display:grid;
      grid-template-columns:minmax(0,1fr) 26px minmax(0,170px);
      gap:10px;align-items:center;min-width:0}
.fctl>.flist{grid-column:1/-1}          /* Zeilenliste nutzt die ganze Breite */
.fctl .fsel{display:flex;align-items:center;gap:6px;min-width:0}
.fctl select{min-width:0;width:100%;max-width:min(420px,100%)}
/* Mehrfachauswahl als Zeilenliste (Variante 1, UI-Entscheid 19.08):
   Switch | Name | Preis (rechtsbündig, tabellarische Ziffern) | Info | Menge.
   Der Info-Knopf erscheint erst beim Überfahren der Zeile. */
.flist{display:flex;flex-direction:column;gap:2px;width:100%;font-size:13px}
/* Kein seitliches Polster: sonst sitzt der Inhaltskasten der Listenzeile 6px
   enger als der der Auswahlzeile und die Stepper fluchten nicht. */
.fitem{display:grid;
      grid-template-columns:26px minmax(70px,1fr) minmax(0,92px) 26px minmax(0,170px);
      gap:10px;align-items:center;padding:4px 0;border-radius:var(--radius-lg)}
.fitem:hover{background:var(--surface-raised)}
.fitem .fname{overflow-wrap:break-word;min-width:0}
.fitem.off .fname{opacity:.45;text-decoration:line-through}
.fitem .fprice{color:var(--success-text);font-variant-numeric:tabular-nums;
      white-space:nowrap;font-size:12.5px;justify-self:end}
.fitem .fibx{visibility:hidden;line-height:1}
.fitem:hover .fibx{visibility:visible}
/* Checkbox als Toggle-Switch — gleiche Optik wie in der Baumansicht. */
.fitem input{appearance:none;-webkit-appearance:none;width:26px;height:15px;margin:0;
      border-radius:var(--radius-lg);background:var(--border-strong);position:relative;cursor:pointer;
      flex:none;transition:background .15s ease}
.fitem input::after{content:"";position:absolute;left:2px;top:2px;width:11px;height:11px;
      border-radius:50%;background:#fff;box-shadow:var(--shadow-sm);
      transition:left .15s ease}
.fitem input:checked{background:var(--success)}
.fitem input:checked::after{left:13px}
.fitem input:disabled{cursor:not-allowed;opacity:.55}
/* Automatisch gewählt (gesperrt): blau wie im Baum, voll sichtbar. */
.fitem input:disabled:checked{background:var(--accent-muted);opacity:1}
/* step view */
.stepbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.dots{display:flex;gap:5px;flex-wrap:wrap}
.dot{width:26px;height:26px;padding:0;border-radius:50%;font-size:12px;color:var(--text-secondary)}
.dot.done{background:var(--success-surface);border-color:var(--success);color:var(--success-text)}
.dot.cur{background:var(--accent-subtle);border-color:var(--accent-muted);color:var(--accent);font-weight:700}
/* info drawer */
.drawer{position:fixed;top:0;right:0;height:100%;width:340px;background:var(--surface-1);border-left:1px solid var(--border);box-shadow:var(--shadow-md);transform:translateX(105%);transition:transform .18s;z-index:50;overflow:auto;padding:16px}
.drawer.open{transform:translateX(0)}
.drawer img{width:100%;height:auto;border-radius:var(--radius-xl);margin-bottom:10px}
.drawer h2{font-size:17px;margin:4px 0 2px}
.drawer .price{font-size:19px;color:var(--success-text);margin:6px 0 12px}
.drawer .k{color:var(--text-muted);font-size:11px;text-transform:uppercase;letter-spacing:.05em;margin-top:14px;margin-bottom:4px}
.drawer ul.why{margin:4px 0 0 0;padding-left:18px;color:var(--error-strong)}
.drawer ul.why li{margin:2px 0}
.drawer .close{float:right;cursor:pointer;background:var(--surface-2);border:1px solid var(--border-strong);border-radius:var(--radius-lg);color:var(--text-primary);padding:3px 9px}
/* collapsible side panels: assistant left, cart right — same mechanism */
#cartBtn b{color:var(--success-text)}
.panel iframe{width:100%;height:100%;border:0;display:block;background:var(--surface-0)}
#v3dNote{position:absolute;top:10px;left:12px;font-size:12px;pointer-events:none}
/* Werkzeugleiste ALS OVERLAY im 3D-Bereich — Kind von pnl-v3d, damit sie im
   Vollbild automatisch mitkommt (requestFullscreen hebt nur das Panel in den
   Top-Layer; alles außerhalb wäre unsichtbar). */
#v3dTools{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);
  display:flex;gap:3px;align-items:center;background:rgba(15,19,26,.78);
  padding:4px 6px;border-radius:var(--radius-xl);z-index:5}
#v3dTools button{font-size:13px;line-height:1;padding:5px 8px;border-radius:var(--radius-lg);
  border:1px solid transparent;background:transparent;color:#dbe2ee;cursor:pointer}
#v3dTools button:hover{background:rgba(255,255,255,.14)}
#v3dTools button.off{opacity:.4}
#v3dTools .sep{width:1px;height:16px;background:rgba(255,255,255,.22);margin:0 3px}
/* Farbwähler der Laufzeit (Pflege-Schalter „Farbwahl"): kleines Overlay über
   der Werkzeugleiste, eine Zeile je gepflegtem Materialnamen. */
#v3dColors{position:absolute;bottom:52px;left:50%;transform:translateX(-50%);
  background:rgba(15,19,26,.92);padding:10px 12px;border-radius:var(--radius-xl);z-index:6;
  display:flex;flex-direction:column;gap:6px;min-width:190px}
/* display:flex auf der ID schlägt sonst die UA-Regel [hidden]{display:none}
   (höhere Spezifität) — ohne diese Zeile hängt das LEERE Panel dauerhaft
   als schwarzer Balken über der Werkzeugleiste (Nutzer-Meldung 20.08.). */
#v3dColors[hidden]{display:none}
#v3dColors label{display:flex;align-items:center;justify-content:space-between;
  gap:10px;font-size:12px;color:#dbe2ee}
#v3dColors input[type=color]{width:36px;height:22px;padding:0;border:1px solid
  rgba(255,255,255,.25);border-radius:var(--radius-md);background:transparent;cursor:pointer}
#v3dColors .mini{font-size:11px;padding:3px 7px;border-radius:var(--radius-md);border:1px solid
  rgba(255,255,255,.25);background:transparent;color:#dbe2ee;cursor:pointer}
#v3dLogo{position:absolute;bottom:52px;left:50%;transform:translateX(-50%);
  background:rgba(15,19,26,.92);padding:10px 12px;border-radius:var(--radius-xl);z-index:6;
  display:flex;gap:8px;align-items:center}
#v3dLogo[hidden]{display:none}
/* Ladeanzeige (Nutzer 21.08.): dreht im Akzent — die Farbe ist eine Referenz
   auf das globale Blau, kein eingefrorener Wert. Wer „reduzierte Bewegung"
   eingestellt hat, sieht einen ruhenden Ring statt der Drehung. */
.ladekreis{width:15px;height:15px;flex:none;border-radius:50%;
  border:2px solid var(--border-strong);border-top-color:var(--accent);
  animation:ladedreh .8s linear infinite}
@keyframes ladedreh{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.ladekreis{animation:none}}
#v3dLogo .mini{font-size:11px;padding:3px 7px;border-radius:var(--radius-md);border:1px solid
  rgba(255,255,255,.25);background:transparent;color:#dbe2ee;cursor:pointer}
/* Aufblitzen der Panel-Zeile nach einem Klick im 3D-Modell. */
.reflash{animation:reflash 1.6s ease-out}
@keyframes reflash{0%,55%{background:rgba(232,164,0,.32);
  box-shadow:0 0 0 2px rgba(232,164,0,.6);border-radius:var(--radius-lg)}
  100%{background:transparent;box-shadow:none}}
.ctab{width:100%;border-collapse:collapse;margin-top:10px;font-size:13px}
.ctab td{padding:6px 4px;border-bottom:1px solid var(--surface-2);vertical-align:top}
.ctab .c1{width:38%;color:var(--text-secondary)}
.ctab .c3{text-align:right;white-space:nowrap;color:var(--success-text)}
.ctab .art{display:block;font-size:11px;color:var(--text-muted)}
/* Preisaenderung (F-14): auffaellig genug, um gelesen zu werden, ruhig
   genug, um nicht wie ein Fehler auszusehen — der Preis ist ja gueltig, er
   ist nur nicht mehr der von gestern. Deshalb der Warnton und keine
   Fehlerfarbe. */
.ctab .preishinweis{display:block;margin-top:4px;font-size:11px;line-height:1.35;
                    color:var(--warning-text,#a86400)}
.ctab .preishinweis b{font-size:12px}
.ctab .preisalt{color:var(--text-muted);text-decoration:line-through}
/* Dieselbe Marke im Konfigurator, damit die Aenderung schon dort auffaellt
   und nicht erst an der Kasse („muss dies in der Konfiguration sichtbar
   sein", F-14). */
.preismarke{display:inline-block;margin-left:5px;padding:0 5px;border-radius:8px;
            font-size:10px;line-height:15px;vertical-align:middle;
            background:var(--warning-bg,#fdf3dd);color:var(--warning-text,#a86400)}
.ctotal{display:flex;justify-content:space-between;align-items:baseline;margin-top:12px;
        padding-top:10px;border-top:1px solid var(--border-strong);font-size:14px}
.ctotal b{font-size:19px;color:var(--success-text)}
.cexp{display:flex;gap:8px;align-items:center}
.cexp select{flex:1}
.hand{display:flex;flex-direction:column;gap:7px}
.hand input,.hand select{width:100%}
.hrow{display:flex;gap:7px}
.hrow select{flex:0 0 130px}
.hrow input{flex:1}
.hand .status{font-size:12px}
.hores{background:var(--field);border:1px solid var(--border-strong);border-radius:var(--radius-lg);
       padding:7px 9px;margin:6px 0 0;font-size:11px;max-height:170px;overflow:auto;
       white-space:pre-wrap;word-break:break-all}
/* ── Kasse: nach dem Abschluss nur noch der Warenkorb (Nutzer 23.08.) ──────
   „Sobald eine Konfiguration abgeschlossen ist, schließen wir alle anderen
   Panels, auch das Config Panel, und zeigen nur noch das Warenkorb Panel an,
   damit der Anwender eindeutig in den Warenkorbprozess kommt."

   Nur Klassen, kein DOM-Umbau: das 3D-iframe bleibt an seinem Platz und
   verliert seinen WebGL-Kontext nicht — dieselbe Regel wie beim Mobil-Overlay.
   Der Korb nimmt die ganze Breite und begrenzt seinen Inhalt selbst: eine
   Firmenanschrift in einer 460-px-Spalte ist unbedienbar. */
.wrap.kasse{grid-template-columns:minmax(0,1fr)}
.wrap.kasse .main,.wrap.kasse .split{display:none}
.wrap.kasse #pnl-chat,.wrap.kasse #pnl-v3d{display:none}
.wrap.kasse #pnl-cart{grid-column:1;grid-row:1/-1;border-left:none;display:flex}
.wrap.kasse #pnl-cart .panel-body{padding:20px 16px}
.kassebox{max-width:760px;margin:0 auto}
/* Bestellformular. Zwei Spalten, wo Platz ist — Pflichtfelder tragen einen
   Stern, damit niemand raten muss, was fehlt. */
.bfelder{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
         gap:9px 14px;margin-top:8px}
.bfeld{display:flex;flex-direction:column;gap:3px;min-width:0}
.bfeld.weit{grid-column:1/-1}
.bfeld label{font-size:12px;color:var(--text-secondary)}
.bfeld .pflicht{color:var(--error-text)}
.bfeld input,.bfeld textarea{width:100%;min-width:0}
.bfeld textarea{min-height:70px;resize:vertical}
.bgruppe{margin-top:14px;font-size:12.5px;font-weight:600;
         color:var(--text-secondary)}
.bhinweis{background:var(--field);border:1px solid var(--border);
          border-radius:var(--radius-lg);padding:9px 11px;margin:10px 0 0;
          font-size:12.5px;white-space:pre-wrap}
.bfertig{background:var(--field);border:1px solid var(--success-text);
         border-radius:var(--radius-lg);padding:14px 16px;margin-top:12px}
.bfertig .nr{font-size:20px;font-weight:600;color:var(--success-text);
             user-select:all}
.bwahl{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
/* Fenster des Aufmass-Assistenten. Das Studio hatte bisher kein <dialog> —
   die Pflege bringt ihre eigenen Regeln mit, hier steht die erste. */
.redlg{max-width:640px;width:92vw;border:1px solid var(--border);
       border-radius:var(--radius-2xl);background:var(--surface-1);
       color:inherit;padding:18px 20px}
.redlg::backdrop{background:var(--overlay-veil)}
.redlg .horow{display:flex;align-items:center}
.aufmzeile{display:flex;justify-content:space-between;gap:12px}
.aufmzeile b{white-space:nowrap}
/* Kiosk (externer Laufzeit-Link): interne Bedienelemente verschwinden. */
body.kiosk .nur-intern{display:none}
/* B-109: das Studio als Vorschau im Rahmen der Pflege — nur die Konfiguration, kein Kopfwerkzeug. */
body.vorschau header nav,body.vorschau #hdrTools,body.vorschau #themaBtn,body.vorschau #lang,body.vorschau #startBtn{display:none}
/* B-165 (Nutzer 01.10.): vor dem Start keine Ansichts-, Panel- und Korbknöpfe
   und keine Kennzahlenleiste — sie zeigen erst mit einer Sitzung etwas. */
body.startseite #hdrTools,body.startseite .main>.bar,body.startseite #legend{display:none}
.starthinweis{margin:0 0 12px}
/* B-172: ein beendeter Kundenlink — kein „Start“, der nur wieder abgelehnt würde. */
body.kiosk-ende #startBtn{display:none}
/* Umgebungs-Abzeichen (Prod/Dev-Trennung 21.08.): auffaellig, aber nicht
   schreiend — es soll verhindern, dass jemand Dev fuer Prod haelt. Im Kiosk
   und in der Lese-Ansicht erscheint es NIE (der Kunde sieht kein „DEV"), und
   seit dem 22.08. auch auf Prod nicht mehr (Nutzerentscheid) — die frueher
   hier stehende Warn-Variante .envbadge.prod ist damit entfallen. */
.envbadge{font-size:10.5px;font-weight:700;letter-spacing:.08em;padding:2px 7px;
  border-radius:var(--radius-md);background:var(--accent-subtle);color:var(--accent);
  border:1px solid var(--accent);text-transform:uppercase}
/* Kopf-Auswahl und „Start" werden per hidden geschaltet (Nutzer 21.08.).
   Explizit, damit eine spätere ID-Regel mit display das [hidden] nicht
   aushebelt — die Lehre aus #v3dColors. */
#pickers[hidden],#startBtn[hidden]{display:none}
/* ── Handy und Tablet (Responsive-Etappe E1, 22.08.) ──────────────────────
   Additiv am ENDE des Stilblocks: keine bestehende Regel wird umformuliert,
   nur uebersteuert. --headH kommt aus einem ResizeObserver, weil der Kopf
   mobil mehrzeilig wird und das feste calc(100vh - 52px) sonst zu hoch ist.
   dvh statt vh: die Adressleiste mobiler Browser frisst sonst den Rest. */
@media (max-width:900px){
  html,body{overflow-x:clip}
  body{display:flex;flex-direction:column;min-height:100dvh}
  header{padding:8px 10px;gap:6px;position:sticky;top:0;z-index:60}
  header .sp{display:none}
  header h1{font-size:14px}
  #hdrTools{display:flex;flex-basis:100%;gap:6px;overflow-x:auto;
            scrollbar-width:none;padding-bottom:2px}
  /* Ohne flex:none schrumpfen die Gruppen und brechen um, statt zu scrollen —
     der Kopf wurde dadurch ein Drittel des Bildschirms hoch. */
  #hdrTools>*{flex:none}
  #hdrTools .toggle{flex-wrap:nowrap}
  #hdrTools::-webkit-scrollbar{display:none}
  /* Auswahl und „Start“ teilen eine Zeile — sonst kostet der Knopf allein
     eine weitere Zeile Kopfhoehe. */
  #pickers{display:flex;flex:1 1 auto;gap:6px;min-width:0}
  #accInfo{display:none}   /* steht im Konto-Dialog */
  #defs{flex:1;min-width:0}
  /* Ein Raster, eine Spalte — die Panels liegen mobil als Overlay darueber. */
  .wrap{height:auto;flex:1;min-height:0;
        grid-template-columns:minmax(0,1fr);grid-template-rows:1fr}
  .main{grid-column:1;grid-row:1;padding:10px 12px}
  .split{display:none}
  /* Overlay statt Spalte: das Panel-DOM bleibt an seinem Platz, damit das
     3D-iframe nicht neu laedt. */
  .panel.mobov{position:fixed;left:0;right:0;bottom:0;top:var(--headH,52px);
       z-index:50;border:none;border-top:1px solid var(--border);
       background:var(--surface-1);box-shadow:var(--shadow-lg)}
  .panel.mobov .ph-tools button{min-width:34px}
  /* Eingaben mit 16px, sonst zoomt iOS beim Antippen in das Feld. */
  input,select,textarea{font-size:16px}
}
/* Der Konfigurationsbereich ist ein Groessen-Behaelter: die Formularzeilen
   richten sich nach SEINER Breite, nicht nach der des Fensters. Mit offener
   3D-Ansicht bleiben bei 1280px nur ~370px — dort brach der Artikelname
   buchstabenweise um (im 3D-Pixelvergleich aufgefallen, 22.08.). */
#config{container-type:inline-size}
@container (max-width:560px){
  .frow{grid-template-columns:minmax(0,1fr);gap:4px}
  .flab{padding-top:0}
  .fctl{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
  .fctl .fsel,.fctl>.flist{flex:1 1 100%}
  .fitem{grid-template-columns:26px minmax(0,1fr) max-content;
         grid-template-areas:"schalter name preis" "schalter menge info";
         row-gap:4px;column-gap:8px}
  .fitem>input[type=checkbox]{grid-area:schalter;align-self:start;margin-top:3px}
  .fitem .fname{grid-area:name}
  .fitem .fprice{grid-area:preis;justify-self:end}
  .fitem .fq{grid-area:menge;min-width:0}
  .fitem .fibx{grid-area:info;justify-self:end}
  .qty{grid-template-columns:30px minmax(40px,1fr) 30px minmax(0,auto);gap:4px}
}
/* ── Laufzeit am Handy (Responsive-Etappe E2, 22.08.) ─────────────────────
   Bei 375px blieben von der Zeile 80px fuer die Bedienung uebrig: die
   Beschriftungsspalte nahm 220px, die Rasterspuren der Mengen weitere 288px —
   zehn Elemente liefen aus ihrem Kasten. Unter 640px steht die Beschriftung
   deshalb UEBER der Bedienung, und die Artikelzeile bekommt zwei Zeilen. */
@media (max-width:640px){
  .frow{grid-template-columns:minmax(0,1fr);gap:4px;padding:10px 2px}
  .flab{padding-top:0}
  /* Einfachauswahl: Auswahlfeld eine ganze Zeile, Info und Menge darunter. */
  .fctl{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
  .fctl .fsel{flex:1 1 100%}
  .fctl>.flist{flex:1 1 100%}
  .fctl .fq{flex:0 1 auto}
  /* Mehrfachauswahl: Schalter | Name | Preis, darunter Menge | Info. */
  .fitem{grid-template-columns:26px minmax(0,1fr) max-content;
         grid-template-areas:"schalter name preis" "schalter menge info";
         row-gap:4px;column-gap:8px}
  .fitem>input[type=checkbox]{grid-area:schalter;align-self:start;margin-top:3px}
  .fitem .fname{grid-area:name}
  .fitem .fprice{grid-area:preis;justify-self:end}
  .fitem .fq{grid-area:menge;min-width:0}
  .fitem .fibx{grid-area:info;justify-self:end}
  /* Der Stepper darf schrumpfen, sonst sprengt die Einheit die Zeile. */
  .qty{grid-template-columns:30px minmax(40px,1fr) 30px minmax(0,auto);gap:4px}
  /* Werkzeugleiste der 3D-Ansicht: dreizehn Knoepfe brechen um statt zu
     verschwinden; Farb- und Logofeld nach oben, weil die Leiste zweizeilig ist. */
  #v3dTools{flex-wrap:wrap;row-gap:4px}
  #v3dColors,#v3dLogo{top:10px;bottom:auto;max-width:calc(100vw - 24px)}
  /* Artikelinfo am Handy (Nutzer 23.08.: „die Artikelinfos … scheinen zu groß
     zu sein und überlagern auch den Header"). Zwei Fehler in einer Regel:
     `top:0` legte die Schublade ÜBER den Kopf — sie hat z-index 50, der Kopf
     nicht —, und `height:100%` ab dem Kopf hinaus wäre unten abgeschnitten.
     Sie beginnt jetzt unter dem Kopf wie jedes Panel (dieselbe Messung
     `--headH`) und endet am unteren Rand. Dazu ein Deckel auf das Bild: ein
     hochformatiges Artikelbild füllte sonst den ganzen Schirm, und Benennung,
     Preis und Beschreibung standen darunter im Nichts. */
  .drawer{width:min(340px,100vw);top:var(--headH,52px);bottom:0;height:auto;
          padding:12px}
  .drawer img{max-height:32vh;object-fit:contain;background:var(--surface-2)}
  .drawer h2{font-size:16px}
  .drawer .price{font-size:17px;margin:4px 0 10px}
  /* Im Vollbild der 3D-Ansicht gibt es keinen Kopf — dort wieder ganz oben.
     openInfo() haengt die Schublade dann INS Vollbild-Element um. */
  .panel:fullscreen .drawer{top:0}
}

@media (max-width:480px){
  header h1{display:none}
  #vorlageInp{display:none}
}
/* Fingerbedienung: groessere Ziele, und was nur beim Ueberfahren erscheint,
   bleibt dauerhaft sichtbar — ein Finger kann nicht hovern. */
@media (pointer:coarse){
  button,select,.tab{min-height:40px}
  .qty button{min-width:34px;min-height:34px}
  .fitem .fibx{visibility:visible}
}

/* B-166 (Nutzer 01.10.): Startseite als Kachelübersicht der Konfigurationen. */
.starttitel{font-size:17px;font-weight:600;margin:4px 0 14px}
.kacheln{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:16px}
.kachel{display:flex;flex-direction:column;padding:0;text-align:left;font:inherit;color:inherit;cursor:pointer;
  background:var(--surface-1);border:1px solid var(--border);border-radius:var(--radius-xl);overflow:hidden;
  transition:border-color .12s,box-shadow .12s,transform .12s}
.kachel:hover,.kachel:focus-visible{border-color:var(--accent);box-shadow:var(--shadow-sm);transform:translateY(-1px)}
.kbild{display:flex;align-items:center;justify-content:center;aspect-ratio:480/280;background:var(--surface-2);overflow:hidden}
.kbild img{width:100%;height:100%;object-fit:cover;display:block}
.kinitial{font-size:30px;font-weight:600;color:var(--text-muted);letter-spacing:.04em}
.ktext{display:flex;flex-direction:column;gap:4px;padding:10px 12px 12px}
.ktext b{font-size:14px}
.kbesch{font-size:12.5px;line-height:1.4;color:var(--text-secondary);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}

/* R12c: Eingabefelder und Berechnungen */
.card.angaben .felder{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px 16px}
.card.angaben .feld{display:flex;flex-direction:column;gap:4px;font-size:13px}
.card.angaben .flab{color:var(--text-secondary)}
.card.angaben .fpfl{color:var(--error-text)}
.card.angaben .fein{display:flex;align-items:center;gap:6px}
.card.angaben .fein input{flex:1;min-width:0;box-sizing:border-box}
.card.angaben .fein input.ferr{border-color:var(--error)}
.card.angaben .feinh{color:var(--text-secondary);white-space:nowrap}
.card .fhilfe{font-size:11.5px;color:var(--text-secondary)}
.card .ffehler{font-size:12px;color:var(--error-text)}
.card.rechnung .rtab{width:100%;border-collapse:collapse;font-size:13px}
.card.rechnung .rtab td{padding:5px 4px;border-top:1px solid var(--border);vertical-align:top}
.card.rechnung .rtab tr:first-child td{border-top:0}
.card.rechnung .fwert{text-align:right;white-space:nowrap}
.card.rechnung .fpos{color:var(--text-secondary);font-size:11px}

/* R1: Erklaerbox „So teilen sich Rules und KI die Arbeit“ */
.card.erkl summary{cursor:pointer;font-weight:600}
.card.erkl .erklintro{margin:8px 0 4px}
.card.erkl .erklspalten{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:4px 18px}
.card.erkl ul{margin:4px 0 0;padding-left:18px}
.card.erkl li{margin:2px 0}
