@rslsp1/fa-app-tools 10.3.2 → 10.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/StageEngine-O5I654LD.js +1243 -0
- package/dist/StageEngine-PYWITIIY.mjs +1243 -0
- package/dist/{chunk-ACB2543O.js → chunk-DDH2SGZM.js} +113 -20
- package/dist/{chunk-TFWIMFNF.mjs → chunk-GKLCL2VQ.mjs} +111 -18
- package/dist/{chunk-HFX6D53W.js → chunk-VSHSZEGV.js} +1810 -606
- package/dist/{chunk-JP7LIWDR.mjs → chunk-XLNA2BD6.mjs} +1448 -244
- package/dist/index.d.mts +53 -2
- package/dist/index.d.ts +53 -2
- package/dist/index.js +265 -106
- package/dist/index.mjs +531 -372
- package/dist/szenen.d.mts +610 -279
- package/dist/szenen.d.ts +610 -279
- package/dist/szenen.js +75 -29
- package/dist/szenen.mjs +48 -2
- package/package.json +1 -1
- package/dist/StageEngine-3MOBM2WX.mjs +0 -590
- package/dist/StageEngine-5VR3KEZB.js +0 -590
package/dist/index.mjs
CHANGED
|
@@ -17,12 +17,12 @@ import {
|
|
|
17
17
|
setHFToken,
|
|
18
18
|
tsFromEventPath,
|
|
19
19
|
writeHFEvent
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XLNA2BD6.mjs";
|
|
21
21
|
import "./chunk-FUY2OCVC.mjs";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-GKLCL2VQ.mjs";
|
|
23
23
|
|
|
24
24
|
// package.json
|
|
25
|
-
var version = "10.3.
|
|
25
|
+
var version = "10.3.3";
|
|
26
26
|
|
|
27
27
|
// src/hooks/useOnClickOutside.ts
|
|
28
28
|
import { useEffect } from "react";
|
|
@@ -61,7 +61,7 @@ function useKeyboardNavigation(history, currentResult, setCurrentResult) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// src/features/szenen/szenenViewStyles.generated.ts
|
|
64
|
-
var SZENEN_VIEW_STYLES = '/* ==========================================================================\n SZENEN VIEW\n ========================================================================== */\n\n.szenen-view {\n display: grid;\n gap: var(--space-md);\n width: 100%;\n min-width: 0;\n font-family: var(--font-sans);\n padding: var(--space-md);\n}\n\n@media (max-width: 760px) {\n .szenen-view {\n padding: var(--space-sm);\n gap: var(--space-sm);\n }\n}\n\n/* Kette `szenen-design`, P1 \u2014 Bild zuerst, Text auf Abruf. Der Kopf ist nur\n * noch Titel und \u24D8; die Erklaerung klappt darunter auf. */\n.szenen-view__intro {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--space-sm);\n color: var(--color-text-primary);\n}\n\n.szenen-view__titel {\n display: grid;\n gap: 0.1rem;\n min-width: 0;\n}\n\n.szenen-view__intro h2,\n.szenen-view__intro p {\n margin: 0;\n}\n\n.szenen-view__intro h2 {\n font-size: clamp(1.5rem, 3vw, 1.9rem);\n font-weight: 700;\n letter-spacing: -0.01em;\n line-height: 1.15;\n}\n\n.szenen-view__eyebrow {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.szenen-view .szenen-view__info {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n min-height: 2.75rem;\n padding: 0;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-view__info[aria-expanded="true"] {\n color: var(--color-text-primary);\n border-color: var(--color-accent-teal, #2dd4bf);\n}\n\n.szenen-view__intro-text {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n font-size: 0.85rem;\n line-height: 1.4;\n}\n\n.szenen-icon {\n flex: none;\n}\n\n/* Fuer Screenreader sichtbar, fuer das Auge nicht \u2014 Status-Punkte und\n * Node-Symbole tragen ihre Bedeutung als Text. */\n.szenen-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Die Bereiche als Pill-Leiste. Sie scrollt in sich, nie die Seite: `min-width:\n * 0` haelt sie in der Spalte, `overflow-x: auto` macht jeden Bereich\n * erreichbar, auch wenn nicht alle nebeneinander passen. */\n.szenen-view__nav {\n display: flex;\n flex-wrap: nowrap;\n gap: var(--space-xs);\n min-width: 0;\n padding: 0 0 var(--space-xs);\n overflow-x: auto;\n scrollbar-width: thin;\n}\n\n.szenen-view__nav button,\n.szenen-view button {\n min-height: 2.25rem;\n padding: 0.45rem 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-view button:hover:not(:disabled) {\n color: var(--color-text-primary);\n background: var(--color-bg-surface-hover);\n border-color: var(--color-border-hover);\n}\n\n.szenen-view button:focus-visible,\n.szenen-view input:focus-visible,\n.szenen-view select:focus-visible,\n.szenen-view textarea:focus-visible {\n outline: 2px solid var(--color-accent-blue);\n outline-offset: 2px;\n}\n\n.szenen-view button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.szenen-view .szenen-view__nav button {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.25rem;\n padding: 0 0.9rem;\n white-space: nowrap;\n border-radius: var(--radius-full);\n font-size: 0.875rem;\n}\n\n.szenen-view .szenen-view__nav button.is-active,\n.szenen-view .szenen-view__nav button[aria-selected="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-view__area {\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-view__capability-note,\n.szenen-area__lead {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border-left: 3px solid var(--color-accent-purple);\n border-radius: var(--radius-sm);\n}\n\n.szenen-view__host-notes {\n color: var(--color-text-secondary);\n}\n\n.szenen-view__host-notes > summary {\n cursor: pointer;\n font-size: 0.8rem;\n}\n\n/* `box-sizing` steht hier und nicht beim Host: Die React-App bringt in\n * `master.css` einen globalen `* { box-sizing: border-box }` mit, Flow **nicht**\n * \u2014 dort ragte `width: 100%` plus Innenabstand um die Randbreite aus dem\n * Elternelement heraus und erzeugte auf ~390 px einen horizontalen Scroll. Die\n * gemeinsame Ansicht darf sich auf keinen Host-Reset verlassen. */\n.szenen-view input:not([type="checkbox"]),\n.szenen-view select,\n.szenen-view textarea {\n box-sizing: border-box;\n width: 100%;\n min-height: 2.25rem;\n padding: 0.5rem 0.65rem;\n color: var(--color-text-primary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font: inherit;\n}\n\n.szenen-view textarea {\n min-height: 7rem;\n resize: vertical;\n font-family: var(--font-mono);\n font-size: 0.8rem;\n}\n\n.szenen-view label {\n display: grid;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n.szenen-view code,\n.szenen-view pre {\n font-family: var(--font-mono);\n overflow-wrap: anywhere;\n}\n\n.szenen-view h3,\n.szenen-view h4,\n.szenen-view h5 {\n margin-top: 0;\n}\n\n.szenen-view ul,\n.szenen-view ol {\n padding-left: 1.25rem;\n}\n\n.szenen-elements,\n.szenen-detail,\n.szenen-scene,\n.szenen-setup,\n.szenen-erweitert,\n.szenen-prompts,\n.szenen-shot,\n.szenen-media,\n.szenen-runs {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n/* Arbeitsoberflaeche: Liste links, Bearbeitung rechts.\n *\n * Breit stehen beide Spalten nebeneinander \u2014 die Auswahl bleibt sichtbar,\n * waehrend bearbeitet wird. Schmal rendert die Komponente nur eine der beiden;\n * hier steht deshalb keine Regel, die die andere versteckt. */\n@media (min-width: 761px) {\n .szenen-elements {\n grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);\n align-items: start;\n }\n\n .szenen-elements__master,\n .szenen-elements__detail {\n min-width: 0;\n }\n}\n\n.szenen-elements__master,\n.szenen-elements__detail {\n display: grid;\n gap: var(--space-sm);\n align-content: start;\n min-width: 0;\n}\n\n.szenen-elements__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-elements__heading {\n margin: 0;\n font-size: 1.05rem;\n}\n\n.szenen-elements__scope {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-elements__scope > select {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.szenen-elements__new {\n flex: none;\n font-weight: 700;\n}\n\n.szenen-elements__create {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n}\n\n.szenen-elements__create label {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-elements__create-actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n}\n\n.szenen-elements__options > summary {\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n cursor: pointer;\n}\n\n.szenen-elements__back {\n justify-self: start;\n font-weight: 700;\n}\n\n.szenen-elements__empty-detail {\n margin: 0;\n color: var(--color-text-tertiary);\n}\n\n.szenen-elements__filter,\n.szenen-detail__actions,\n.szenen-runs__start,\n.szenen-scene-editor__add,\n.szenen-scene-editor__add-relation {\n display: flex;\n flex-wrap: wrap;\n align-items: end;\n gap: var(--space-sm);\n}\n\n.szenen-elements__filter > label,\n.szenen-runs__start > label,\n.szenen-scene-editor__add > input {\n flex: 1 1 16rem;\n}\n\n.szenen-elements__filter > label:has(input[type="checkbox"]) {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: row;\n align-items: center;\n}\n\n.szenen-elements__filter input[type="checkbox"] {\n width: 1rem;\n height: 1rem;\n accent-color: var(--color-accent-blue);\n}\n\n.szenen-elements__list {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-elements__list > li > button {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs) var(--space-sm);\n width: 100%;\n height: 100%;\n text-align: left;\n}\n\n.szenen-elements__list > li > button > .szenen-elements__title {\n flex: 1 1 100%;\n}\n\n.szenen-elements__list > li > button.is-selected,\n.szenen-elements__list > li > button[aria-current="true"] {\n background: var(--color-accent-blue-dim);\n border-color: var(--color-accent-blue);\n}\n\n.szenen-elements__type {\n color: var(--color-accent-blue);\n font-size: 0.75rem;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.szenen-elements__title {\n color: var(--color-text-primary);\n font-size: 0.95rem;\n}\n\n.szenen-elements__subtype,\n.szenen-elements__retired {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-elements__retired {\n color: var(--color-warning);\n}\n\n.szenen-detail {\n margin-top: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n@media (min-width: 761px) {\n .szenen-detail {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n }\n}\n\n.szenen-detail > header,\n.szenen-detail__heads,\n.szenen-detail__draft,\n.szenen-capability {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n/* .szenen-runs ist ein eigenst\xE4ndiger sichtbarer Bereich, beh\xE4lt Styling auf Desktop */\n@media (min-width: 761px) {\n .szenen-runs {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n }\n}\n\n@media (max-width: 760px) {\n .szenen-runs {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n}\n\n.szenen-detail__ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin-bottom: 0;\n color: var(--color-text-secondary);\n}\n\n.szenen-detail__heads ul,\n.szenen-scene-editor ul,\n.szenen-runs > ol,\n.szenen-capability > ul {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-detail__heads li,\n.szenen-scene-editor li,\n.szenen-runs > ol > li,\n.szenen-capability > ul > li {\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n\n/* Stufe 6.7.2 (D-126) \u2014 Advanced-/Debug-Fl\xE4che f\xFCr die rohe, schema-getriebene\n * Feldliste einer Szene. Gestrichelt wie die anderen \u201EAngebot statt\n * Auskunft"-Bereiche, aber ohne Akzentfarbe: sie ist kein Vorschlag, sondern\n * ein Eskalationsweg. */\n.szenen-detail__technical {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__technical > summary {\n margin-bottom: var(--space-sm);\n color: var(--color-text-secondary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-detail__technical[open] > summary {\n margin-bottom: var(--space-md);\n}\n\n.szenen-detail__field small,\n.szenen-capability small {\n color: var(--color-text-tertiary);\n}\n\n.szenen-detail__preview-errors,\n.szenen-detail__notice--error,\n.szenen-view [role="alert"] {\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-color: var(--color-accent-red);\n}\n\n.szenen-detail__notice {\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__notice--success,\n.szenen-view [data-tone="success"] {\n color: #bbf7d0;\n background: var(--color-accent-green-dim);\n border-color: var(--color-accent-green);\n}\n\n.szenen-scene-editor {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--space-md);\n margin-bottom: 0;\n}\n\n.szenen-scene-editor > section {\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n/* \u2500\u2500 Stufe 6.7.2 (D-126): Node-/Relationskarten \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Nodes und Beziehungen sind `<details>` \u2014 dieselbe Interaktionssprache wie\n * \u201ERohantwort (Diagnose)" und \u201EBilder zu diesem Lauf" in RunsPanel.tsx. Kopf\n * (immer sichtbar) tr\xE4gt Inhalt zuerst, Technik zuletzt; Body (nur bei\n * ge\xF6ffneter Karte) tr\xE4gt die Bearbeitungscontrols. Padding wandert von der\n * `<li>` in Kopf/Body, damit die Karte keinen doppelten Rand bekommt. */\n.szenen-scene-editor li {\n padding: 0;\n overflow: hidden;\n}\n\n.szenen-node-karte__kopf,\n.szenen-relation-karte__kopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs) var(--space-sm);\n padding: var(--space-sm);\n cursor: pointer;\n list-style: none;\n}\n\n.szenen-node-karte__kopf::-webkit-details-marker,\n.szenen-relation-karte__kopf::-webkit-details-marker {\n display: none;\n}\n\n.szenen-node-karte__titel {\n flex: 1 1 12rem;\n min-width: 0;\n color: var(--color-text-primary);\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.szenen-node-karte__typ {\n flex: none;\n padding: 0.15rem 0.55rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.72rem;\n white-space: nowrap;\n}\n\n/* node_id klein, monospace, sekund\xE4r \u2014 sichtbar auch bei zugeklappter Karte,\n * aber optisch klar hinter Beschreibung und Typ. */\n.szenen-node-karte__meta {\n flex: 1 1 100%;\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n}\n\n.szenen-node-karte__meta code {\n font-size: inherit;\n}\n\n.szenen-node-karte__body,\n.szenen-relation-karte__body {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm) var(--space-sm) var(--space-sm);\n border-top: 1px solid var(--color-border);\n}\n\n/* \xA74 \u2014 Prim\xE4raktion und destruktive Aktion optisch getrennt: \u201ENode/Beziehung\n * entfernen" bekommt einen eigenen, warnenden Ton statt gleichgewichtig neben\n * der normalen Bearbeitung zu stehen. */\n.szenen-node-karte__entfernen,\n.szenen-relation-karte__entfernen {\n justify-self: start;\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-color: var(--color-accent-red);\n}\n\n.szenen-relation-karte__kopf {\n font-size: 0.9rem;\n}\n\n.szenen-relation-karte__kopf code {\n overflow-wrap: anywhere;\n}\n\n.szenen-relation-karte__pfeil {\n flex: none;\n color: var(--color-text-secondary);\n}\n\n/* Die Composer-\xD6ffner (\u201E+ Node hinzuf\xFCgen", \u201E+ Beziehung hinzuf\xFCgen") sind\n * Angebote, keine Ausk\xFCnfte \u2014 dasselbe gestrichelte Muster wie beim Folgelauf\n * und der Fehlerrettung (\xA73.3/\xA73.5). */\n.szenen-scene-editor__oeffnen {\n width: 100%;\n border-style: dashed;\n}\n\n.szenen-refpicker {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n margin: var(--space-sm) 0;\n padding: var(--space-sm) 0;\n border: none;\n border-radius: 0;\n}\n\n.szenen-refpicker legend {\n padding: 0 var(--space-xs);\n color: var(--color-text-secondary);\n font-weight: 600;\n}\n\n.szenen-capability > ul > li {\n display: grid;\n grid-template-columns: minmax(10rem, 1fr) auto minmax(14rem, 2fr);\n align-items: start;\n gap: var(--space-sm);\n}\n\n.szenen-capability__state {\n padding: 0.1rem 0.5rem;\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.szenen-capability__state--yes {\n color: #bbf7d0;\n background: var(--color-accent-green-dim);\n}\n\n.szenen-capability__state--no {\n color: #fecaca;\n background: var(--color-accent-red-dim);\n}\n\n.szenen-capability__state--unknown {\n color: #fef08a;\n background: rgba(234, 179, 8, 0.2);\n}\n\n.szenen-runs > ol > li {\n display: grid;\n gap: var(--space-sm);\n}\n\n/* B1 \u2014 die geschlossene Runde. Vorher stand die `run_id` als erstes und war\n die einzige Information, die niemand liest; jetzt beantwortet die Kopfzeile\n welche Runde, ob sie durchging, mit welchem Modell und was ungef\xE4hr\n herauskam. */\n.szenen-runs__hinweis {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n}\n\n.szenen-runs__kopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-sm);\n width: 100%;\n padding: var(--space-xs) 0;\n text-align: left;\n color: var(--color-text-secondary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.szenen-runs__marke {\n font-weight: 700;\n color: var(--color-text-primary);\n}\n\n.szenen-runs__status {\n padding: 0.05rem 0.4rem;\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n border-radius: var(--radius-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n}\n\n.szenen-runs__status[data-status="succeeded"] {\n border-color: var(--color-success);\n}\n\n.szenen-runs__status[data-status="failed"] {\n border-color: var(--color-danger);\n}\n\n.szenen-runs__modell {\n font-size: 0.75rem;\n}\n\n/* Der Auszug ist die Inhaltsvorschau der Runde. Er bekommt eine eigene Zeile,\n damit er nicht mit Marke und Modell um dieselbe Zeile ringt. */\n.szenen-runs__auszug {\n flex: 1 1 100%;\n min-width: 0;\n color: var(--color-text-tertiary);\n font-size: 0.8125rem;\n}\n\n/* B2 \u2014 ein Fehler steht ausserhalb der aufklappbaren Fl\xE4che: Wer eine rote\n Runde sieht, soll nicht erst klicken m\xFCssen, um zu erfahren, woran sie\n gescheitert ist. */\n.szenen-runs__fehler {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-sm);\n border-radius: var(--radius-sm);\n}\n\n.szenen-runs__fehler p {\n margin: 0;\n}\n\n.szenen-runs__inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-runs__prompt > h5,\n.szenen-runs__sekundaer > h5 {\n margin: 0 0 var(--space-xs);\n}\n\n/* Im Kopf traegt die Zeile selbst den Abstand \u2014 sonst kaeme er doppelt. */\n.szenen-runs__promptkopf > h5 {\n margin: 0;\n}\n\n/* Ueberschrift und Kopierknopf in einer Zeile. Der Knopf gehoert an den Text,\n den er kopiert \u2014 nicht an den Rand der Runde, wo er neben dem falschen\n Abschnitt stuende. */\n.szenen-runs__promptkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-sm);\n margin: 0 0 var(--space-xs);\n}\n\n/* Ein kompakter Knopf, kein zweiter Titel: Der Prompt ist die Hauptsache des\n Abschnitts, die Aktion daneben darf ihn nicht ueberstimmen. Rahmen und\n Hintergrund kommen aus `.szenen-view button` und bleiben \u2014 dieselbe Optik wie\n jeder andere Knopf der Ansicht; hier wird nur die Groesse zurueckgenommen.\n Zwei Klassen im Selektor, weil `.szenen-view button` sonst spezifischer ist. */\n.szenen-runs__promptkopf .szenen-runs__kopieren {\n min-height: 0;\n padding: 0.1rem 0.45rem;\n font-size: 0.72rem;\n}\n\n/* Regel 11: die Bestaetigung nennt die Zahl, nicht nur \u201EErfolgreich". */\n.szenen-runs__kopiert {\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-size: 0.72rem;\n}\n\n.szenen-runs__prompt > p {\n margin: 0;\n white-space: pre-wrap;\n}\n\n.szenen-runs__prompt--negativ > p,\n.szenen-runs__sekundaer > p {\n margin: 0;\n color: var(--color-text-secondary);\n white-space: pre-wrap;\n}\n\n.szenen-runs__mehr {\n justify-self: start;\n margin-top: var(--space-xs);\n padding: 0;\n color: var(--color-accent-teal, var(--color-text-secondary));\n background: transparent;\n border: none;\n font-size: 0.75rem;\n text-decoration: underline;\n cursor: pointer;\n}\n\n.szenen-runs > ol > li[data-status="succeeded"] {\n border-left: 3px solid var(--color-success);\n}\n\n.szenen-runs > ol > li[data-status="failed"] {\n border-left: 3px solid var(--color-danger);\n}\n\n.szenen-runs details pre {\n max-height: 20rem;\n overflow: auto;\n padding: var(--space-sm);\n white-space: pre-wrap;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border-radius: var(--radius-sm);\n}\n\n.szenen-media > section {\n display: grid;\n gap: var(--space-sm);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-media__lookup,\n.szenen-media__attach {\n display: flex;\n flex-wrap: wrap;\n align-items: end;\n gap: var(--space-sm);\n}\n\n.szenen-media__lookup > label,\n.szenen-media__attach > label:first-child {\n flex: 1 1 18rem;\n}\n\n.szenen-media__list {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-media__list > li {\n display: grid;\n grid-template-columns: minmax(12rem, 1fr) auto auto auto;\n align-items: center;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n@media (max-width: 760px) {\n .szenen-view {\n gap: var(--space-sm);\n }\n\n /* C1 \u2014 auf 390 px bleiben drei Kacheln je Reihe gross genug zum Erkennen\n und klein genug, dass vier Bilder eine Reihe sind und keine Seite. */\n .szenen-bildgalerie {\n grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));\n }\n\n /* Der Viewer bekommt den ganzen Bildschirm; die Bl\xE4tterkn\xF6pfe bleiben am\n Rand, wo der Daumen sie erreicht. */\n .szenen-bildviewer {\n padding: var(--space-xs);\n }\n\n .szenen-bildviewer__blaettern {\n width: 2.25rem;\n height: 4rem;\n }\n\n .szenen-view__nav {\n position: sticky;\n top: 0;\n z-index: 2;\n padding: var(--space-xs) 0;\n background: var(--color-bg-app);\n }\n\n\n .szenen-scene-editor {\n grid-template-columns: 1fr;\n }\n\n .szenen-capability > ul > li {\n grid-template-columns: 1fr;\n }\n\n .szenen-derive,\n .szenen-elements,\n .szenen-scene,\n .szenen-setup,\n .szenen-shot,\n .szenen-media,\n .szenen-runs {\n gap: var(--space-sm);\n }\n\n .szenen-elements__filter {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-sm);\n }\n\n .szenen-elements__filter > label {\n width: 100%;\n min-width: 0;\n flex: none;\n }\n\n .szenen-elements__filter > label:has(input[type="checkbox"]) {\n flex: none;\n grid-column: 1 / -1;\n }\n\n /* Schmal ist die Liste eine Spalte, und die Auswahl fuehrt weiter \u2014 der\n * Eintrag ist deshalb ein Ziel fuer den Finger, keine Kachel. */\n .szenen-elements__list {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .szenen-elements__list > li > button {\n min-height: 2.75rem;\n }\n\n .szenen-elements__back {\n justify-self: stretch;\n min-height: 2.5rem;\n }\n\n .szenen-detail__actions,\n .szenen-runs__start,\n .szenen-scene-editor__add,\n .szenen-scene-editor__add-relation {\n align-items: stretch;\n flex-direction: column;\n }\n\n .szenen-runs__start > *,\n .szenen-scene-editor__add > *,\n .szenen-scene-editor__add-relation > * {\n width: 100%;\n flex: none;\n }\n}\n\n/* \u2500\u2500 Kette `szenen-design`, P2: Szenen-\xDCbersicht als Bildgalerie \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Kacheln wie in der Library: quadratisch, Deckbild, Titel ueber einem\n * Verlauf, Bildzahl als Plakette. Eine Szene ohne Bild zeigt ihre\n * Node-Symbole; ein nicht ladbares Deckbild nennt den Grund. Die Schrift auf\n * dem Bild ist hell auf dunklem Verlauf \u2014 unabhaengig vom Hostthema, weil das\n * Bild es auch ist. */\n.szenen-galerie {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-galerie__kopf > .szenen-elements__heading {\n flex: 1 1 auto;\n margin: 0;\n}\n\n.szenen-galerie__anzahl,\n.szenen-galerie__sortierung {\n color: var(--color-text-secondary);\n font-weight: 400;\n}\n\n.szenen-galerie__sortierung {\n font-size: 0.8rem;\n}\n\n.szenen-galerie__raster {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr));\n gap: 0.625rem;\n min-width: 0;\n}\n\n/* Die Kacheln sind Zellen desselben Rasters wie die Neu-Kachel. */\n.szenen-view .szenen-galerie__liste {\n display: contents;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-galerie__kachel {\n min-width: 0;\n}\n\n.szenen-view .szenen-galerie__kachel > button,\n.szenen-view .szenen-galerie__neu,\n.szenen-view .szenen-galerie__zuletzt {\n position: relative;\n display: block;\n width: 100%;\n min-width: 0;\n padding: 0;\n overflow: hidden;\n color: var(--color-text-primary);\n text-align: left;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-galerie__kachel > button {\n aspect-ratio: 1 / 1;\n}\n\n.szenen-view .szenen-galerie__kachel > button[aria-current="true"],\n.szenen-view .szenen-galerie__zuletzt[aria-current="true"] {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-galerie__bild {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-galerie__scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.4) 40%, rgba(0, 0, 0, 0) 65%);\n}\n\n.szenen-galerie__ohnebild {\n position: absolute;\n inset: 0;\n padding: 0.75rem;\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 14px 14px,\n var(--color-bg-surface);\n}\n\n.szenen-galerie__bildfehler {\n position: absolute;\n inset: 0;\n /* Oben Platz fuer Status-Punkte und Bildzahl, die darueber liegen. */\n padding: 2.25rem 0.75rem 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n font-size: 0.75rem;\n line-height: 1.3;\n}\n\n.szenen-galerie__text {\n position: absolute;\n right: 0.75rem;\n bottom: 0.7rem;\n left: 0.75rem;\n display: grid;\n gap: 0.25rem;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__text,\n.szenen-galerie__zuletzt--mitbild .szenen-galerie__zuletzt-text {\n color: #fff;\n}\n\n.szenen-galerie__titel {\n display: -webkit-box;\n overflow: hidden;\n font-size: 0.875rem;\n font-weight: 650;\n line-height: 1.25;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n overflow-wrap: anywhere;\n}\n\n.szenen-galerie__meta {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__meta,\n.szenen-galerie__zuletzt--mitbild .szenen-galerie__meta {\n color: rgba(255, 255, 255, 0.82);\n}\n\n.szenen-galerie__tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n min-width: 0;\n}\n\n.szenen-galerie__tag {\n max-width: 100%;\n padding: 0.05rem 0.4rem;\n overflow: hidden;\n color: inherit;\n background: var(--color-bg-elevated);\n border-radius: var(--radius-full);\n font-size: 0.68rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__tag {\n background: rgba(0, 0, 0, 0.5);\n}\n\n.szenen-galerie__status {\n position: absolute;\n top: 0.7rem;\n left: 0.7rem;\n display: flex;\n gap: 0.3rem;\n}\n\n.szenen-galerie__punkt {\n width: 0.625rem;\n height: 0.625rem;\n background: var(--color-text-secondary);\n border-radius: 50%;\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.55);\n}\n\n.szenen-galerie__punkt[data-ton="info"] { background: var(--color-accent-blue); }\n.szenen-galerie__punkt[data-ton="ok"] { background: var(--color-success); }\n.szenen-galerie__punkt[data-ton="fertig"] { background: var(--color-warning); }\n/* Unvollstaendig ist ein Ring: Die Form unterscheidet es von \u201Evollstaendig",\n * nicht nur der Farbton (P8). */\n.szenen-galerie__punkt[data-ton="warn"] {\n background: transparent;\n box-shadow: inset 0 0 0 2px var(--color-accent-orange), 0 0 0 2px rgba(0, 0, 0, 0.55);\n}\n\n/* Die Legende der Punkte \u2014 einmal je Ansicht. */\n.szenen-statuslegende {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem 0.85rem;\n margin: 0;\n padding: 0;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n list-style: none;\n}\n\n.szenen-statuslegende__eintrag {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-statuslegende .szenen-galerie__punkt {\n display: inline-block;\n width: 0.5rem;\n height: 0.5rem;\n}\n\n.szenen-galerie__bildzahl {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.15rem 0.5rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.65);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.szenen-galerie__symbole {\n display: flex;\n flex-wrap: wrap;\n gap: 0.3rem;\n}\n\n.szenen-galerie__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 1.875rem;\n height: 1.875rem;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-galerie__symbol[data-node-type="light"] {\n color: var(--color-warning);\n}\n\n.szenen-galerie__symbol--rest {\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n}\n\n.szenen-view .szenen-galerie__neu {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.6rem;\n aspect-ratio: 1 / 1;\n text-align: center;\n background: var(--color-bg-app);\n border: 1.5px dashed var(--color-border-hover, var(--color-border));\n}\n\n.szenen-galerie__neu-plus {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-accent-teal, #2dd4bf);\n border-radius: 50%;\n}\n\n.szenen-galerie__neu-titel {\n font-size: 0.95rem;\n font-weight: 600;\n}\n\n.szenen-galerie__neu-text {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__zuletzt-bild {\n position: relative;\n display: block;\n aspect-ratio: 4 / 3;\n max-height: 17rem;\n width: 100%;\n}\n\n.szenen-galerie__chip {\n position: absolute;\n top: 0.75rem;\n left: 0.75rem;\n padding: 0.3rem 0.6rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.6);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__zuletzt .szenen-galerie__status {\n right: 0.75rem;\n left: auto;\n top: 1rem;\n}\n\n/* Die Symbole einer Szene ohne Bild stehen unter dem Chip, nicht darauf. */\n.szenen-galerie__zuletzt .szenen-galerie__ohnebild {\n padding-top: 3rem;\n}\n\n.szenen-galerie__zuletzt-text {\n position: absolute;\n right: 1rem;\n bottom: 0.9rem;\n left: 1rem;\n display: grid;\n gap: 0.35rem;\n}\n\n.szenen-galerie__zuletzt-text .szenen-galerie__titel {\n font-size: 1.3rem;\n font-weight: 700;\n line-height: 1.2;\n}\n\n.szenen-galerie__zuletzt-fuss {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n padding: 0.75rem 0.9rem;\n}\n\n.szenen-galerie__oeffnen {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.25rem;\n color: var(--color-accent-teal, #2dd4bf);\n font-size: 0.875rem;\n font-weight: 600;\n}\n\n/* \u2500\u2500 Stufe 6.5: Rekonstruktion \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Bereich zeigt drei Dinge nebeneinander: den Vorschlag, das nicht\n * Ableitbare und die Widerspr\xFCche. Die Diagnosen sind deshalb bewusst nicht\n * kleiner gesetzt als der Vorschlag \u2014 wer sie \xFCbersieht, \xFCbernimmt Geratenes.\n */\n\n.szenen-derive {\n display: grid;\n gap: var(--space-md);\n}\n\n.szenen-form {\n display: grid;\n gap: var(--space-sm);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-field {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-field > span {\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.szenen-error {\n padding: var(--space-sm) var(--space-md);\n color: var(--color-danger);\n background: var(--color-accent-red-dim);\n border: 1px solid var(--color-accent-red);\n border-radius: var(--radius-sm);\n}\n\n.szenen-empty {\n padding: var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-diagnose {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-warning);\n border-radius: var(--radius-sm);\n}\n\n/* Ein Widerspruch ist der schwerste der drei Befunde: dort steht eine\n * Entscheidung aus, die das System bewusst nicht getroffen hat (D-74). */\n.szenen-diagnose--konflikt {\n border-left-color: var(--color-danger);\n}\n\n.szenen-diagnose > h4 {\n margin: 0 0 var(--space-sm);\n font-size: 0.9375rem;\n}\n\n.szenen-diagnose ul {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding-left: var(--space-md);\n}\n\n.szenen-proposal {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-proposal > h4 {\n margin: 0 0 var(--space-sm);\n font-family: var(--font-mono);\n font-size: 0.9375rem;\n}\n\n.szenen-proposal__payload {\n max-height: 18rem;\n margin: 0 0 var(--space-sm);\n padding: var(--space-sm);\n overflow: auto;\n /* Ein erzeugter Prompt ist ein einziger langer Satz \u2014 ohne Umbruch\n verschwindet er nach rechts aus dem Bild. JSON-Payloads bringen ihre\n eigenen Zeilenumbrueche mit und leiden nicht darunter. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font-family: var(--font-mono);\n font-size: 0.8125rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-proposal__done {\n margin: var(--space-sm) 0 0;\n color: var(--color-success);\n}\n\n/* Die Belege eines Laufs: Rohantwort und Systemprompt. Zum Lesen und Kopieren,\n nicht zum Bedienen \u2014 deshalb voll markierbar und in Monospace. */\n.szenen-beleg__text {\n width: 100%;\n margin: var(--space-sm) 0 0;\n padding: var(--space-sm);\n font-family: var(--font-mono);\n font-size: 0.8125rem;\n line-height: 1.5;\n white-space: pre;\n background: var(--color-bg-app);\n color: var(--color-text);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n resize: vertical;\n}\n\n/* Der Folgelauf (D-87): abgesetzt, damit er nicht wie Teil des Ergebnisses\n aussieht \u2014 er ist eine Frage, keine Auskunft. */\n.szenen-folgelauf {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-folgelauf > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-run__herkunft {\n margin: 0 0 var(--space-sm);\n font-size: 0.875rem;\n color: var(--color-text-muted, inherit);\n}\n\n/* Widerspricht das Modell, ist das das Wichtigste auf der Seite. */\n.szenen-diagnose--antwort {\n border-left: 3px solid var(--color-accent, var(--color-border));\n}\n\n/* Der Bildw\xE4hler (D-92) \u2014 Browser und Inspector, dem Labs-Tab nachgebildet,\n aber mit dem CSS dieser Ansicht: eine gemeinsame Komponente \xFCber zwei\n Dom\xE4nengrenzen w\xE4re eine Kopplung, die keiner gewollt hat.\n\n Der Review vom 2026-08-22 (R12.1/R12.2) hat den Ma\xDFstab gesetzt: Der Bestand\n ist ein **Browser**, kein Seiteninhalt. Vierzig Werke d\xFCrfen die Szenenseite\n nicht meterlang machen, und zw\xF6lf Varianten eines Werkes keine zw\xF6lf\n Bildschirmseiten. Deshalb steht hier alles unter zwei Regeln \u2014 begrenzte\n Fl\xE4che mit eigenem Scroll, und Kacheln statt Karten. */\n\n/* \u2500\u2500 Ebene 1: der Browser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl {\n /* Dieselbe Begr\xFCndung wie beim Inspector: Als Grid-Element w\xFCrde der\n W\xE4hler sonst so breit wie sein breitester Inhalt. */\n min-width: 0;\n}\n\n.szenen-bildwahl__browser {\n /* Die eigene Scrollfl\xE4che ist der ganze Punkt: Der Bestand w\xE4chst nach\n innen, nicht nach unten. Dieselbe Gr\xF6\xDFenordnung wie `max-h-[300px]` im\n Labs-Browser. */\n max-height: 19rem;\n overflow-y: auto;\n overscroll-behavior: contain;\n margin-top: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__raster {\n display: grid;\n /* Vier Spalten auf schmalen Displays \u2014 der gemeldete Screenshot zeigte eine\n einzige Spalte gro\xDFer Karten. Breiter wird automatisch dichter. */\n grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildwahl__karte {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n overflow: hidden;\n background: var(--color-bg-surface);\n text-align: left;\n cursor: pointer;\n}\n\n/* Das fokussierte Werk ist klar markiert \u2014 sonst wei\xDF niemand, wessen Galerie\n der Inspector unten zeigt. */\n.szenen-bildwahl__karte.is-fokus {\n border-color: var(--color-accent, var(--color-text-primary));\n box-shadow: 0 0 0 2px var(--color-accent, var(--color-text-primary));\n}\n\n/* \u2500\u2500 Die Kachel selbst \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Der Platz steht, bevor das Bild da ist \u2014 sonst springt das Raster, sobald\n die erste Vorschau eintrifft. */\n.szenen-bildkachel {\n display: block;\n width: 100%;\n aspect-ratio: 1;\n overflow: hidden;\n background: var(--color-bg-app);\n}\n\n.szenen-bildkachel img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.szenen-bildkachel__leer {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, var(--color-bg-app), var(--color-bg-surface));\n}\n\n/* R12.3: Eine fehlende Vorschau bleibt kachelgro\xDF. Vorher fiel die Karte auf\n ihren Prompttext zur\xFCck \u2014 und ein Prompt hat im echten Bestand mehrere\n hundert Zeichen. */\n.szenen-bildkachel__zeichen {\n font-size: 0.875rem;\n font-weight: 700;\n color: var(--color-text-secondary);\n opacity: 0.6;\n}\n\n/* Wie viele Varianten das Werk hat \u2014 klein und \xFCberlagernd, nie als\n dominanter Text. */\n.szenen-bildwahl__anzahl {\n position: absolute;\n top: 0.15rem;\n right: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n font-weight: 700;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* Eine Zeile, dann Schluss. Der Prompt eines Werkes ist oft mehrere hundert\n Zeichen lang und w\xE4re als Prim\xE4rdarstellung genau die Textw\xFCste, gegen die\n der Review antritt. */\n.szenen-bildwahl__kacheltitel {\n display: block;\n padding: 0.15rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.3;\n color: var(--color-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Ebene 2: der Inspector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl__inspector {\n /* Ohne `min-width: 0` gewinnt der Inhalt: Der W\xE4hler ist Element eines\n Grids (`.szenen-form`), und dort ist `min-width: auto` die Vorgabe. Der\n Streifen unten ist rund 1000 px breit \u2014 gemessen am 2026-08-22 im echten\n Browser zog er die Auswahl von 374 px auf 1088 px auf und schob die\n ganze Seite waagerecht heraus, statt selbst zu scrollen. */\n min-width: 0;\n margin-top: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n /* Sichtbar abgesetzt vom Browser: zwei Ebenen, nicht eine lange Liste. */\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent, var(--color-border));\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__inspektorkopf {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bildwahl__werktitel {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--color-text-primary);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bildwahl__zurueck {\n flex: 0 0 auto;\n font-size: 0.6875rem;\n padding: 0.15rem 0.5rem;\n}\n\n/* Der Streifen: waagerecht scrollend, feste kleine Kacheln \u2014 zw\xF6lf Varianten\n bleiben ein \xDCberblick statt zw\xF6lf Bildschirmseiten. */\n.szenen-bildwahl__streifen {\n /* Die Breite kommt vom Elter, nie vom Inhalt \u2014 sonst scrollt hier nichts. */\n max-width: 100%;\n display: flex;\n gap: var(--space-sm);\n margin: 0;\n padding: 0 0 0.25rem;\n list-style: none;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n}\n\n.szenen-bildwahl__streifen > li {\n flex: 0 0 auto;\n width: 5rem;\n}\n\n.szenen-bildwahl__variante {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n overflow: hidden;\n background: var(--color-bg-app);\n cursor: pointer;\n}\n\n.szenen-bildwahl__variante.is-gewaehlt {\n border-color: var(--color-accent, var(--color-text-primary));\n box-shadow: 0 0 0 2px var(--color-accent, var(--color-text-primary));\n}\n\n.szenen-bildwahl__nummer {\n position: absolute;\n bottom: 0.15rem;\n left: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n/* \u2500\u2500 Das Gew\xE4hlte \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl__gewaehlt {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: var(--space-sm) 0 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildwahl__gewaehlt li {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.8125rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n max-width: 100%;\n}\n\n/* Das gew\xE4hlte Bild wird best\xE4tigt, nicht nur benannt: eine kleine Vorschau\n neben dem Titel. */\n.szenen-bildwahl__gewaehlt .szenen-bildkachel {\n width: 2.25rem;\n flex: 0 0 auto;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__gewaehlt .szenen-bildwahl__kacheltitel {\n min-width: 0;\n max-width: 12rem;\n font-size: 0.75rem;\n}\n\n.szenen-beleg__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n margin-top: var(--space-sm);\n}\n\n.szenen-diagnose > details + details {\n margin-top: var(--space-sm);\n}\n\n.szenen-diagnose > details > summary {\n cursor: pointer;\n font-weight: 600;\n}\n\n/* \u2500\u2500 Die Fehlerrettung (Stufe 6.6, A5) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Sie steht im Fehlerblock und muss trotzdem als Werkzeug lesbar sein, nicht\n * als weitere Fehlermeldung. Deshalb abgesetzt wie der Folgelauf \u2014 und aus\n * demselben Grund: Beides sind Angebote, keine Ausk\xFCnfte.\n *\n * Der wichtigste optische Punkt ist die Trennung von Original und\n * Arbeitskopie. Das Original bekommt den ruhigen, \u201Efesten" Hintergrund der\n * Belege; die Kopie sieht aus wie ein normales Eingabefeld, weil sie eines\n * ist. */\n.szenen-rettung {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-rettung > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-rettung textarea[readonly] {\n background: var(--color-bg-surface);\n color: var(--color-text-secondary);\n font-family: var(--font-mono, monospace);\n font-size: 0.8125rem;\n}\n\n.szenen-rettung textarea:not([readonly]) {\n font-family: var(--font-mono, monospace);\n font-size: 0.8125rem;\n}\n\n.szenen-rettung__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: var(--space-sm) 0;\n}\n\n/* Ein Befund tr\xE4gt Code, Bezug und Meldung. Der Code steht klein und\n * monospaced davor: Er ist die Kennung, nicht die Aussage. */\n.szenen-diagnose__liste {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding-left: var(--space-md);\n}\n\n.szenen-diagnose__liste code {\n font-size: 0.8125rem;\n}\n\n.szenen-diagnose__liste > li[data-severity=\'warning\'] {\n color: var(--color-text-secondary);\n}\n\n/* \u2500\u2500 Die Draft-Kette (Stufe 6.6, C4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Hauptweg. Er steht nach den Einzel\xFCbernahmen und muss als das erkennbar\n * sein, was er ist: nicht eine weitere Option, sondern der k\xFCrzere Weg zum\n * selben Ziel. Deshalb durchgezogener Rahmen statt gestricheltem \u2014 er ist\n * Angebot **und** Empfehlung. */\n.szenen-kette {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent, var(--color-border));\n border-radius: var(--radius-sm);\n}\n\n.szenen-kette > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-kette ul {\n display: grid;\n gap: var(--space-xs);\n margin: 0 0 var(--space-sm);\n padding-left: var(--space-md);\n}\n\n.szenen-kette code {\n font-size: 0.8125rem;\n}\n\n/* Ein Hinweis, der eine Bedingung erklaert \u2014 nicht rot, weil er kein Fehler\n ist, aber abgesetzt, weil er eine Folge hat. */\n.szenen-detail__hint {\n margin: var(--space-sm) 0 0;\n padding: var(--space-sm);\n font-size: 0.875rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border-left: 3px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* \u2500\u2500 Stufe 6.7: Bilder am Prompt-Lauf (H0/H1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Bereich tr\xE4gt zwei Dinge, die man nie verwechseln darf: den **Eingang**\n * (woraus der Prompt entstand) und den **Ausgang** (was daraus wurde). Sie\n * bekommen deshalb verschiedene Akzentkanten statt nur verschiedener\n * \xDCberschriften \u2014 wer schnell liest, sieht die Trennung, bevor er sie liest.\n */\n.szenen-bilder {\n display: grid;\n gap: var(--space-md);\n margin-top: var(--space-sm);\n}\n\n.szenen-bilder__eingang,\n.szenen-bilder__ausgang {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__eingang {\n border-left: 3px solid var(--color-accent-purple, var(--color-border));\n}\n\n.szenen-bilder__ausgang {\n border-left: 3px solid var(--color-accent-teal, var(--color-border));\n}\n\n.szenen-bilder h5 {\n margin: 0;\n}\n\n.szenen-bilder__ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: 0;\n align-items: baseline;\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.szenen-bilder__eingangsliste,\n.szenen-bilder__batchliste,\n.szenen-bilder__auftraege {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bilder__eingangsliste > li,\n.szenen-bilder__batchliste > li,\n.szenen-bilder__auftraege > li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font-size: 0.8125rem;\n}\n\n/* Ein unterbrochener Auftrag ist der Fall, f\xFCr den der Auftragssatz existiert.\n Er wird deshalb markiert \u2014 nicht rot, denn er ist kein Fehler, sondern eine\n offene Entscheidung. */\n.szenen-bilder__auftraege > li[data-status="started"] {\n border-left: 3px solid var(--color-warning);\n}\n\n.szenen-bilder__auftraege > li[data-status="succeeded"] {\n border-left: 3px solid var(--color-success);\n}\n\n.szenen-bilder__auftraege > li[data-status="partial"] {\n border-left: 3px solid var(--color-accent-blue, var(--color-border));\n}\n\n.szenen-bilder__auftraege > li[data-status="failed"] {\n border-left: 3px solid var(--color-danger);\n}\n\n/* Das Eingangsbild benutzt seit C3 dieselbe Kachel wie W\xE4hler und Galerie.\n Sie ist von Haus aus so breit wie ihr Platz \u2014 in dieser Zeile bekommt sie\n deshalb eine feste Gr\xF6sse, sonst sch\xF6be sie die Metadaten heraus. */\n.szenen-bilder__eingangsliste .szenen-bildkachel {\n flex: 0 0 auto;\n width: 4rem;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__batch {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__batchkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-bilder__herkunft {\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n}\n\n/* Review-Befund \u2014 ein transienter Bildfehler ist wiederholbar, kein\n endg\xFCltiges \u201Efehlt". Dezent wie ein Angebot, nicht wie ein Fehlerzustand. */\n.szenen-bilder__retry {\n justify-self: start;\n padding: 0.15rem 0.5rem;\n font-size: 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n/* C4 \u2014 die Provenienz vollst\xE4ndig, aber sekund\xE4r. */\n.szenen-bilder__technik > summary {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.szenen-bilder__meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n font-size: 0.75rem;\n color: var(--color-text-secondary);\n}\n\n/* C5 \u2014 der Verlauf verdichtet, seine Ausreisser nicht. */\n.szenen-bilder__verlauf > summary {\n color: var(--color-text-secondary);\n font-size: 0.8125rem;\n cursor: pointer;\n}\n\n.szenen-bilder__verlauf[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bilder__auffaellig {\n margin: 0;\n padding: var(--space-sm);\n border-radius: var(--radius-sm);\n font-size: 0.8125rem;\n}\n\n.szenen-bilder__auftragskennung {\n flex-basis: 100%;\n color: var(--color-text-tertiary);\n font-size: 0.6875rem;\n}\n\n/* \u2500\u2500 C1/C2 \u2014 Galerie und grosse Ansicht \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Das Raster w\xE4chst mit dem Platz: auf 390 px drei bis vier Kacheln je Reihe,\n auf dem Desktop entsprechend mehr. Vorher war jedes Bild eine Zeile aus\n Daumennagel plus vier Metadatenfeldern \u2014 vier Bilder ergaben vier Textzeilen\n und das Protokoll war die Hauptsache. */\n.szenen-bildgalerie {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));\n gap: var(--space-sm);\n min-width: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildgalerie__kachel {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-bildgalerie__kachel:hover,\n.szenen-bildgalerie__kachel:focus-visible {\n border-color: var(--color-accent-teal, var(--color-text-primary));\n}\n\n.szenen-bildgalerie__nummer {\n position: absolute;\n bottom: 0.15rem;\n left: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n/* Die grosse Ansicht liegt \xFCber allem und bringt ihren eigenen Grund mit \u2014\n `position: fixed` bezieht sich im Flow-Canvas auf dessen Rahmen, in React auf\n das Fenster; in beiden F\xE4llen genau das Gew\xFCnschte. */\n.szenen-bildviewer {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: grid;\n grid-template-rows: auto 1fr auto;\n gap: var(--space-sm);\n padding: var(--space-sm);\n /* Deckend, nicht get\xF6nt: Bei 0.92 schimmerte der Laufbereich durch und man\n las Prompttext quer \xFCber dem Bild \u2014 im Browser gemessen. */\n background: #000;\n}\n\n/* Titel, Z\xE4hlung, Schliessen \u2014 drei Spalten, damit ein langer Werktitel die\n Z\xE4hlung nicht in die n\xE4chste Zeile und \xFCber das Bild schiebt. */\n.szenen-bildviewer__kopf {\n display: grid;\n /* Titel nimmt den Rest; Zaehler, eine optionale Bildaktion (P6) und\n Schliessen stehen rechts \u2014 mit und ohne Aktion in einer Zeile. */\n grid-template-columns: minmax(0, 1fr);\n grid-auto-columns: auto;\n grid-auto-flow: column;\n align-items: center;\n gap: var(--space-sm);\n color: var(--color-text-primary);\n}\n\n.szenen-bildviewer__titel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 600;\n}\n\n.szenen-bildviewer__zaehler {\n color: var(--color-text-secondary);\n font-size: 0.8125rem;\n}\n\n.szenen-bildviewer__buehne {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-sm);\n min-height: 0;\n min-width: 0;\n}\n\n/* Der Rahmen nimmt den Platz, der zwischen den Bl\xE4tterkn\xF6pfen \xFCbrig ist \u2014\n `min-width: 0`, damit er auch wirklich schrumpft statt sie hinauszuschieben. */\n.szenen-bildviewer__rahmen {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n min-height: 0;\n height: 100%;\n}\n\n.szenen-bildviewer__bild {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}\n\n.szenen-bildviewer__leer {\n color: var(--color-text-secondary);\n text-align: center;\n}\n\n/* Die Bl\xE4tterkn\xF6pfe sind daumengross und liegen an den R\xE4ndern \u2014 auf einem\n Telefon ist der Rand erreichbar, die Bildmitte nicht. */\n.szenen-bildviewer__blaettern {\n flex: 0 0 auto;\n width: 2.75rem;\n height: 3.5rem;\n font-size: 1.75rem;\n line-height: 1;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-bildviewer__details {\n max-height: 8rem;\n overflow-y: auto;\n color: var(--color-text-secondary);\n}\n\n/* Die Aktionen stehen abgesetzt: Sie sind Angebote, keine Ausk\xFCnfte \u2014 dasselbe\n Muster wie beim Folgelauf und bei der Fehlerrettung. */\n/* D \u2014 die Aktionen stehen abgesetzt und standardm\xE4ssig kompakt: Sie sind\n Angebote, keine Ausk\xFCnfte. Vorher hielten beide Formulare dauerhaft offen und\n machten aus jedem Lauf zwei zus\xE4tzliche Bildschirmseiten. */\n.szenen-bilder__aktion {\n min-width: 0;\n padding: var(--space-sm) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__aktion > summary {\n color: var(--color-text-primary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-bilder__aktion[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bilder__aktion-inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-sm);\n}\n\n.szenen-bilder__aktion h5 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-bilder__aktion ol {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding-left: var(--space-md);\n font-size: 0.8125rem;\n}\n\n/* Regelwerk-UX Schritt 16 \u2014 der ZIP-Sammelimport.\n *\n * \xA78: Der gemeldete Einsatz ist mobil. Deshalb **ein** Seedfeld statt einer\n * gestapelten Eingabe je Bild, und die Zuordnung Bild -> Seed als umbrechende\n * Zeile statt als Tabelle: Eine Tabelle waere auf 390 px abgeschnitten, und\n * abgeschnitten heisst hier, dass der Nutzer die Zuordnung nicht mehr pruefen\n * kann \u2014 genau die Pruefung, wegen der die Vorschau existiert. */\n.szenen-bilder__zip {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-bilder__zipkopf {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n.szenen-bilder__zipvorlagen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin: 0;\n}\n\n/* Eine laengere Liste bleibt scrollbar, statt die Sektion und damit den\n * Import-Knopf aus dem Blick zu schieben (\xA78, letzter Punkt). */\n.szenen-bilder__zipliste {\n max-height: 16rem;\n overflow-y: auto;\n}\n\n.szenen-bilder__zipliste > li {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-bilder__zipliste > li > span:first-child {\n overflow-wrap: anywhere;\n}\n\n.szenen-bilder__zipliste > li > span:last-child {\n color: var(--color-text-secondary);\n white-space: nowrap;\n}\n\n/* ==========================================================================\n STUFE 6.10 \u2014 ELEMENTEDITOR UND VERSIONSNAVIGATION\n ========================================================================== */\n\n/* \xA74.2 \u2014 vier Sachverhalte, vier Marken. Die Marken stehen in einer eigenen\n * Spalte, damit ANGEZEIGT + BEVORZUGT nebeneinander lesbar bleiben, statt sich\n * durch den Text zu schieben. */\n.szenen-detail__heads li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-version__titel {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n min-width: 0;\n margin-right: auto;\n}\n\n/* V17 \u2014 Kennungen bleiben vollst\xE4ndig sichtbar, aber optisch sekund\xE4r. */\n.szenen-version__id,\n.szenen-ref__id,\n.szenen-detail__field-key {\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-version__marken {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-version__marken > span {\n padding: 0.1rem 0.5rem;\n color: var(--color-text-primary);\n background: rgba(45, 212, 191, 0.12);\n border: 1px solid rgba(45, 212, 191, 0.35);\n border-radius: var(--radius-full);\n font-size: 0.7rem;\n font-weight: 800;\n letter-spacing: 0.08em;\n}\n\n.szenen-version--angezeigt {\n border-color: var(--color-accent-teal, #2dd4bf) !important;\n}\n\n/* V9 \u2014 der Basiswechsel ist eine Entscheidung, keine Nebenwirkung. */\n.szenen-detail__confirm {\n display: grid;\n gap: var(--space-sm);\n margin: var(--space-md) 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-accent-amber, #f59e0b);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__confirm p {\n margin: 0;\n}\n\n/* Untergruppen von Objektfeldern (`prompt_render_settings`, `overrides`,\n `blender_render_settings`) \u2014 seit A1/A2 auf- und zuklappbar. Eine optionale\n Gruppe startet zu: Blender und `overrides` f\xFCllten auf einem 390-px-Display\n sonst mehrere Bildschirmseiten, obwohl die meisten Shots sie nie anfassen. */\n.szenen-detail__group {\n min-width: 0;\n margin: var(--space-md) 0;\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__group > summary {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-detail__group[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n/* A2 \u2014 dass eine zugeklappte Gruppe schon Werte tr\xE4gt, muss man sehen, ohne\n sie zu \xF6ffnen. Sonst \xFCbersieht man eine gesetzte Blender-Ausgabe genau so\n lange, bis sie im Ergebnis auftaucht. */\n.szenen-detail__group-status {\n padding: 0.05rem 0.4rem;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--color-text-tertiary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__group[data-konfiguriert="ja"] > summary .szenen-detail__group-status {\n color: var(--color-text-primary);\n border-color: var(--color-accent-teal, var(--color-border));\n}\n\n.szenen-detail__group-inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-sm);\n}\n\n/* A3 \u2014 die Kernaussage steht am Feld, die Begr\xFCndung dahinter. Nicht als\n Tooltip: Auf einem Telefon gibt es kein Hover, und was dort unerreichbar ist,\n ist gestrichen \u2014 nur ohne dass es jemand entschieden h\xE4tte. */\n.szenen-detail__warum > summary {\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.szenen-detail__warum > small {\n display: block;\n padding-top: var(--space-xs);\n color: var(--color-text-tertiary);\n}\n\n.szenen-detail__fieldrow {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n margin-bottom: var(--space-md);\n}\n\n/* A4 \u2014 der technische Feldname bleibt lesbar, tritt aber hinter das fachliche\n Label zur\xFCck. */\n.szenen-detail__field-label {\n color: var(--color-text-primary);\n}\n\n.szenen-detail__field {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-detail__field > span {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n}\n\n/* Mehrfachauswahl und Listeneditoren. */\n.szenen-feld__mehrfach,\n.szenen-feld__liste,\n.szenen-feld__reflist,\n.szenen-feld__ref,\n.szenen-feld__zielmodell,\n.szenen-bilder__modellwahl,\n.szenen-feld__kamera {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n/* \u201ENeues Modell hinzufuegen" im Importdialog \u2014 dieselben Abstaende wie jedes\n andere Formular dieser Ansicht, damit es kein Fremdkoerper wird. */\n.szenen-feld__zielmodell-neu {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n padding: var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-feld__zielmodell-neu-aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-feld__mehrfach > label,\n.szenen-feld__null {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n.szenen-feld__liste-zeile {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-feld__reflist ol {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-feld__reflist li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n padding: var(--space-xs) var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* \xA76.1 \u2014 Titel und Typ zuerst, Kennungen daneben. */\n.szenen-ref__anzeige {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-ref__typ {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-ref__warn {\n padding: 0.1rem 0.5rem;\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-radius: var(--radius-full);\n font-size: 0.72rem;\n font-weight: 700;\n}\n\n/* \xA76.5 \u2014 abgeleitete Angaben, ausdr\xFCcklich nur Anzeige. */\n.szenen-detail__derived {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__derived dl {\n display: grid;\n grid-template-columns: minmax(10rem, auto) 1fr;\n gap: var(--space-xs) var(--space-sm);\n margin: 0;\n}\n\n.szenen-detail__derived dt {\n color: var(--color-text-secondary);\n}\n\n.szenen-detail__derived dd {\n margin: 0;\n}\n\n.szenen-feld__abgeleitet {\n margin: 0;\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n}\n\n/* Bereich `Prompts` \u2014 die herkunftsuebergreifende Sicht (P1-A).\n *\n * Die Eintraege selbst rendert `RundenEintrag` und tragen damit die\n * `szenen-runs__*`-Regeln. Hier stehen nur Rahmen und Kennzeichen; eine zweite\n * Laufdarstellung gibt es nicht, also braucht sie auch kein zweites Aussehen. */\n.szenen-prompts__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-prompts__heading {\n margin: 0;\n font-size: 1.05rem;\n margin-right: auto;\n}\n\n.szenen-view__fokus {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n}\n\n.szenen-prompts__fokus {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-accent, #0d9488);\n border-radius: var(--radius-sm, 4px);\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-prompts__hinweis {\n font-style: italic;\n}\n\n.szenen-prompts__ausgeblendet {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n Kette `szenen-design`, P8 \u2014 der Bereich `Prompts` als Bildraster\n ========================================================================== */\n\n/* Herkunfts-Chips: eine Zeile, die in sich scrollt \u2014 nie die Seite. */\n.szenen-prompts__chips {\n display: flex;\n flex-wrap: nowrap;\n gap: 0.375rem;\n min-width: 0;\n padding-bottom: 0.15rem;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n\n.szenen-view .szenen-prompts__chip {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.8rem;\n white-space: nowrap;\n border-radius: var(--radius-full);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-prompts__chip[aria-pressed="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-prompts__zeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.375rem;\n min-width: 0;\n}\n\n.szenen-prompts__anzahl {\n flex: 1 1 8rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-prompts__umschalter {\n min-height: 2rem;\n padding: 0 0.65rem;\n font-size: 0.75rem;\n}\n\n.szenen-prompts__raster-bereich {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n/* Der neueste Lauf \u2014 gross, mit Promptzeile und Kopierknopf. */\n.szenen-prompts__neuester {\n min-width: 0;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-prompts__oeffnen {\n display: block;\n width: 100%;\n padding: 0;\n color: var(--color-text-primary);\n text-align: left;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-prompts__bild {\n position: relative;\n display: block;\n height: 17.5rem;\n overflow: hidden;\n}\n\n.szenen-prompts__neuester .szenen-galerie__status {\n top: 0.75rem;\n left: 0.75rem;\n padding: 0.35rem 0.5rem;\n background: rgba(0, 0, 0, 0.55);\n border-radius: var(--radius-full);\n}\n\n.szenen-prompts__neuester .szenen-galerie__bildzahl {\n top: 0.75rem;\n right: 0.75rem;\n}\n\n.szenen-prompts__promptzeile {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.6rem 0.5rem 0.6rem 0.9rem;\n}\n\n.szenen-prompts__prompt {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-view .szenen-kopieren--symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n min-height: 2.75rem;\n padding: 0;\n color: var(--color-text-primary);\n border-radius: var(--radius-lg);\n}\n\n.szenen-prompts__promptzeile .szenen-lauf__kopieren {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.4rem;\n}\n\n/* Gruppe aufeinanderfolgender Laeufe derselben Szene. */\n.szenen-prompts__gruppe {\n display: grid;\n gap: 0.6rem;\n min-width: 0;\n}\n\n.szenen-prompts__gruppenkopf {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-prompts__gruppenkopf h4 {\n min-width: 0;\n margin: 0;\n font-size: 1rem;\n font-weight: 650;\n line-height: 1.3;\n overflow-wrap: anywhere;\n}\n\n.szenen-prompts__gruppenkopf span {\n flex: none;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* Zwei Spalten, Kacheln im Format 3:4. */\n.szenen-view .szenen-prompts__raster {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0.625rem;\n min-width: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n@media (min-width: 761px) {\n .szenen-view .szenen-prompts__raster {\n grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));\n }\n}\n\n.szenen-prompts__kachel {\n min-width: 0;\n}\n\n.szenen-view .szenen-prompts__kachel > button {\n position: relative;\n display: block;\n width: 100%;\n min-width: 0;\n aspect-ratio: 3 / 4;\n padding: 0;\n overflow: hidden;\n color: var(--color-text-primary);\n text-align: left;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-prompts__kachel.is-fokus > button,\n.szenen-view .szenen-prompts__neuester.is-fokus {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-prompts__text {\n position: absolute;\n right: 0.75rem;\n bottom: 0.7rem;\n left: 0.75rem;\n display: grid;\n gap: 0.2rem;\n min-width: 0;\n}\n\n.szenen-prompts--mitbild .szenen-prompts__text {\n color: #fff;\n}\n\n.szenen-prompts__titel {\n display: -webkit-box;\n overflow: hidden;\n font-size: 1.25rem;\n font-weight: 700;\n line-height: 1.2;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow-wrap: anywhere;\n}\n\n.szenen-prompts__kachelrunde {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.95rem;\n font-weight: 700;\n}\n\n.szenen-prompts__meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.3rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-prompts--mitbild .szenen-prompts__meta {\n color: rgba(255, 255, 255, 0.82);\n}\n\n.szenen-prompts__statuspunkt {\n display: inline-block;\n flex: none;\n width: 0.5rem;\n height: 0.5rem;\n background: var(--color-success);\n border-radius: 50%;\n}\n\n.szenen-prompts__statuspunkt[data-status="failed"] {\n background: var(--color-danger);\n}\n\n/* Eine Kachel ohne Bild nennt ihren Grund \u2014 oben, damit der Text unten frei bleibt. */\n.szenen-prompts__grund {\n display: grid;\n align-content: start;\n gap: 0.3rem;\n padding-top: 2.25rem;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n line-height: 1.3;\n}\n\n.szenen-prompts__fehlertext {\n display: -webkit-box;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 4;\n overflow-wrap: anywhere;\n}\n\n/* ==========================================================================\n ZIP-MODELLVORSCHLAG (modaler Best\xE4tigungsdialog)\n ========================================================================== */\n\n/* Wie die grosse Bildansicht: eigener Grund, `position: fixed`, damit der\n Dialog im Flow-Canvas und in React gleichermassen \xFCber allem liegt. */\n.szenen-zipmodell {\n position: fixed;\n inset: 0;\n z-index: 1100;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--space-md);\n background: rgba(0, 0, 0, 0.72);\n}\n\n.szenen-zipmodell__karte {\n display: grid;\n gap: var(--space-sm);\n width: min(34rem, 100%);\n max-height: 100%;\n overflow-y: auto;\n padding: var(--space-md);\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-zipmodell__titel {\n margin: 0;\n font-size: 1rem;\n}\n\n.szenen-zipmodell__quelle,\n.szenen-zipmodell__treffer,\n.szenen-zipmodell__vertrauen,\n.szenen-zipmodell__fallback {\n margin: 0;\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__quelle,\n.szenen-zipmodell__vertrauen {\n color: var(--color-text-secondary);\n}\n\n/* Ein schwacher oder mehrdeutiger Treffer muss sich vom sicheren unterscheiden,\n sonst ist die Warnung nur ein weiterer Satz. */\n.szenen-zipmodell__warnung {\n margin: 0;\n padding: var(--space-xs) var(--space-sm);\n color: var(--color-text-primary);\n background: rgba(234, 179, 8, 0.14);\n border-left: 3px solid #eab308;\n border-radius: var(--radius-sm);\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__alternativen {\n display: grid;\n gap: 0.2rem;\n margin: 0;\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__alternativen > label {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-zipmodell__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n/* ==========================================================================\n MEHR LADEN \u2014 der gemeinsame Fuss jeder seitenweise geladenen Liste\n ========================================================================== */\n\n.szenen-mehr-laden {\n display: grid;\n gap: var(--space-xs);\n justify-items: start;\n padding: var(--space-xs) 0;\n}\n\n.szenen-mehr-laden__button {\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-surface);\n color: var(--color-text-primary);\n font-size: 0.85rem;\n cursor: pointer;\n}\n\n.szenen-mehr-laden__button:disabled {\n cursor: progress;\n opacity: 0.6;\n}\n\n.szenen-mehr-laden__fehler {\n margin: 0;\n color: var(--color-danger, #f87171);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n PROMPTKARTE \u2014 Tags, Vorschau und Bildzahl\n (Kette `szenen-prompt-anzeige-bilder-tags`)\n\n Der Zuschnitt ist der der Library-Karte (`.library-item` + der absolut\n gesetzte Bildstreifen in `LibraryTab`): Textteil links, Deckbild rechts am\n Rand ueber die ganze Kartenhoehe, Bildzahl als Plakette darauf. Dieselben\n Werte (7rem Streifenbreite, linke Trennlinie, Plakette unten rechts), nur\n hier statt in Tailwind-Klassen \u2014 die Szenen-Ansicht teilt dieses Stylesheet\n byteweise mit Flow, und Flow hat kein Tailwind.\n ========================================================================== */\n\n.szenen-promptkarte {\n position: relative;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n padding: var(--space-sm);\n}\n\n/* Nur wo ein Bild liegt, wird Platz dafuer freigehalten. Ohne Bild nutzt der\n Textteil die ganze Breite \u2014 keine leere Spalte. */\n.szenen-promptkarte--mitbild .szenen-promptkarte__inhalt {\n padding-right: calc(7rem + var(--space-sm));\n}\n\n.szenen-promptkarte__bild {\n position: absolute;\n top: 0;\n right: 0;\n width: 7rem;\n height: 100%;\n /* Hoechstens so hoch wie breit \u2014 der Streifen bleibt eine Kachel.\n `height: 100%` allein band ihn an die **Kartenhoehe**, und die ist in der\n aufgeklappten Runde die Hoehe des ganzen Prompts: Das Deckbild sprang\n dann als mehrere hundert Pixel hoher, auf Streifenbreite beschnittener\n Balken an den rechten Rand. Geschlossen aendert die Grenze nichts \u2014 dort\n ist die Karte niedriger als 7rem. */\n max-height: 7rem;\n border-left: 1px solid var(--color-border);\n background: #000;\n}\n\n/* Die gemeinsame Kachel bringt `width: 100%` und `aspect-ratio: 1` mit \u2014 hier\n fuellt sie stattdessen den Streifen, genau wie das Library-Deckbild. */\n.szenen-promptkarte__bild .szenen-bildkachel {\n width: 100%;\n height: 100%;\n aspect-ratio: auto;\n}\n\n.szenen-promptkarte__bildzahl {\n position: absolute;\n right: 0.25rem;\n bottom: 0.25rem;\n padding: 0.1rem 0.35rem;\n border-radius: var(--radius-sm);\n background: rgba(0, 0, 0, 0.6);\n color: #fff;\n font-size: 0.62rem;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n/* Ein Kasten je Karte, nicht zwei.\n *\n * `.szenen-view button` (master.css) gibt **jedem** Knopf der Ansicht Rahmen\n * und Hintergrund und schlaegt dabei `.szenen-runs__kopf` (eine Klasse gegen\n * Klasse plus Element). In der Laufhistorie ist das richtig: Dort ist der Kopf\n * der Eintrag. In der Promptkarte ist die Karte der Eintrag \u2014 ein zweiter\n * Kasten darin waere die doppelte Umrandung, die die Library nicht hat.\n * Der Hover braucht eine eigene Zeile, weil die Regel dort spezifischer ist. */\n.szenen-promptkarte .szenen-runs__kopf,\n.szenen-promptkarte .szenen-runs__kopf:hover:not(:disabled) {\n min-height: 0;\n padding: var(--space-xs) 0;\n background: transparent;\n border: none;\n}\n\n/* Dieselbe Karte in der Elementliste.\n *\n * Dort ist der Auswahlknopf die Karte \u2014 er traegt Rahmen, Hintergrund und die\n * Auswahlmarkierung. Der Bildstreifen liegt deshalb **darueber** statt darin:\n * Ein `<button>` nimmt nur Phrasing Content auf, ein Streifen-`div` darin\n * waere ungueltiges Markup. Damit der rechte Kartenrand trotzdem auswaehlbar\n * bleibt, laesst der Streifen Klicks durch. */\n.szenen-elementkarte {\n position: relative;\n}\n\n.szenen-elementkarte--mitbild > button {\n padding-right: calc(7rem + var(--space-sm));\n}\n\n.szenen-elementkarte > .szenen-promptkarte__bild {\n border-radius: 0 var(--radius-sm) var(--radius-sm) 0;\n}\n\n.szenen-promptkarte__bild--durchklickbar {\n pointer-events: none;\n}\n\n/* Null Bilder: die Zahl, keine Flaeche. */\n/* Die Tagliste bricht um. Auf einem Telefon ist das der Unterschied zwischen\n einer kompakten Karte und einer Zeile, die seitlich herauslaeuft. */\n.szenen-tagliste {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n align-items: center;\n margin: 0 0 var(--space-xs);\n padding: 0;\n list-style: none;\n}\n\n.szenen-tag {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.05rem 0.4rem;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-app);\n font-size: 0.72rem;\n line-height: 1.5;\n white-space: nowrap;\n}\n\n/* Herkunft sichtbar, aber ohne zweite Bedeutungsebene: Ein Prompt-Tag steht\n voll, ein reiner Library-Tag zurueckgenommen. Die Karte soll schnell lesbar\n sein, nicht zwei Farbcodes lehren. */\n.szenen-tag[data-herkunft="library"] {\n border-style: dashed;\n opacity: 0.85;\n}\n\n.szenen-tag--rest {\n border-style: none;\n opacity: 0.7;\n}\n\n.szenen-tag__weg {\n border: none;\n background: none;\n padding: 0;\n color: var(--color-text-secondary, inherit);\n font-size: 0.85rem;\n line-height: 1;\n cursor: pointer;\n}\n\n.szenen-tag__weg:disabled {\n cursor: progress;\n opacity: 0.5;\n}\n\n.szenen-taggeber {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-xs);\n margin-bottom: var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-taggeber__zeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n margin: 0;\n}\n\n.szenen-taggeber__label {\n font-size: 0.72rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n opacity: 0.75;\n}\n\n.szenen-taggeber__leer,\n.szenen-taggeber__hinweis {\n font-size: 0.72rem;\n opacity: 0.75;\n}\n\n.szenen-taggeber input[type="text"] {\n flex: 1 1 8rem;\n min-width: 0;\n padding: var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-surface);\n color: var(--color-text-primary);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n BILDAUFTR\xC4GE \u2014 die bestandsweite Arbeitsqueue\n Kette `szenen-bildauftraege-arbeitsqueue`, Schritt 01.\n ========================================================================== */\n\n.szenen-bildauftraege {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-bildauftraege__steuerung,\n.szenen-bildauftraege__filter,\n.szenen-bildauftraege__aktionen,\n.szenen-bildauftraege__nachladen,\n.szenen-bildauftraege__blaettern {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n}\n\n/* Der manuelle Refresh \u2014 Schritt 03 \xA72. Er steht oben und sichtbar, weil er\n die einzige Stelle ist, an der dieser Bereich nachlaedt: Es gibt keinen\n Timer mehr, den er ersetzen koennte. */\n.szenen-bildauftraege__nachladen {\n justify-content: flex-start;\n}\n\n.szenen-bildauftraege__nachladen span {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* Die Blaetterleiste der Bildkontrolle \u2014 Schritt 03 \xA73.1. */\n.szenen-bildauftraege__blaettern {\n margin: 0;\n}\n\n/* \u201EWeitere Bilder" \u2014 seit Schritt 06 eine **Leiste in der Zeile**, kein\n aufklappbares Formular: Modell, Anzahl, Knopf nebeneinander. */\n.szenen-bildauftraege__weitere {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n margin: var(--space-xs) 0 0;\n font-size: 0.85rem;\n}\n\n.szenen-bildauftraege__weitere label {\n color: var(--color-text-secondary);\n}\n\n/* Der Lauf-Zaehler: sichtbar, aber nicht im Weg (Schritt 06). */\n.szenen-bildauftraege__laufzaehler {\n padding: 0.05rem var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm, 4px);\n font-size: 0.8rem;\n font-variant-numeric: tabular-nums;\n}\n\n/* Die Vorschau steht oben und beh\xE4lt ihren Platz, auch solange noch kein Bild\n vorliegt \u2014 sie ist die Kontrollfl\xE4che des zweiten Browserfensters (\xA75). */\n.szenen-bildauftraege__letztes {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-bildauftraege__letztes h3 {\n margin: 0;\n font-size: 0.95rem;\n}\n\n.szenen-bildauftraege__letztes .szenen-bildkachel {\n width: min(100%, 22rem);\n height: auto;\n}\n\n.szenen-bildauftraege__lauf {\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bildauftraege__lauf p {\n margin: 0.1rem 0;\n}\n\n.szenen-bildauftraege__liste {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildauftraege__zeile {\n display: grid;\n gap: 0.25rem;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bildauftraege__kopf,\n.szenen-bildauftraege__prompt {\n margin: 0;\n}\n\n.szenen-bildauftraege__meta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.15rem var(--space-sm);\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-bildauftraege__prompt {\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n/* \u2500\u2500 Kette `szenen-design`, P4: Szene als Studio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Kopf mit Speichern, Hero mit Titelbild und Versions-Pill, die B\xFChne auf\n * einem Punktraster, das Element-Sheet von unten, der Prompt-Start als ein\n * Block, L\xE4ufe als Bildstreifen, Aufklapper unten. Kn\xF6pfe in der B\xFChne und im\n * Sheet setzen die Grundoptik von `.szenen-view button` gezielt zur\xFCck \u2014 daher\n * die zwei Klassen in diesen Selektoren. */\n.szenen-studio {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n.szenen-studio__kopf {\n position: sticky;\n top: 0;\n z-index: 3;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n padding: var(--space-xs) 0;\n background: var(--color-bg-app);\n}\n\n.szenen-studio__kopf > .szenen-detail__ids {\n flex: 1 1 auto;\n margin: 0;\n}\n\n.szenen-studio__ungespeichert {\n color: var(--color-warning);\n font-size: 0.8rem;\n font-weight: 600;\n}\n\n.szenen-view .szenen-studio__speichern {\n min-height: 2.25rem;\n padding: 0 1rem;\n color: var(--color-accent-teal, #2dd4bf);\n background: transparent;\n border-color: var(--color-accent-teal, #2dd4bf);\n border-radius: var(--radius-full);\n font-weight: 650;\n}\n\n.szenen-studio__hero {\n position: relative;\n min-height: 12rem;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-studio__hero--mitbild {\n min-height: 16rem;\n border-color: transparent;\n}\n\n.szenen-studio__titelbild {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-studio__scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.45) 42%, rgba(0, 0, 0, 0) 70%);\n}\n\n.szenen-studio__ohnebild {\n position: absolute;\n inset: 0;\n padding: var(--space-md);\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 16px 16px,\n var(--color-bg-surface);\n}\n\n.szenen-studio__symbole {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n color: var(--color-text-secondary);\n}\n\n.szenen-studio__bildfehler {\n margin: 0 0 var(--space-sm);\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-studio__herotext {\n position: absolute;\n right: var(--space-md);\n bottom: var(--space-md);\n left: var(--space-md);\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-studio__herotext h3 {\n margin: 0;\n font-size: 1.5rem;\n line-height: 1.2;\n overflow-wrap: anywhere;\n}\n\n.szenen-studio__hero--mitbild .szenen-studio__herotext {\n color: #fff;\n}\n\n.szenen-studio__herometa {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-studio__pill {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n color: inherit;\n background: rgba(0, 0, 0, 0.55);\n border: 1px solid rgba(255, 255, 255, 0.25);\n border-radius: var(--radius-full);\n}\n\n.szenen-studio__hero:not(.szenen-studio__hero--mitbild) .szenen-studio__pill {\n background: var(--color-bg-elevated);\n border-color: var(--color-border);\n}\n\n/* Kette `szenen-design`, P6 \u2014 Titelbild: \u22EF-Menue im Hero, Hinweis, Zeile\n unter \u201ETechnisch" und die Aktion im Bildviewer. */\n.szenen-studio__heromenu {\n position: relative;\n display: inline-flex;\n}\n\n.szenen-view .szenen-studio__menuknopf {\n justify-content: center;\n min-width: 2.25rem;\n padding: 0 0.5rem;\n}\n\n.szenen-studio__menu {\n position: absolute;\n top: calc(100% + 0.25rem);\n left: 0;\n z-index: 5;\n display: grid;\n min-width: 12rem;\n padding: var(--space-xs, 0.25rem);\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md, 0.5rem);\n}\n\n.szenen-studio__menu button {\n min-height: 2.25rem;\n padding: 0 0.75rem;\n text-align: left;\n color: inherit;\n background: transparent;\n border: 0;\n}\n\n.szenen-studio__menu button:disabled {\n color: var(--color-text-secondary);\n}\n\n.szenen-studio__titelbildhinweis {\n margin: 0;\n font-size: 0.8rem;\n color: var(--color-warning);\n}\n\n.szenen-studio__hero--mitbild .szenen-studio__titelbildhinweis {\n color: #fde68a;\n}\n\n.szenen-studio__titelbildzeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n padding: var(--space-sm) 0;\n font-size: 0.875rem;\n}\n\n.szenen-studio__titelbildref {\n display: block;\n overflow-wrap: anywhere;\n color: var(--color-text-secondary);\n}\n\n.szenen-view .szenen-bildviewer__aktion {\n min-height: 2.25rem;\n padding: 0 0.75rem;\n}\n\n.szenen-bildviewer__titelbild {\n color: var(--color-accent-teal, #2dd4bf);\n font-size: 0.8125rem;\n}\n\n.szenen-studio__komposition {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-studio__abschnittkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-studio__abschnittkopf h4 {\n margin: 0;\n}\n\n.szenen-studio__umschalter {\n display: inline-flex;\n padding: 3px;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-studio__umschalter button {\n min-height: 2rem;\n padding: 0 0.75rem;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-studio__umschalter button[aria-pressed="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-studio__aufklapper {\n display: grid;\n min-width: 0;\n}\n\n.szenen-studio__aufklapper > details {\n min-width: 0;\n border-top: 1px solid var(--color-border);\n}\n\n.szenen-studio__aufklapper > details:last-child {\n border-bottom: 1px solid var(--color-border);\n}\n\n.szenen-studio__aufklapper > details > summary {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n cursor: pointer;\n}\n\n.szenen-studio__zusammenfassung {\n margin-left: auto;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Die B\xFChne */\n.szenen-buehne {\n position: relative;\n width: 100%;\n aspect-ratio: 358 / 330;\n overflow: hidden;\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 16px 16px,\n var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-buehne--leer {\n display: grid;\n place-items: center;\n aspect-ratio: auto;\n min-height: 8rem;\n color: var(--color-text-secondary);\n}\n\n.szenen-buehne__linien {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n}\n\n.szenen-buehne__linie {\n stroke: var(--color-text-tertiary);\n stroke-width: 1.5;\n}\n\n.szenen-buehne__linie--naehe {\n stroke-width: 1;\n stroke-dasharray: 3 4;\n}\n\n.szenen-buehne__linie--kontakt {\n stroke: var(--color-text-primary);\n stroke-width: 3;\n}\n\n.szenen-buehne__kegel-start {\n stop-color: var(--color-accent-amber, #f2c46d);\n stop-opacity: 0.35;\n}\n\n.szenen-buehne__kegel-ende {\n stop-color: var(--color-accent-amber, #f2c46d);\n stop-opacity: 0;\n}\n\n.szenen-view .szenen-buehne__node {\n position: absolute;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.3rem;\n min-height: 0;\n max-width: 6rem;\n padding: 0;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n transform: translate(-50%, -50%);\n}\n\n.szenen-view .szenen-buehne__node:hover:not(:disabled) {\n background: transparent;\n}\n\n.szenen-buehne__symbol {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-buehne__node--mitte .szenen-buehne__symbol {\n width: 4rem;\n height: 4rem;\n border: 2px solid var(--color-text-primary);\n}\n\n.szenen-buehne__node--light .szenen-buehne__symbol {\n color: var(--color-accent-amber, #f2c46d);\n}\n\n.szenen-buehne__node[aria-pressed="true"] .szenen-buehne__symbol {\n box-shadow: 0 0 0 2px var(--color-accent-blue);\n}\n\n.szenen-buehne__name {\n max-width: 100%;\n padding: 0 0.25rem;\n overflow: hidden;\n background: var(--color-bg-app);\n border-radius: var(--radius-sm);\n font-size: 0.75rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-buehne__node--mitte .szenen-buehne__name {\n font-weight: 650;\n}\n\n.szenen-buehne__legende {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs) var(--space-md);\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-buehne__legende > span {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-buehne__legende-hinweis {\n margin-left: auto;\n}\n\n.szenen-buehne__muster {\n display: inline-block;\n width: 1.1rem;\n border-top: 1px dashed var(--color-text-tertiary);\n}\n\n.szenen-buehne__muster--kontakt {\n border-top: 3px solid var(--color-text-primary);\n}\n\n/* Das Element-Sheet */\n.szenen-sheet {\n position: fixed;\n inset: 0;\n z-index: 50;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n}\n\n.szenen-view .szenen-sheet__hintergrund {\n position: absolute;\n inset: 0;\n padding: 0;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n border-radius: 0;\n cursor: default;\n}\n\n.szenen-sheet__flaeche {\n position: relative;\n display: grid;\n gap: var(--space-md);\n width: 100%;\n max-width: 40rem;\n max-height: 85vh;\n padding: var(--space-sm) var(--space-md) var(--space-md);\n overflow-y: auto;\n box-sizing: border-box;\n background: var(--color-bg-surface);\n border-top: 1px solid var(--color-border);\n border-radius: 1.5rem 1.5rem 0 0;\n}\n\n.szenen-sheet__griff {\n justify-self: center;\n width: 2.5rem;\n height: 4px;\n background: var(--color-border);\n border-radius: 2px;\n}\n\n.szenen-sheet__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-sheet__symbol {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 3.5rem;\n height: 3.5rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-sheet__symbol--light {\n color: var(--color-accent-amber, #f2c46d);\n}\n\n.szenen-sheet__titel {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n}\n\n.szenen-sheet__titel strong {\n font-size: 1.25rem;\n}\n\n.szenen-sheet__titel code {\n overflow: hidden;\n color: var(--color-text-secondary);\n font-family: var(--font-mono);\n font-size: 0.75rem;\n text-overflow: ellipsis;\n}\n\n.szenen-view .szenen-sheet__schliessen {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n margin-left: auto;\n padding: 0;\n border-radius: 50%;\n}\n\n.szenen-sheet__abschnitt {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-sheet__abschnitt h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n font-weight: 500;\n}\n\n.szenen-sheet__leer {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-sheet__beziehungen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-sheet__beziehungen li {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n}\n\n.szenen-sheet__beziehungsart {\n color: var(--color-text-secondary);\n}\n\n.szenen-sheet__bilder {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-sheet__bild {\n position: relative;\n aspect-ratio: 1 / 1;\n overflow: hidden;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-sheet__bild img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-sheet__bildtext {\n display: grid;\n gap: 0.2rem;\n padding: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.65rem;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n.szenen-sheet__bildtext code {\n font-family: var(--font-mono);\n}\n\n.szenen-view .szenen-sheet__fertig {\n min-height: 3rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border: none;\n border-radius: var(--radius-md);\n font-weight: 700;\n}\n\n/* Der Prompt-Start als ein Block */\n.szenen-start {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-start__primaer {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-accent-teal, #2dd4bf);\n border: none;\n border-radius: var(--radius-md);\n font-size: 1.05rem;\n font-weight: 700;\n}\n\n.szenen-start__kosten {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n text-align: center;\n}\n\n.szenen-start__manuell {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-view .szenen-start__zweit {\n min-height: 2.75rem;\n background: transparent;\n}\n\n.szenen-start__erklaerung > summary {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-start__erklaerung[open] .szenen-start__chevron {\n transform: rotate(90deg);\n}\n\n/* L\xE4ufe als Bildstreifen */\n.szenen-streifen {\n display: grid;\n gap: 0.35rem;\n padding: 0 var(--space-sm) var(--space-sm);\n}\n\n.szenen-streifen__bilder {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-streifen__bild {\n position: relative;\n aspect-ratio: 3 / 4;\n overflow: hidden;\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n.szenen-streifen__bild img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-streifen__fehler {\n display: block;\n padding: 0.25rem;\n color: var(--color-text-secondary);\n font-size: 0.65rem;\n}\n\n.szenen-streifen__mehr {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n background: rgba(0, 0, 0, 0.6);\n font-size: 0.95rem;\n font-weight: 700;\n}\n\n.szenen-streifen__anzahl {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n/* \xC4ltere Runden: kompakte Zeile mit \xFCberlappenden Miniaturen. */\n.szenen-streifen--zeile {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-streifen--zeile .szenen-streifen__bilder {\n display: flex;\n gap: 0;\n}\n\n.szenen-streifen--zeile .szenen-streifen__bild {\n width: 2.1rem;\n height: 2.75rem;\n aspect-ratio: auto;\n border: 2px solid var(--color-bg-surface);\n}\n\n.szenen-streifen--zeile .szenen-streifen__bild + .szenen-streifen__bild {\n margin-left: -0.75rem;\n}\n\n.szenen-runs__eintrag--karte {\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n/* Szenenst\xE4nde enthalten mehrere Runden derselben eingefrorenen Szene (#538). */\n.szenen-runs__stand > h5 {\n margin: 0;\n font-size: 1rem;\n}\n\n.szenen-runs__stand-laeufe {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-runs__stand-laeufe > li {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* ==========================================================================\n Kette `szenen-design`, P5 \u2014 der Prompt-Lauf als Ergebnisgalerie\n ========================================================================== */\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-chip,\n.szenen-view .szenen-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n min-height: 1.75rem;\n padding: 0 0.65rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n line-height: 1.2;\n white-space: nowrap;\n}\n\n.szenen-view .szenen-chip--knopf {\n min-height: 2.25rem;\n color: var(--color-text-primary);\n cursor: pointer;\n}\n\n.szenen-chip--library,\n.szenen-view .szenen-chip--library {\n color: var(--color-accent-teal, #2dd4bf);\n border-color: var(--color-accent-teal, #2dd4bf);\n}\n\n/* \u2500\u2500 Navigation der Laufansicht \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf__nav {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n min-width: 0;\n scroll-margin-top: var(--space-md);\n}\n\n.szenen-view .szenen-lauf__zurueck {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n min-height: 2.75rem;\n padding: 0 0.6rem 0 0.25rem;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n}\n\n.szenen-lauf__blaettern {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.2rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-lauf__blaettern button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n min-height: 2.5rem;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n}\n\n/* \u2500\u2500 Kopf: Runde, Status, Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-laufinhalt {\n gap: var(--space-md);\n}\n\n.szenen-lauf__kopf {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-lauf__szene {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-lauf__titelzeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__runde {\n margin: 0;\n color: var(--color-text-primary);\n font-size: 1.6rem;\n font-weight: 700;\n line-height: 1.15;\n}\n\n.szenen-lauf__status {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n min-height: 1.6rem;\n padding: 0 0.6rem;\n border: 1px solid currentColor;\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.szenen-lauf__status::before {\n content: "";\n width: 0.4rem;\n height: 0.4rem;\n border-radius: 50%;\n background: currentColor;\n}\n\n.szenen-lauf__status[data-status="succeeded"] { color: var(--color-success); }\n.szenen-lauf__status[data-status="failed"] { color: var(--color-danger); }\n\n.szenen-lauf__chips {\n display: flex;\n flex-wrap: wrap;\n gap: 0.4rem;\n min-width: 0;\n}\n\n.szenen-lauf__hinweis {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n/* \u2500\u2500 Galerie \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf .szenen-bilder__ausgang {\n padding: 0;\n background: none;\n border: none;\n}\n\n.szenen-lauf {\n gap: var(--space-md);\n margin-top: 0;\n}\n\n.szenen-lauf .szenen-bilder__batch {\n padding: 0;\n background: none;\n border: none;\n}\n\n.szenen-bildgalerie--ergebnis {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n overflow: hidden;\n border-radius: var(--radius-md);\n}\n\n.szenen-bildgalerie--einzeln {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.szenen-bildgalerie--ergebnis .szenen-bildgalerie__kachel {\n border: none;\n border-radius: 0;\n}\n\n.szenen-bildgalerie--einzeln .szenen-bildgalerie__kachel {\n border-radius: var(--radius-md);\n}\n\n.szenen-bildgalerie--ergebnis .szenen-bildkachel {\n aspect-ratio: 3 / 4;\n}\n\n.szenen-bildgalerie__alle-text {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.1rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.65);\n font-size: 0.75rem;\n}\n\n.szenen-bildgalerie__alle-text strong {\n font-size: 1.25rem;\n}\n\n/* P5-Akzeptanz: Eine leere Kachel nennt ihren Grund \u2014 lesbar, nicht nur im\n Tooltip. */\n.szenen-bildkachel__grund {\n display: -webkit-box;\n max-width: 90%;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n line-height: 1.3;\n text-align: center;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n}\n\n/* \u2500\u2500 Karten: Prompt, Tags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf__karte {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-lauf__kartenkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__label {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-lauf__legende {\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-size: 0.72rem;\n}\n\n.szenen-lauf__kopieren {\n display: inline-flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__prompttext {\n margin: 0;\n color: var(--color-text-primary);\n line-height: 1.5;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n/* Drei Zeilen Vorschau \u2014 der volle Text bleibt im Dokument (Kopieren,\n Markieren), gek\xFCrzt wird nur die Darstellung. */\n.szenen-lauf__prompttext--zu {\n display: -webkit-box;\n overflow: hidden;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n}\n\n.szenen-view .szenen-lauf__ganz {\n justify-self: start;\n min-height: 2.25rem;\n padding: 0;\n color: var(--color-accent-teal, var(--color-text-primary));\n background: transparent;\n border: none;\n}\n\n.szenen-lauf__negativ {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-lauf__negativ[hidden] {\n display: none;\n}\n\n.szenen-lauf__negativ p {\n margin: 0;\n color: var(--color-text-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.szenen-lauf__karte .szenen-taggeber {\n margin: 0;\n}\n\n.szenen-tagliste .szenen-tag__neu {\n min-height: 2rem;\n}\n\n/* \u2500\u2500 \u201ENeue Bilder" (Serverauftrag des Hosts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-neuebilder {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg, var(--radius-md));\n}\n\n.szenen-neuebilder__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-neuebilder__kopf h4 {\n margin: 0;\n color: var(--color-text-primary);\n font-size: 1.05rem;\n}\n\n.szenen-neuebilder__symbol {\n color: var(--color-accent-teal, #2dd4bf);\n}\n\n.szenen-neuebilder__weg {\n margin-left: auto;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-neuebilder__felder {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--space-sm);\n}\n\n.szenen-wahlfeld {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n padding: 0.4rem 0.6rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-wahlfeld__label {\n color: var(--color-text-secondary);\n font-size: 0.68rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n.szenen-view .szenen-wahlfeld select {\n min-height: 1.75rem;\n padding: 0;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n font-weight: 600;\n}\n\n.szenen-umschalter {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n padding: 3px;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-view .szenen-umschalter button {\n min-height: 2.5rem;\n background: transparent;\n border: none;\n}\n\n.szenen-view .szenen-umschalter button[aria-pressed="true"] {\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n font-weight: 600;\n}\n\n.szenen-view .szenen-neuebilder__start {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-sm);\n min-height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border: none;\n border-radius: var(--radius-md);\n font-size: 1rem;\n font-weight: 700;\n}\n\n.szenen-view .szenen-neuebilder__start:hover:not(:disabled) {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n opacity: 0.9;\n}\n\n.szenen-neuebilder__laedt,\n.szenen-neuebilder__fehler {\n margin: 0;\n font-size: 0.85rem;\n}\n\n.szenen-neuebilder__laedt { color: var(--color-text-secondary); }\n\n/* Referenzbild eines Laufs (#569-Folge): eigener Bereich \xFCber den Ergebnissen. */\n.szenen-bilder__referenz {\n display: flex;\n gap: var(--space-md);\n align-items: center;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent-blue);\n border-radius: var(--radius-md);\n}\n\n.szenen-bilder__referenzbild {\n flex: none;\n width: 9rem;\n}\n\n.szenen-bilder__referenzbild img {\n display: block;\n width: 100%;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__referenzleer {\n display: grid;\n place-items: center;\n aspect-ratio: 4 / 3;\n color: var(--color-text-secondary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n font-size: 0.8rem;\n}\n\n.szenen-bilder__referenztext {\n display: grid;\n gap: 0.2rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.82rem;\n}\n\n.szenen-bilder__referenztext strong {\n color: var(--color-text-primary);\n}\n\n/* Referenzbild und Prompt am einzelnen Bildauftrag. */\n.szenen-zeitleiste__referenz {\n display: flex;\n gap: var(--space-sm);\n align-items: center;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-zeitleiste__referenz img,\n.szenen-zeitleiste__referenz-leer {\n display: block;\n width: 4.5rem;\n aspect-ratio: 4 / 3;\n object-fit: cover;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-zeitleiste__prompt {\n white-space: pre-wrap;\n user-select: text;\n}\n\n/* Das mitgegebene Kamera-Preview (#569-Folge) \u2014 sichtbar, bevor bestellt wird. */\n.szenen-neuebilder__referenz {\n margin: 0;\n padding: 0.35rem 0.6rem;\n color: var(--color-text-primary);\n background: var(--color-accent-blue-dim);\n border-left: 2px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n font-size: 0.82rem;\n}\n.szenen-neuebilder__fehler { color: var(--color-danger); }\n\n.szenen-neuebilder__warnung > summary {\n display: flex;\n align-items: flex-start;\n gap: var(--space-sm);\n color: var(--color-warning);\n font-size: 0.85rem;\n line-height: 1.45;\n cursor: pointer;\n list-style: none;\n}\n\n.szenen-neuebilder__warnung > summary::-webkit-details-marker { display: none; }\n\n.szenen-neuebilder__warnung > p,\n.szenen-neuebilder__zuordnung ul {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n line-height: 1.5;\n}\n\n.szenen-neuebilder__zuordnung > summary {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-neuebilder__zuordnung ul {\n padding-left: 1.1rem;\n}\n\n/* \u2500\u2500 Aufklapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-aufklapper {\n display: grid;\n min-width: 0;\n border-bottom: 1px solid var(--color-border);\n}\n\n.szenen-aufklapper__eintrag,\n.szenen-aufklapper .szenen-bilder__aktion {\n min-width: 0;\n padding: 0;\n border: none;\n border-top: 1px solid var(--color-border);\n border-radius: 0;\n}\n\n.szenen-aufklapper__eintrag > summary,\n.szenen-aufklapper .szenen-bilder__aktion > summary {\n list-style: none;\n cursor: pointer;\n}\n\n.szenen-aufklapper__eintrag > summary::-webkit-details-marker { display: none; }\n\n.szenen-aufklapper .szenen-bilder__aktion[open] > summary {\n margin-bottom: 0;\n}\n\n.szenen-aufklapper__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n padding: 0 var(--space-xs);\n color: var(--color-text-primary);\n font-weight: 400;\n}\n\n.szenen-aufklapper__pfeil {\n flex: none;\n transition: transform 0.15s ease;\n}\n\ndetails[open] > summary .szenen-aufklapper__pfeil {\n transform: rotate(90deg);\n}\n\n.szenen-aufklapper__titel {\n min-width: 0;\n}\n\n.szenen-aufklapper__meta {\n margin-left: auto;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-aufklapper__inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: 0 var(--space-xs) var(--space-md) 2rem;\n}\n\n@media (max-width: 760px) {\n .szenen-aufklapper__inhalt {\n padding-left: var(--space-xs);\n }\n}\n\n.szenen-aufklapper__inhalt > p {\n margin: 0;\n}\n\n/* \u2500\u2500 Zeitleiste der Bildauftr\xE4ge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-zeitleiste {\n display: grid;\n gap: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-zeitleiste__schritt {\n position: relative;\n display: flex;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-md);\n}\n\n/* Die Linie zur n\xE4chsten Zeile. */\n.szenen-zeitleiste__schritt:not(:last-child)::before {\n content: "";\n position: absolute;\n top: 2.1rem;\n bottom: 0;\n left: calc(1rem - 1px);\n width: 2px;\n background: var(--color-border);\n}\n\n.szenen-zeitleiste__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n border: 1px solid var(--color-border);\n border-radius: 50%;\n background: var(--color-bg-elevated);\n color: var(--color-text-secondary);\n font-weight: 700;\n}\n\n.szenen-zeitleiste__symbol[data-zustand="fertig"] {\n color: var(--color-success);\n border-color: var(--color-success);\n background: var(--color-accent-green-dim, var(--color-bg-elevated));\n}\n\n.szenen-zeitleiste__symbol[data-zustand="fehlgeschlagen"] {\n color: var(--color-danger);\n border-color: var(--color-danger);\n background: var(--color-accent-red-dim, var(--color-bg-elevated));\n}\n\n.szenen-zeitleiste__symbol[data-zustand="teilweise"] {\n color: var(--color-warning);\n border-color: var(--color-warning);\n}\n\n.szenen-zeitleiste__inhalt {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n padding-top: 0.3rem;\n}\n\n.szenen-zeitleiste__titel {\n color: var(--color-text-primary);\n font-size: 0.9rem;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__ergebnis,\n.szenen-zeitleiste__zusatz {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__ergebnis[data-zustand="fehlgeschlagen"] { color: var(--color-danger); }\n.szenen-zeitleiste__ergebnis[data-zustand="teilweise"] { color: var(--color-warning); }\n\n.szenen-zeitleiste__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin-top: var(--space-xs);\n}\n\n.szenen-zeitleiste__meldung > summary {\n min-height: 2rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n line-height: 2rem;\n cursor: pointer;\n}\n\n.szenen-zeitleiste__meldung p {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__meldung code {\n display: block;\n margin-top: var(--space-xs);\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-family: var(--font-mono);\n font-size: 0.72rem;\n overflow-wrap: anywhere;\n}\n\n/* \u2500\u2500 Annahmen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-annahmen {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-annahmen__zeile {\n display: flex;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-annahmen__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: 50%;\n}\n\n.szenen-annahmen__text {\n display: grid;\n gap: 0.1rem;\n min-width: 0;\n font-size: 0.85rem;\n line-height: 1.45;\n overflow-wrap: anywhere;\n}\n\n.szenen-annahmen__art {\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n.szenen-annahmen__text details > summary,\n.szenen-lauf__erlaeuterung > summary {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-annahmen__text details p,\n.szenen-lauf__erlaeuterung p {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n line-height: 1.5;\n white-space: pre-wrap;\n}\n\n.szenen-lauf__handeingabe h5 {\n margin: 0 0 var(--space-xs);\n}\n\n.szenen-lauf__handeingabe p {\n margin: 0;\n font-size: 0.85rem;\n}\n\n/* Kette `szenen-design`, P7 (#533) \u2014 die Szene aus Bausteinen. Felder als\n Karten, Bausteine im Feld als Chips; die Leiste ist das vorhandene\n Bottom-Sheet mit Bildkacheln. Bedient wird durch Antippen, nicht Ziehen. */\n.szenen-bausteinfelder {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n.szenen-bausteinfelder__liste {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bausteinfeld {\n display: grid;\n align-content: start;\n gap: var(--space-xs);\n min-width: 0;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bausteinfeld__kopf {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-bausteinfeld__leer,\n.szenen-bausteinfeld__gesperrt {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-bausteinfeld__refs {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bausteinchip {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-view .szenen-bausteinchip__name {\n min-height: 2.25rem;\n max-width: 100%;\n padding: 0 0.75rem;\n overflow: hidden;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bausteinchip__aktionen {\n display: inline-flex;\n gap: var(--space-xs);\n}\n\n.szenen-view .szenen-bausteinchip__aktionen button {\n min-width: 2.25rem;\n min-height: 2.25rem;\n padding: 0 0.6rem;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-bausteinfeld__plus {\n display: inline-flex;\n align-items: center;\n justify-self: start;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n background: transparent;\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-full);\n}\n\n.szenen-bausteinfelder__weitere {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-bausteinfelder__weitere h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n font-weight: 500;\n}\n\n.szenen-bausteinfelder__weitere ul {\n display: grid;\n gap: 0.25rem;\n margin: 0;\n padding: 0;\n list-style: none;\n font-size: 0.85rem;\n}\n\n.szenen-bausteinfelder__ort {\n color: var(--color-text-secondary);\n}\n\n.szenen-view .szenen-bausteinleiste__suche {\n min-height: 2.75rem;\n width: 100%;\n box-sizing: border-box;\n}\n\n.szenen-bausteinleiste {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-view .szenen-bausteinkachel {\n display: grid;\n gap: 0.25rem;\n width: 100%;\n padding: 0;\n overflow: hidden;\n text-align: left;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-view .szenen-bausteinkachel[aria-pressed="true"] {\n border-color: var(--color-text-primary);\n}\n\n.szenen-view .szenen-bausteinkachel:disabled {\n cursor: default;\n opacity: 0.7;\n}\n\n.szenen-bausteinkachel__name {\n display: flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0 0.4rem;\n overflow: hidden;\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bausteinkachel__status,\n.szenen-bausteinkachel__grund {\n padding: 0 0.4rem 0.4rem;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n@media (min-width: 761px) {\n .szenen-bausteinleiste {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n}\n/* Issue #569: mobile stage controls and exact camera letterbox. */\n/* 3D-B\xFChne (#569): Ansicht zuerst, Werte als Karten darunter. */\n.szenen-3d {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-3d__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-3d__kopf h4 {\n margin: 0 auto 0 0;\n}\n\n/* Als Ansicht \u201E3D\u201C der Komposition: kein zweiter Rahmen im Abschnitt. */\n.szenen-3d--eingebettet {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-3d__kopf {\n flex-wrap: wrap;\n}\n\n.szenen-3d .szenen-3d__aufbau {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-width: 0;\n margin-right: auto;\n}\n\n.szenen-3d .szenen-3d__aufbau select {\n width: auto;\n min-width: 0;\n max-width: 100%;\n}\n\n.szenen-3d__stand {\n min-width: 0;\n margin-right: auto;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-3d__sync {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-3d__sync::before {\n width: 0.5rem;\n height: 0.5rem;\n background: var(--color-success);\n border-radius: var(--radius-full);\n content: "";\n}\n\n.szenen-3d__sync[data-state="speichert"]::before {\n background: var(--color-warning);\n}\n\n.szenen-3d__sync[data-state="ansicht"]::before {\n background: var(--color-accent-blue);\n}\n\n.szenen-3d__meldung,\n.szenen-3d__fehler {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-elevated);\n border-left: 3px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n}\n\n.szenen-3d__fehler {\n border-left-color: var(--color-danger);\n}\n\n.szenen-3d__oeffnen {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-3d label {\n display: grid;\n gap: 0.3rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-3d__leiste {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-3d__katalog {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-3d__katalog > span {\n margin-right: 0.15rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-3d__katalog button,\n.szenen-view .szenen-3d__elemente button {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2rem;\n padding: 0 0.7rem;\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n}\n\n.szenen-3d__katalog i,\n.szenen-3d__elemente i {\n flex: none;\n width: 0.6rem;\n height: 0.6rem;\n border-radius: 2px;\n}\n\n.szenen-view .szenen-3d__elemente button[aria-pressed="true"] {\n color: var(--color-text-primary);\n background: var(--color-bg-surface-hover);\n border-color: var(--color-text-primary);\n}\n\n/* Viewport: feste H\xF6he f\xFCr Drauf- und Seitenansicht; die Kameraansicht wird\n * darin auf das gespeicherte Kameraformat eingepasst (Letterbox). */\n.szenen-3d__viewport {\n position: relative;\n display: grid;\n place-items: center;\n height: clamp(320px, 58vh, 560px);\n overflow: hidden;\n background: #0d0f12;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n container-type: size;\n outline: none;\n}\n\n.szenen-3d__viewport:focus-visible {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-3d__surface {\n position: relative;\n width: 100%;\n height: 100%;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.szenen-3d__viewport[data-view="camera"] {\n background: #050607;\n}\n\n.szenen-3d__viewport[data-view="camera"] .szenen-3d__surface {\n width: min(100cqw, calc(100cqh * var(--seitenverhaeltnis)));\n height: min(100cqh, calc(100cqw / var(--seitenverhaeltnis)));\n}\n\n.szenen-3d__hud {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n color: #d4d4d4;\n font-size: 0.78rem;\n font-variant-numeric: tabular-nums;\n pointer-events: none;\n}\n\n.szenen-3d__hud--werkzeuge {\n top: 0.6rem;\n right: 0.6rem;\n gap: 0.25rem;\n pointer-events: auto;\n}\n\n.szenen-view .szenen-3d__hud--werkzeuge button {\n min-width: 2rem;\n min-height: 2rem;\n padding: 0 0.6rem;\n color: #e5e5e5;\n background: rgba(23, 23, 23, 0.85);\n border-color: rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(4px);\n}\n\n.szenen-3d__hud--kamera {\n top: 0.6rem;\n left: 0.6rem;\n padding: 0.2rem 0.55rem;\n background: rgba(0, 0, 0, 0.65);\n border-radius: var(--radius-full);\n}\n\n.szenen-3d__hud--info {\n bottom: 0.6rem;\n left: 0.6rem;\n max-width: calc(100% - 7rem);\n padding: 0.25rem 0.6rem;\n background: rgba(0, 0, 0, 0.6);\n border-radius: var(--radius-full);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.szenen-3d__hud--info strong {\n color: #ffffff;\n font-weight: 600;\n}\n\n.szenen-3d__hud i {\n font-style: normal;\n font-weight: 700;\n}\n\n.szenen-3d__hud--achsen {\n right: 0.75rem;\n bottom: 0.7rem;\n gap: 0.6rem;\n font-weight: 700;\n}\n\n.szenen-3d__labels {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.szenen-3d__label {\n position: absolute;\n padding: 0.05rem 0.4rem;\n color: #f5f5f5;\n background: rgba(10, 10, 10, 0.72);\n border-left: 2px solid var(--farbe, #9bafbc);\n border-radius: 3px;\n font: 500 0.72rem/1.4 var(--font-sans);\n white-space: nowrap;\n transform: translate(-50%, 6px);\n}\n\n.szenen-3d__label--side {\n transform: translate(-50%, calc(-100% - 6px));\n}\n\n.szenen-3d__label--kamera {\n color: #bfdbfe;\n border-left-color: #60a5fa;\n transform: translate(14px, -50%);\n}\n\n.szenen-3d__label--kamera.is-links {\n transform: translate(calc(-100% - 14px), -50%);\n}\n\n.szenen-3d__label.is-selected {\n color: #000000;\n background: #ffffff;\n}\n\n.szenen-3d__inspektor {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));\n gap: var(--space-sm);\n}\n\n.szenen-3d__karte {\n display: grid;\n align-content: start;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm) var(--space-md) var(--space-md);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-3d__karte h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.72rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.szenen-3d__elemente {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem;\n}\n\n.szenen-3d__werte {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0.4rem;\n margin: 0;\n padding: 0;\n border: none;\n}\n\n.szenen-3d__werte legend {\n margin-bottom: 0.4rem;\n padding: 0;\n color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-3d__werte legend span {\n margin-left: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n font-weight: 400;\n}\n\n.szenen-3d__zeilenkopf {\n grid-column: 1 / -1;\n margin-top: 0.2rem;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-3d__werte > button {\n grid-column: 1 / -1;\n}\n\n.szenen-3d .szenen-3d__feld {\n position: relative;\n display: block;\n}\n\n.szenen-3d__achse {\n position: absolute;\n top: 50%;\n left: 0.55rem;\n font-size: 0.72rem;\n font-weight: 700;\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n.szenen-3d__achse--x { color: #f87171; }\n.szenen-3d__achse--y { color: #4ade80; }\n.szenen-3d__achse--z { color: #60a5fa; }\n\n.szenen-view .szenen-3d__feld input {\n padding-left: 1.6rem;\n font-variant-numeric: tabular-nums;\n}\n\n.szenen-3d__hinweis {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.82rem;\n}\n\n.szenen-3d__abschluss {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-view .szenen-3d__primaer {\n min-height: 2.75rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-view .szenen-3d__primaer:hover:not(:disabled) {\n color: var(--color-bg-app);\n background: var(--color-primary-hover);\n}\n\n.szenen-view .szenen-3d__nebenaktion {\n justify-self: start;\n min-height: 2rem;\n padding: 0;\n background: none;\n border: none;\n font-size: 0.82rem;\n text-decoration: underline;\n}\n\n/* Hinweise passend zum Eingabeger\xE4t; ohne Angabe gilt die Maus-Variante. */\n.szenen-3d__nur-touch {\n display: none;\n}\n\n@media (hover: none) and (pointer: coarse) {\n .szenen-3d__nur-maus {\n display: none;\n }\n\n .szenen-3d__nur-touch {\n display: inline;\n }\n\n /* Fingergerechte Ziele (44 px) f\xFCr Ansichtssteuerung, Katalog und Elemente. */\n .szenen-view .szenen-3d__hud--werkzeuge button,\n .szenen-view .szenen-3d__katalog button,\n .szenen-view .szenen-3d__elemente button,\n .szenen-view .szenen-3d .szenen-studio__umschalter button {\n min-width: 2.75rem;\n min-height: 2.75rem;\n }\n}\n\n@media (max-width: 760px) {\n .szenen-3d {\n gap: var(--space-sm);\n padding: var(--space-sm);\n }\n\n .szenen-3d__leiste {\n display: grid;\n }\n\n .szenen-3d .szenen-studio__umschalter {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n }\n\n /* Katalog als eine Zeile, die in sich scrollt, statt die Ansicht nach unten zu schieben. */\n .szenen-3d__katalog {\n flex-wrap: nowrap;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .szenen-3d__katalog > * {\n flex: none;\n }\n\n .szenen-3d__viewport {\n height: clamp(300px, 62svh, 560px);\n margin: 0 calc(-1 * var(--space-sm));\n border-right: none;\n border-left: none;\n border-radius: 0;\n }\n\n .szenen-3d__hud--info {\n max-width: calc(100% - 1.2rem);\n bottom: 2.4rem;\n }\n\n .szenen-3d__hud--achsen {\n bottom: 0.8rem;\n left: 0.75rem;\n right: auto;\n }\n}\n\n/* One DOM canvas, no nested React renderer. */\n.szenen-3d__canvas { display: block; width: 100%; height: 100%; }\n\n/* Prompt choices before the 3D run; mobile buttons wrap within each category. */\n.szenen-3d__prompt details { margin-block: .65rem; }\n.szenen-3d__prompt summary { cursor: pointer; font-weight: 600; }\n.szenen-3d__prompt fieldset { border: 0; padding: .6rem 0; min-width: 0; }\n.szenen-3d__prompt legend { color: var(--color-text-secondary); font-size: .85rem; }\n.szenen-3d__prompt textarea { min-height: 6rem; width: 100%; box-sizing: border-box; }\n.szenen-3d__referenz { white-space: pre-wrap; overflow-wrap: anywhere; font-size: .9rem; }\n\n.szenen-3d__gemini img { display: block; width: 100%; max-height: 28rem; object-fit: contain; background: #eef0f3; border-radius: .4rem; }\n.szenen-3d__gemini pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 32rem; overflow: auto; font-size: .8rem; }\n.szenen-3d__gemini ul { list-style: none; padding: 0; }\n.szenen-3d__gemini li { margin-block: .6rem; overflow-wrap: anywhere; }\n.szenen-3d__gemini li i { display: inline-block; width: .9rem; height: .9rem; margin-right: .4rem; border-radius: .15rem; }\n';
|
|
64
|
+
var SZENEN_VIEW_STYLES = '/* ==========================================================================\n SZENEN VIEW\n ========================================================================== */\n\n.szenen-view {\n display: grid;\n gap: var(--space-md);\n width: 100%;\n min-width: 0;\n font-family: var(--font-sans);\n padding: var(--space-md);\n}\n\n@media (max-width: 760px) {\n .szenen-view {\n padding: var(--space-sm);\n gap: var(--space-sm);\n }\n}\n\n/* Kette `szenen-design`, P1 \u2014 Bild zuerst, Text auf Abruf. Der Kopf ist nur\n * noch Titel und \u24D8; die Erklaerung klappt darunter auf. */\n.szenen-view__intro {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--space-sm);\n color: var(--color-text-primary);\n}\n\n.szenen-view__titel {\n display: grid;\n gap: 0.1rem;\n min-width: 0;\n}\n\n.szenen-view__intro h2,\n.szenen-view__intro p {\n margin: 0;\n}\n\n.szenen-view__intro h2 {\n font-size: clamp(1.5rem, 3vw, 1.9rem);\n font-weight: 700;\n letter-spacing: -0.01em;\n line-height: 1.15;\n}\n\n.szenen-view__eyebrow {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.szenen-view .szenen-view__info {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n min-height: 2.75rem;\n padding: 0;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-view__info[aria-expanded="true"] {\n color: var(--color-text-primary);\n border-color: var(--color-accent-teal, #2dd4bf);\n}\n\n.szenen-view__intro-text {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n font-size: 0.85rem;\n line-height: 1.4;\n}\n\n.szenen-icon {\n flex: none;\n}\n\n/* Fuer Screenreader sichtbar, fuer das Auge nicht \u2014 Status-Punkte und\n * Node-Symbole tragen ihre Bedeutung als Text. */\n.szenen-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Die Bereiche als Pill-Leiste. Sie scrollt in sich, nie die Seite: `min-width:\n * 0` haelt sie in der Spalte, `overflow-x: auto` macht jeden Bereich\n * erreichbar, auch wenn nicht alle nebeneinander passen. */\n.szenen-view__nav {\n display: flex;\n flex-wrap: nowrap;\n gap: var(--space-xs);\n min-width: 0;\n padding: 0 0 var(--space-xs);\n overflow-x: auto;\n scrollbar-width: thin;\n}\n\n.szenen-view__nav button,\n.szenen-view button {\n min-height: 2.25rem;\n padding: 0.45rem 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-view button:hover:not(:disabled) {\n color: var(--color-text-primary);\n background: var(--color-bg-surface-hover);\n border-color: var(--color-border-hover);\n}\n\n.szenen-view button:focus-visible,\n.szenen-view input:focus-visible,\n.szenen-view select:focus-visible,\n.szenen-view textarea:focus-visible {\n outline: 2px solid var(--color-accent-blue);\n outline-offset: 2px;\n}\n\n.szenen-view button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.szenen-view .szenen-view__nav button {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.25rem;\n padding: 0 0.9rem;\n white-space: nowrap;\n border-radius: var(--radius-full);\n font-size: 0.875rem;\n}\n\n.szenen-view .szenen-view__nav button.is-active,\n.szenen-view .szenen-view__nav button[aria-selected="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-view__area {\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-view__capability-note,\n.szenen-area__lead {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border-left: 3px solid var(--color-accent-purple);\n border-radius: var(--radius-sm);\n}\n\n.szenen-view__host-notes {\n color: var(--color-text-secondary);\n}\n\n.szenen-view__host-notes > summary {\n cursor: pointer;\n font-size: 0.8rem;\n}\n\n/* `box-sizing` steht hier und nicht beim Host: Die React-App bringt in\n * `master.css` einen globalen `* { box-sizing: border-box }` mit, Flow **nicht**\n * \u2014 dort ragte `width: 100%` plus Innenabstand um die Randbreite aus dem\n * Elternelement heraus und erzeugte auf ~390 px einen horizontalen Scroll. Die\n * gemeinsame Ansicht darf sich auf keinen Host-Reset verlassen. */\n.szenen-view input:not([type="checkbox"]),\n.szenen-view select,\n.szenen-view textarea {\n box-sizing: border-box;\n width: 100%;\n min-height: 2.25rem;\n padding: 0.5rem 0.65rem;\n color: var(--color-text-primary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font: inherit;\n}\n\n.szenen-view textarea {\n min-height: 7rem;\n resize: vertical;\n font-family: var(--font-mono);\n font-size: 0.8rem;\n}\n\n.szenen-view label {\n display: grid;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n.szenen-view code,\n.szenen-view pre {\n font-family: var(--font-mono);\n overflow-wrap: anywhere;\n}\n\n.szenen-view h3,\n.szenen-view h4,\n.szenen-view h5 {\n margin-top: 0;\n}\n\n.szenen-view ul,\n.szenen-view ol {\n padding-left: 1.25rem;\n}\n\n.szenen-elements,\n.szenen-detail,\n.szenen-scene,\n.szenen-setup,\n.szenen-erweitert,\n.szenen-prompts,\n.szenen-shot,\n.szenen-media,\n.szenen-runs {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n/* Arbeitsoberflaeche: Liste links, Bearbeitung rechts.\n *\n * Breit stehen beide Spalten nebeneinander \u2014 die Auswahl bleibt sichtbar,\n * waehrend bearbeitet wird. Schmal rendert die Komponente nur eine der beiden;\n * hier steht deshalb keine Regel, die die andere versteckt. */\n@media (min-width: 761px) {\n .szenen-elements {\n grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);\n align-items: start;\n }\n\n .szenen-elements__master,\n .szenen-elements__detail {\n min-width: 0;\n }\n}\n\n.szenen-elements__master,\n.szenen-elements__detail {\n display: grid;\n gap: var(--space-sm);\n align-content: start;\n min-width: 0;\n}\n\n.szenen-elements__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-elements__heading {\n margin: 0;\n font-size: 1.05rem;\n}\n\n.szenen-elements__scope {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-elements__scope > select {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.szenen-elements__new {\n flex: none;\n font-weight: 700;\n}\n\n.szenen-elements__create {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n}\n\n.szenen-elements__create label {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-elements__create-actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n}\n\n.szenen-elements__options > summary {\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n cursor: pointer;\n}\n\n.szenen-elements__back {\n justify-self: start;\n font-weight: 700;\n}\n\n.szenen-elements__empty-detail {\n margin: 0;\n color: var(--color-text-tertiary);\n}\n\n.szenen-elements__filter,\n.szenen-detail__actions,\n.szenen-runs__start,\n.szenen-scene-editor__add,\n.szenen-scene-editor__add-relation {\n display: flex;\n flex-wrap: wrap;\n align-items: end;\n gap: var(--space-sm);\n}\n\n.szenen-elements__filter > label,\n.szenen-runs__start > label,\n.szenen-scene-editor__add > input {\n flex: 1 1 16rem;\n}\n\n.szenen-elements__filter > label:has(input[type="checkbox"]) {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: row;\n align-items: center;\n}\n\n.szenen-elements__filter input[type="checkbox"] {\n width: 1rem;\n height: 1rem;\n accent-color: var(--color-accent-blue);\n}\n\n.szenen-elements__list {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-elements__list > li > button {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs) var(--space-sm);\n width: 100%;\n height: 100%;\n text-align: left;\n}\n\n.szenen-elements__list > li > button > .szenen-elements__title {\n flex: 1 1 100%;\n}\n\n.szenen-elements__list > li > button.is-selected,\n.szenen-elements__list > li > button[aria-current="true"] {\n background: var(--color-accent-blue-dim);\n border-color: var(--color-accent-blue);\n}\n\n.szenen-elements__type {\n color: var(--color-accent-blue);\n font-size: 0.75rem;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.szenen-elements__title {\n color: var(--color-text-primary);\n font-size: 0.95rem;\n}\n\n.szenen-elements__subtype,\n.szenen-elements__retired {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-elements__retired {\n color: var(--color-warning);\n}\n\n.szenen-detail {\n margin-top: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n@media (min-width: 761px) {\n .szenen-detail {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n }\n}\n\n.szenen-detail > header,\n.szenen-detail__heads,\n.szenen-detail__draft,\n.szenen-capability {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n/* .szenen-runs ist ein eigenst\xE4ndiger sichtbarer Bereich, beh\xE4lt Styling auf Desktop */\n@media (min-width: 761px) {\n .szenen-runs {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n }\n}\n\n@media (max-width: 760px) {\n .szenen-runs {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n}\n\n.szenen-detail__ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin-bottom: 0;\n color: var(--color-text-secondary);\n}\n\n.szenen-detail__heads ul,\n.szenen-scene-editor ul,\n.szenen-runs > ol,\n.szenen-capability > ul {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-detail__heads li,\n.szenen-scene-editor li,\n.szenen-runs > ol > li,\n.szenen-capability > ul > li {\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n\n/* Stufe 6.7.2 (D-126) \u2014 Advanced-/Debug-Fl\xE4che f\xFCr die rohe, schema-getriebene\n * Feldliste einer Szene. Gestrichelt wie die anderen \u201EAngebot statt\n * Auskunft"-Bereiche, aber ohne Akzentfarbe: sie ist kein Vorschlag, sondern\n * ein Eskalationsweg. */\n.szenen-detail__technical {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__technical > summary {\n margin-bottom: var(--space-sm);\n color: var(--color-text-secondary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-detail__technical[open] > summary {\n margin-bottom: var(--space-md);\n}\n\n.szenen-detail__field small,\n.szenen-capability small {\n color: var(--color-text-tertiary);\n}\n\n.szenen-detail__preview-errors,\n.szenen-detail__notice--error,\n.szenen-view [role="alert"] {\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-color: var(--color-accent-red);\n}\n\n.szenen-detail__notice {\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__notice--success,\n.szenen-view [data-tone="success"] {\n color: #bbf7d0;\n background: var(--color-accent-green-dim);\n border-color: var(--color-accent-green);\n}\n\n.szenen-scene-editor {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--space-md);\n margin-bottom: 0;\n}\n\n.szenen-scene-editor > section {\n min-width: 0;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n/* \u2500\u2500 Stufe 6.7.2 (D-126): Node-/Relationskarten \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Nodes und Beziehungen sind `<details>` \u2014 dieselbe Interaktionssprache wie\n * \u201ERohantwort (Diagnose)" und \u201EBilder zu diesem Lauf" in RunsPanel.tsx. Kopf\n * (immer sichtbar) tr\xE4gt Inhalt zuerst, Technik zuletzt; Body (nur bei\n * ge\xF6ffneter Karte) tr\xE4gt die Bearbeitungscontrols. Padding wandert von der\n * `<li>` in Kopf/Body, damit die Karte keinen doppelten Rand bekommt. */\n.szenen-scene-editor li {\n padding: 0;\n overflow: hidden;\n}\n\n.szenen-node-karte__kopf,\n.szenen-relation-karte__kopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs) var(--space-sm);\n padding: var(--space-sm);\n cursor: pointer;\n list-style: none;\n}\n\n.szenen-node-karte__kopf::-webkit-details-marker,\n.szenen-relation-karte__kopf::-webkit-details-marker {\n display: none;\n}\n\n.szenen-node-karte__titel {\n flex: 1 1 12rem;\n min-width: 0;\n color: var(--color-text-primary);\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.szenen-node-karte__typ {\n flex: none;\n padding: 0.15rem 0.55rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.72rem;\n white-space: nowrap;\n}\n\n/* node_id klein, monospace, sekund\xE4r \u2014 sichtbar auch bei zugeklappter Karte,\n * aber optisch klar hinter Beschreibung und Typ. */\n.szenen-node-karte__meta {\n flex: 1 1 100%;\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n}\n\n.szenen-node-karte__meta code {\n font-size: inherit;\n}\n\n.szenen-node-karte__body,\n.szenen-relation-karte__body {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm) var(--space-sm) var(--space-sm);\n border-top: 1px solid var(--color-border);\n}\n\n/* \xA74 \u2014 Prim\xE4raktion und destruktive Aktion optisch getrennt: \u201ENode/Beziehung\n * entfernen" bekommt einen eigenen, warnenden Ton statt gleichgewichtig neben\n * der normalen Bearbeitung zu stehen. */\n.szenen-node-karte__entfernen,\n.szenen-relation-karte__entfernen {\n justify-self: start;\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-color: var(--color-accent-red);\n}\n\n.szenen-relation-karte__kopf {\n font-size: 0.9rem;\n}\n\n.szenen-relation-karte__kopf code {\n overflow-wrap: anywhere;\n}\n\n.szenen-relation-karte__pfeil {\n flex: none;\n color: var(--color-text-secondary);\n}\n\n/* Die Composer-\xD6ffner (\u201E+ Node hinzuf\xFCgen", \u201E+ Beziehung hinzuf\xFCgen") sind\n * Angebote, keine Ausk\xFCnfte \u2014 dasselbe gestrichelte Muster wie beim Folgelauf\n * und der Fehlerrettung (\xA73.3/\xA73.5). */\n.szenen-scene-editor__oeffnen {\n width: 100%;\n border-style: dashed;\n}\n\n.szenen-refpicker {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n margin: var(--space-sm) 0;\n padding: var(--space-sm) 0;\n border: none;\n border-radius: 0;\n}\n\n.szenen-refpicker legend {\n padding: 0 var(--space-xs);\n color: var(--color-text-secondary);\n font-weight: 600;\n}\n\n.szenen-capability > ul > li {\n display: grid;\n grid-template-columns: minmax(10rem, 1fr) auto minmax(14rem, 2fr);\n align-items: start;\n gap: var(--space-sm);\n}\n\n.szenen-capability__state {\n padding: 0.1rem 0.5rem;\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.szenen-capability__state--yes {\n color: #bbf7d0;\n background: var(--color-accent-green-dim);\n}\n\n.szenen-capability__state--no {\n color: #fecaca;\n background: var(--color-accent-red-dim);\n}\n\n.szenen-capability__state--unknown {\n color: #fef08a;\n background: rgba(234, 179, 8, 0.2);\n}\n\n.szenen-runs > ol > li {\n display: grid;\n gap: var(--space-sm);\n}\n\n/* B1 \u2014 die geschlossene Runde. Vorher stand die `run_id` als erstes und war\n die einzige Information, die niemand liest; jetzt beantwortet die Kopfzeile\n welche Runde, ob sie durchging, mit welchem Modell und was ungef\xE4hr\n herauskam. */\n.szenen-runs__hinweis {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n}\n\n.szenen-runs__kopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-sm);\n width: 100%;\n padding: var(--space-xs) 0;\n text-align: left;\n color: var(--color-text-secondary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.szenen-runs__marke {\n font-weight: 700;\n color: var(--color-text-primary);\n}\n\n.szenen-runs__status {\n padding: 0.05rem 0.4rem;\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n border-radius: var(--radius-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n}\n\n.szenen-runs__status[data-status="succeeded"] {\n border-color: var(--color-success);\n}\n\n.szenen-runs__status[data-status="failed"] {\n border-color: var(--color-danger);\n}\n\n.szenen-runs__modell {\n font-size: 0.75rem;\n}\n\n/* Der Auszug ist die Inhaltsvorschau der Runde. Er bekommt eine eigene Zeile,\n damit er nicht mit Marke und Modell um dieselbe Zeile ringt. */\n.szenen-runs__auszug {\n flex: 1 1 100%;\n min-width: 0;\n color: var(--color-text-tertiary);\n font-size: 0.8125rem;\n}\n\n/* B2 \u2014 ein Fehler steht ausserhalb der aufklappbaren Fl\xE4che: Wer eine rote\n Runde sieht, soll nicht erst klicken m\xFCssen, um zu erfahren, woran sie\n gescheitert ist. */\n.szenen-runs__fehler {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-sm);\n border-radius: var(--radius-sm);\n}\n\n.szenen-runs__fehler p {\n margin: 0;\n}\n\n.szenen-runs__inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-runs__prompt > h5,\n.szenen-runs__sekundaer > h5 {\n margin: 0 0 var(--space-xs);\n}\n\n/* Im Kopf traegt die Zeile selbst den Abstand \u2014 sonst kaeme er doppelt. */\n.szenen-runs__promptkopf > h5 {\n margin: 0;\n}\n\n/* Ueberschrift und Kopierknopf in einer Zeile. Der Knopf gehoert an den Text,\n den er kopiert \u2014 nicht an den Rand der Runde, wo er neben dem falschen\n Abschnitt stuende. */\n.szenen-runs__promptkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-sm);\n margin: 0 0 var(--space-xs);\n}\n\n/* Ein kompakter Knopf, kein zweiter Titel: Der Prompt ist die Hauptsache des\n Abschnitts, die Aktion daneben darf ihn nicht ueberstimmen. Rahmen und\n Hintergrund kommen aus `.szenen-view button` und bleiben \u2014 dieselbe Optik wie\n jeder andere Knopf der Ansicht; hier wird nur die Groesse zurueckgenommen.\n Zwei Klassen im Selektor, weil `.szenen-view button` sonst spezifischer ist. */\n.szenen-runs__promptkopf .szenen-runs__kopieren {\n min-height: 0;\n padding: 0.1rem 0.45rem;\n font-size: 0.72rem;\n}\n\n/* Regel 11: die Bestaetigung nennt die Zahl, nicht nur \u201EErfolgreich". */\n.szenen-runs__kopiert {\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-size: 0.72rem;\n}\n\n.szenen-runs__prompt > p {\n margin: 0;\n white-space: pre-wrap;\n}\n\n.szenen-runs__prompt--negativ > p,\n.szenen-runs__sekundaer > p {\n margin: 0;\n color: var(--color-text-secondary);\n white-space: pre-wrap;\n}\n\n.szenen-runs__mehr {\n justify-self: start;\n margin-top: var(--space-xs);\n padding: 0;\n color: var(--color-accent-teal, var(--color-text-secondary));\n background: transparent;\n border: none;\n font-size: 0.75rem;\n text-decoration: underline;\n cursor: pointer;\n}\n\n.szenen-runs > ol > li[data-status="succeeded"] {\n border-left: 3px solid var(--color-success);\n}\n\n.szenen-runs > ol > li[data-status="failed"] {\n border-left: 3px solid var(--color-danger);\n}\n\n.szenen-runs details pre {\n max-height: 20rem;\n overflow: auto;\n padding: var(--space-sm);\n white-space: pre-wrap;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border-radius: var(--radius-sm);\n}\n\n.szenen-media > section {\n display: grid;\n gap: var(--space-sm);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-media__lookup,\n.szenen-media__attach {\n display: flex;\n flex-wrap: wrap;\n align-items: end;\n gap: var(--space-sm);\n}\n\n.szenen-media__lookup > label,\n.szenen-media__attach > label:first-child {\n flex: 1 1 18rem;\n}\n\n.szenen-media__list {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-media__list > li {\n display: grid;\n grid-template-columns: minmax(12rem, 1fr) auto auto auto;\n align-items: center;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n@media (max-width: 760px) {\n .szenen-view {\n gap: var(--space-sm);\n }\n\n /* C1 \u2014 auf 390 px bleiben drei Kacheln je Reihe gross genug zum Erkennen\n und klein genug, dass vier Bilder eine Reihe sind und keine Seite. */\n .szenen-bildgalerie {\n grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));\n }\n\n /* Der Viewer bekommt den ganzen Bildschirm; die Bl\xE4tterkn\xF6pfe bleiben am\n Rand, wo der Daumen sie erreicht. */\n .szenen-bildviewer {\n padding: var(--space-xs);\n }\n\n .szenen-bildviewer__blaettern {\n width: 2.25rem;\n height: 4rem;\n }\n\n .szenen-view__nav {\n position: sticky;\n top: 0;\n z-index: 2;\n padding: var(--space-xs) 0;\n background: var(--color-bg-app);\n }\n\n\n .szenen-scene-editor {\n grid-template-columns: 1fr;\n }\n\n .szenen-capability > ul > li {\n grid-template-columns: 1fr;\n }\n\n .szenen-derive,\n .szenen-elements,\n .szenen-scene,\n .szenen-setup,\n .szenen-shot,\n .szenen-media,\n .szenen-runs {\n gap: var(--space-sm);\n }\n\n .szenen-elements__filter {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-sm);\n }\n\n .szenen-elements__filter > label {\n width: 100%;\n min-width: 0;\n flex: none;\n }\n\n .szenen-elements__filter > label:has(input[type="checkbox"]) {\n flex: none;\n grid-column: 1 / -1;\n }\n\n /* Schmal ist die Liste eine Spalte, und die Auswahl fuehrt weiter \u2014 der\n * Eintrag ist deshalb ein Ziel fuer den Finger, keine Kachel. */\n .szenen-elements__list {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .szenen-elements__list > li > button {\n min-height: 2.75rem;\n }\n\n .szenen-elements__back {\n justify-self: stretch;\n min-height: 2.5rem;\n }\n\n .szenen-detail__actions,\n .szenen-runs__start,\n .szenen-scene-editor__add,\n .szenen-scene-editor__add-relation {\n align-items: stretch;\n flex-direction: column;\n }\n\n .szenen-runs__start > *,\n .szenen-scene-editor__add > *,\n .szenen-scene-editor__add-relation > * {\n width: 100%;\n flex: none;\n }\n}\n\n/* \u2500\u2500 Kette `szenen-design`, P2: Szenen-\xDCbersicht als Bildgalerie \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Kacheln wie in der Library: quadratisch, Deckbild, Titel ueber einem\n * Verlauf, Bildzahl als Plakette. Eine Szene ohne Bild zeigt ihre\n * Node-Symbole; ein nicht ladbares Deckbild nennt den Grund. Die Schrift auf\n * dem Bild ist hell auf dunklem Verlauf \u2014 unabhaengig vom Hostthema, weil das\n * Bild es auch ist. */\n.szenen-galerie {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-galerie__kopf > .szenen-elements__heading {\n flex: 1 1 auto;\n margin: 0;\n}\n\n.szenen-galerie__anzahl,\n.szenen-galerie__sortierung {\n color: var(--color-text-secondary);\n font-weight: 400;\n}\n\n.szenen-galerie__sortierung {\n font-size: 0.8rem;\n}\n\n.szenen-galerie__raster {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr));\n gap: 0.625rem;\n min-width: 0;\n}\n\n/* Die Kacheln sind Zellen desselben Rasters wie die Neu-Kachel. */\n.szenen-view .szenen-galerie__liste {\n display: contents;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-galerie__kachel {\n min-width: 0;\n}\n\n.szenen-view .szenen-galerie__kachel > button,\n.szenen-view .szenen-galerie__neu,\n.szenen-view .szenen-galerie__zuletzt {\n position: relative;\n display: block;\n width: 100%;\n min-width: 0;\n padding: 0;\n overflow: hidden;\n color: var(--color-text-primary);\n text-align: left;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-galerie__kachel > button {\n aspect-ratio: 1 / 1;\n}\n\n.szenen-view .szenen-galerie__kachel > button[aria-current="true"],\n.szenen-view .szenen-galerie__zuletzt[aria-current="true"] {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-galerie__bild {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-galerie__scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.4) 40%, rgba(0, 0, 0, 0) 65%);\n}\n\n.szenen-galerie__ohnebild {\n position: absolute;\n inset: 0;\n padding: 0.75rem;\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 14px 14px,\n var(--color-bg-surface);\n}\n\n.szenen-galerie__bildfehler {\n position: absolute;\n inset: 0;\n /* Oben Platz fuer Status-Punkte und Bildzahl, die darueber liegen. */\n padding: 2.25rem 0.75rem 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n font-size: 0.75rem;\n line-height: 1.3;\n}\n\n.szenen-galerie__text {\n position: absolute;\n right: 0.75rem;\n bottom: 0.7rem;\n left: 0.75rem;\n display: grid;\n gap: 0.25rem;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__text,\n.szenen-galerie__zuletzt--mitbild .szenen-galerie__zuletzt-text {\n color: #fff;\n}\n\n.szenen-galerie__titel {\n display: -webkit-box;\n overflow: hidden;\n font-size: 0.875rem;\n font-weight: 650;\n line-height: 1.25;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n overflow-wrap: anywhere;\n}\n\n.szenen-galerie__meta {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__meta,\n.szenen-galerie__zuletzt--mitbild .szenen-galerie__meta {\n color: rgba(255, 255, 255, 0.82);\n}\n\n.szenen-galerie__tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n min-width: 0;\n}\n\n.szenen-galerie__tag {\n max-width: 100%;\n padding: 0.05rem 0.4rem;\n overflow: hidden;\n color: inherit;\n background: var(--color-bg-elevated);\n border-radius: var(--radius-full);\n font-size: 0.68rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-galerie__kachel--mitbild .szenen-galerie__tag {\n background: rgba(0, 0, 0, 0.5);\n}\n\n.szenen-galerie__status {\n position: absolute;\n top: 0.7rem;\n left: 0.7rem;\n display: flex;\n gap: 0.3rem;\n}\n\n.szenen-galerie__punkt {\n width: 0.625rem;\n height: 0.625rem;\n background: var(--color-text-secondary);\n border-radius: 50%;\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.55);\n}\n\n.szenen-galerie__punkt[data-ton="info"] { background: var(--color-accent-blue); }\n.szenen-galerie__punkt[data-ton="ok"] { background: var(--color-success); }\n.szenen-galerie__punkt[data-ton="fertig"] { background: var(--color-warning); }\n/* Unvollstaendig ist ein Ring: Die Form unterscheidet es von \u201Evollstaendig",\n * nicht nur der Farbton (P8). */\n.szenen-galerie__punkt[data-ton="warn"] {\n background: transparent;\n box-shadow: inset 0 0 0 2px var(--color-accent-orange), 0 0 0 2px rgba(0, 0, 0, 0.55);\n}\n\n/* Die Legende der Punkte \u2014 einmal je Ansicht. */\n.szenen-statuslegende {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem 0.85rem;\n margin: 0;\n padding: 0;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n list-style: none;\n}\n\n.szenen-statuslegende__eintrag {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-statuslegende .szenen-galerie__punkt {\n display: inline-block;\n width: 0.5rem;\n height: 0.5rem;\n}\n\n.szenen-galerie__bildzahl {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.15rem 0.5rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.65);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.szenen-galerie__symbole {\n display: flex;\n flex-wrap: wrap;\n gap: 0.3rem;\n}\n\n.szenen-galerie__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 1.875rem;\n height: 1.875rem;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-galerie__symbol[data-node-type="light"] {\n color: var(--color-warning);\n}\n\n.szenen-galerie__symbol--rest {\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n}\n\n.szenen-view .szenen-galerie__neu {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.6rem;\n aspect-ratio: 1 / 1;\n text-align: center;\n background: var(--color-bg-app);\n border: 1.5px dashed var(--color-border-hover, var(--color-border));\n}\n\n.szenen-galerie__neu-plus {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 3.25rem;\n height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-accent-teal, #2dd4bf);\n border-radius: 50%;\n}\n\n.szenen-galerie__neu-titel {\n font-size: 0.95rem;\n font-weight: 600;\n}\n\n.szenen-galerie__neu-text {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__zuletzt-bild {\n position: relative;\n display: block;\n aspect-ratio: 4 / 3;\n max-height: 17rem;\n width: 100%;\n}\n\n.szenen-galerie__chip {\n position: absolute;\n top: 0.75rem;\n left: 0.75rem;\n padding: 0.3rem 0.6rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.6);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n}\n\n.szenen-galerie__zuletzt .szenen-galerie__status {\n right: 0.75rem;\n left: auto;\n top: 1rem;\n}\n\n/* Die Symbole einer Szene ohne Bild stehen unter dem Chip, nicht darauf. */\n.szenen-galerie__zuletzt .szenen-galerie__ohnebild {\n padding-top: 3rem;\n}\n\n.szenen-galerie__zuletzt-text {\n position: absolute;\n right: 1rem;\n bottom: 0.9rem;\n left: 1rem;\n display: grid;\n gap: 0.35rem;\n}\n\n.szenen-galerie__zuletzt-text .szenen-galerie__titel {\n font-size: 1.3rem;\n font-weight: 700;\n line-height: 1.2;\n}\n\n.szenen-galerie__zuletzt-fuss {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n padding: 0.75rem 0.9rem;\n}\n\n.szenen-galerie__oeffnen {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.25rem;\n color: var(--color-accent-teal, #2dd4bf);\n font-size: 0.875rem;\n font-weight: 600;\n}\n\n/* \u2500\u2500 Stufe 6.5: Rekonstruktion \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Bereich zeigt drei Dinge nebeneinander: den Vorschlag, das nicht\n * Ableitbare und die Widerspr\xFCche. Die Diagnosen sind deshalb bewusst nicht\n * kleiner gesetzt als der Vorschlag \u2014 wer sie \xFCbersieht, \xFCbernimmt Geratenes.\n */\n\n.szenen-derive {\n display: grid;\n gap: var(--space-md);\n}\n\n.szenen-form {\n display: grid;\n gap: var(--space-sm);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-field {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-field > span {\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.szenen-error {\n padding: var(--space-sm) var(--space-md);\n color: var(--color-danger);\n background: var(--color-accent-red-dim);\n border: 1px solid var(--color-accent-red);\n border-radius: var(--radius-sm);\n}\n\n.szenen-empty {\n padding: var(--space-md);\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-diagnose {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-warning);\n border-radius: var(--radius-sm);\n}\n\n/* Ein Widerspruch ist der schwerste der drei Befunde: dort steht eine\n * Entscheidung aus, die das System bewusst nicht getroffen hat (D-74). */\n.szenen-diagnose--konflikt {\n border-left-color: var(--color-danger);\n}\n\n.szenen-diagnose > h4 {\n margin: 0 0 var(--space-sm);\n font-size: 0.9375rem;\n}\n\n.szenen-diagnose ul {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding-left: var(--space-md);\n}\n\n.szenen-proposal {\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-proposal > h4 {\n margin: 0 0 var(--space-sm);\n font-family: var(--font-mono);\n font-size: 0.9375rem;\n}\n\n.szenen-proposal__payload {\n max-height: 18rem;\n margin: 0 0 var(--space-sm);\n padding: var(--space-sm);\n overflow: auto;\n /* Ein erzeugter Prompt ist ein einziger langer Satz \u2014 ohne Umbruch\n verschwindet er nach rechts aus dem Bild. JSON-Payloads bringen ihre\n eigenen Zeilenumbrueche mit und leiden nicht darunter. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font-family: var(--font-mono);\n font-size: 0.8125rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-proposal__done {\n margin: var(--space-sm) 0 0;\n color: var(--color-success);\n}\n\n/* Die Belege eines Laufs: Rohantwort und Systemprompt. Zum Lesen und Kopieren,\n nicht zum Bedienen \u2014 deshalb voll markierbar und in Monospace. */\n.szenen-beleg__text {\n width: 100%;\n margin: var(--space-sm) 0 0;\n padding: var(--space-sm);\n font-family: var(--font-mono);\n font-size: 0.8125rem;\n line-height: 1.5;\n white-space: pre;\n background: var(--color-bg-app);\n color: var(--color-text);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n resize: vertical;\n}\n\n/* Der Folgelauf (D-87): abgesetzt, damit er nicht wie Teil des Ergebnisses\n aussieht \u2014 er ist eine Frage, keine Auskunft. */\n.szenen-folgelauf {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-folgelauf > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-run__herkunft {\n margin: 0 0 var(--space-sm);\n font-size: 0.875rem;\n color: var(--color-text-muted, inherit);\n}\n\n/* Widerspricht das Modell, ist das das Wichtigste auf der Seite. */\n.szenen-diagnose--antwort {\n border-left: 3px solid var(--color-accent, var(--color-border));\n}\n\n/* Der Bildw\xE4hler (D-92) \u2014 Browser und Inspector, dem Labs-Tab nachgebildet,\n aber mit dem CSS dieser Ansicht: eine gemeinsame Komponente \xFCber zwei\n Dom\xE4nengrenzen w\xE4re eine Kopplung, die keiner gewollt hat.\n\n Der Review vom 2026-08-22 (R12.1/R12.2) hat den Ma\xDFstab gesetzt: Der Bestand\n ist ein **Browser**, kein Seiteninhalt. Vierzig Werke d\xFCrfen die Szenenseite\n nicht meterlang machen, und zw\xF6lf Varianten eines Werkes keine zw\xF6lf\n Bildschirmseiten. Deshalb steht hier alles unter zwei Regeln \u2014 begrenzte\n Fl\xE4che mit eigenem Scroll, und Kacheln statt Karten. */\n\n/* \u2500\u2500 Ebene 1: der Browser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl {\n /* Dieselbe Begr\xFCndung wie beim Inspector: Als Grid-Element w\xFCrde der\n W\xE4hler sonst so breit wie sein breitester Inhalt. */\n min-width: 0;\n}\n\n.szenen-bildwahl__browser {\n /* Die eigene Scrollfl\xE4che ist der ganze Punkt: Der Bestand w\xE4chst nach\n innen, nicht nach unten. Dieselbe Gr\xF6\xDFenordnung wie `max-h-[300px]` im\n Labs-Browser. */\n max-height: 19rem;\n overflow-y: auto;\n overscroll-behavior: contain;\n margin-top: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__raster {\n display: grid;\n /* Vier Spalten auf schmalen Displays \u2014 der gemeldete Screenshot zeigte eine\n einzige Spalte gro\xDFer Karten. Breiter wird automatisch dichter. */\n grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildwahl__karte {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n overflow: hidden;\n background: var(--color-bg-surface);\n text-align: left;\n cursor: pointer;\n}\n\n/* Das fokussierte Werk ist klar markiert \u2014 sonst wei\xDF niemand, wessen Galerie\n der Inspector unten zeigt. */\n.szenen-bildwahl__karte.is-fokus {\n border-color: var(--color-accent, var(--color-text-primary));\n box-shadow: 0 0 0 2px var(--color-accent, var(--color-text-primary));\n}\n\n/* \u2500\u2500 Die Kachel selbst \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Der Platz steht, bevor das Bild da ist \u2014 sonst springt das Raster, sobald\n die erste Vorschau eintrifft. */\n.szenen-bildkachel {\n display: block;\n width: 100%;\n aspect-ratio: 1;\n overflow: hidden;\n background: var(--color-bg-app);\n}\n\n.szenen-bildkachel img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.szenen-bildkachel__leer {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, var(--color-bg-app), var(--color-bg-surface));\n}\n\n/* R12.3: Eine fehlende Vorschau bleibt kachelgro\xDF. Vorher fiel die Karte auf\n ihren Prompttext zur\xFCck \u2014 und ein Prompt hat im echten Bestand mehrere\n hundert Zeichen. */\n.szenen-bildkachel__zeichen {\n font-size: 0.875rem;\n font-weight: 700;\n color: var(--color-text-secondary);\n opacity: 0.6;\n}\n\n/* Wie viele Varianten das Werk hat \u2014 klein und \xFCberlagernd, nie als\n dominanter Text. */\n.szenen-bildwahl__anzahl {\n position: absolute;\n top: 0.15rem;\n right: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n font-weight: 700;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* Eine Zeile, dann Schluss. Der Prompt eines Werkes ist oft mehrere hundert\n Zeichen lang und w\xE4re als Prim\xE4rdarstellung genau die Textw\xFCste, gegen die\n der Review antritt. */\n.szenen-bildwahl__kacheltitel {\n display: block;\n padding: 0.15rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.3;\n color: var(--color-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2500\u2500 Ebene 2: der Inspector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl__inspector {\n /* Ohne `min-width: 0` gewinnt der Inhalt: Der W\xE4hler ist Element eines\n Grids (`.szenen-form`), und dort ist `min-width: auto` die Vorgabe. Der\n Streifen unten ist rund 1000 px breit \u2014 gemessen am 2026-08-22 im echten\n Browser zog er die Auswahl von 374 px auf 1088 px auf und schob die\n ganze Seite waagerecht heraus, statt selbst zu scrollen. */\n min-width: 0;\n margin-top: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n /* Sichtbar abgesetzt vom Browser: zwei Ebenen, nicht eine lange Liste. */\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent, var(--color-border));\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__inspektorkopf {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bildwahl__werktitel {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--color-text-primary);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bildwahl__zurueck {\n flex: 0 0 auto;\n font-size: 0.6875rem;\n padding: 0.15rem 0.5rem;\n}\n\n/* Der Streifen: waagerecht scrollend, feste kleine Kacheln \u2014 zw\xF6lf Varianten\n bleiben ein \xDCberblick statt zw\xF6lf Bildschirmseiten. */\n.szenen-bildwahl__streifen {\n /* Die Breite kommt vom Elter, nie vom Inhalt \u2014 sonst scrollt hier nichts. */\n max-width: 100%;\n display: flex;\n gap: var(--space-sm);\n margin: 0;\n padding: 0 0 0.25rem;\n list-style: none;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n}\n\n.szenen-bildwahl__streifen > li {\n flex: 0 0 auto;\n width: 5rem;\n}\n\n.szenen-bildwahl__variante {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n overflow: hidden;\n background: var(--color-bg-app);\n cursor: pointer;\n}\n\n.szenen-bildwahl__variante.is-gewaehlt {\n border-color: var(--color-accent, var(--color-text-primary));\n box-shadow: 0 0 0 2px var(--color-accent, var(--color-text-primary));\n}\n\n.szenen-bildwahl__nummer {\n position: absolute;\n bottom: 0.15rem;\n left: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n/* \u2500\u2500 Das Gew\xE4hlte \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-bildwahl__gewaehlt {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: var(--space-sm) 0 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildwahl__gewaehlt li {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.8125rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n max-width: 100%;\n}\n\n/* Das gew\xE4hlte Bild wird best\xE4tigt, nicht nur benannt: eine kleine Vorschau\n neben dem Titel. */\n.szenen-bildwahl__gewaehlt .szenen-bildkachel {\n width: 2.25rem;\n flex: 0 0 auto;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bildwahl__gewaehlt .szenen-bildwahl__kacheltitel {\n min-width: 0;\n max-width: 12rem;\n font-size: 0.75rem;\n}\n\n.szenen-beleg__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n margin-top: var(--space-sm);\n}\n\n.szenen-diagnose > details + details {\n margin-top: var(--space-sm);\n}\n\n.szenen-diagnose > details > summary {\n cursor: pointer;\n font-weight: 600;\n}\n\n/* \u2500\u2500 Die Fehlerrettung (Stufe 6.6, A5) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Sie steht im Fehlerblock und muss trotzdem als Werkzeug lesbar sein, nicht\n * als weitere Fehlermeldung. Deshalb abgesetzt wie der Folgelauf \u2014 und aus\n * demselben Grund: Beides sind Angebote, keine Ausk\xFCnfte.\n *\n * Der wichtigste optische Punkt ist die Trennung von Original und\n * Arbeitskopie. Das Original bekommt den ruhigen, \u201Efesten" Hintergrund der\n * Belege; die Kopie sieht aus wie ein normales Eingabefeld, weil sie eines\n * ist. */\n.szenen-rettung {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-rettung > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-rettung textarea[readonly] {\n background: var(--color-bg-surface);\n color: var(--color-text-secondary);\n font-family: var(--font-mono, monospace);\n font-size: 0.8125rem;\n}\n\n.szenen-rettung textarea:not([readonly]) {\n font-family: var(--font-mono, monospace);\n font-size: 0.8125rem;\n}\n\n.szenen-rettung__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: var(--space-sm) 0;\n}\n\n/* Ein Befund tr\xE4gt Code, Bezug und Meldung. Der Code steht klein und\n * monospaced davor: Er ist die Kennung, nicht die Aussage. */\n.szenen-diagnose__liste {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding-left: var(--space-md);\n}\n\n.szenen-diagnose__liste code {\n font-size: 0.8125rem;\n}\n\n.szenen-diagnose__liste > li[data-severity=\'warning\'] {\n color: var(--color-text-secondary);\n}\n\n/* \u2500\u2500 Die Draft-Kette (Stufe 6.6, C4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Hauptweg. Er steht nach den Einzel\xFCbernahmen und muss als das erkennbar\n * sein, was er ist: nicht eine weitere Option, sondern der k\xFCrzere Weg zum\n * selben Ziel. Deshalb durchgezogener Rahmen statt gestricheltem \u2014 er ist\n * Angebot **und** Empfehlung. */\n.szenen-kette {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent, var(--color-border));\n border-radius: var(--radius-sm);\n}\n\n.szenen-kette > h4 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-kette ul {\n display: grid;\n gap: var(--space-xs);\n margin: 0 0 var(--space-sm);\n padding-left: var(--space-md);\n}\n\n.szenen-kette code {\n font-size: 0.8125rem;\n}\n\n/* Ein Hinweis, der eine Bedingung erklaert \u2014 nicht rot, weil er kein Fehler\n ist, aber abgesetzt, weil er eine Folge hat. */\n.szenen-detail__hint {\n margin: var(--space-sm) 0 0;\n padding: var(--space-sm);\n font-size: 0.875rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border-left: 3px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* \u2500\u2500 Stufe 6.7: Bilder am Prompt-Lauf (H0/H1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Der Bereich tr\xE4gt zwei Dinge, die man nie verwechseln darf: den **Eingang**\n * (woraus der Prompt entstand) und den **Ausgang** (was daraus wurde). Sie\n * bekommen deshalb verschiedene Akzentkanten statt nur verschiedener\n * \xDCberschriften \u2014 wer schnell liest, sieht die Trennung, bevor er sie liest.\n */\n.szenen-bilder {\n display: grid;\n gap: var(--space-md);\n margin-top: var(--space-sm);\n}\n\n.szenen-bilder__eingang,\n.szenen-bilder__ausgang {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__eingang {\n border-left: 3px solid var(--color-accent-purple, var(--color-border));\n}\n\n.szenen-bilder__ausgang {\n border-left: 3px solid var(--color-accent-teal, var(--color-border));\n}\n\n.szenen-bilder h5 {\n margin: 0;\n}\n\n.szenen-bilder__ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n margin: 0;\n align-items: baseline;\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.szenen-bilder__eingangsliste,\n.szenen-bilder__batchliste,\n.szenen-bilder__auftraege {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bilder__eingangsliste > li,\n.szenen-bilder__batchliste > li,\n.szenen-bilder__auftraege > li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font-size: 0.8125rem;\n}\n\n/* Ein unterbrochener Auftrag ist der Fall, f\xFCr den der Auftragssatz existiert.\n Er wird deshalb markiert \u2014 nicht rot, denn er ist kein Fehler, sondern eine\n offene Entscheidung. */\n.szenen-bilder__auftraege > li[data-status="started"] {\n border-left: 3px solid var(--color-warning);\n}\n\n.szenen-bilder__auftraege > li[data-status="succeeded"] {\n border-left: 3px solid var(--color-success);\n}\n\n.szenen-bilder__auftraege > li[data-status="partial"] {\n border-left: 3px solid var(--color-accent-blue, var(--color-border));\n}\n\n.szenen-bilder__auftraege > li[data-status="failed"] {\n border-left: 3px solid var(--color-danger);\n}\n\n/* Das Eingangsbild benutzt seit C3 dieselbe Kachel wie W\xE4hler und Galerie.\n Sie ist von Haus aus so breit wie ihr Platz \u2014 in dieser Zeile bekommt sie\n deshalb eine feste Gr\xF6sse, sonst sch\xF6be sie die Metadaten heraus. */\n.szenen-bilder__eingangsliste .szenen-bildkachel {\n flex: 0 0 auto;\n width: 4rem;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__batch {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__batchkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-bilder__herkunft {\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n}\n\n/* Review-Befund \u2014 ein transienter Bildfehler ist wiederholbar, kein\n endg\xFCltiges \u201Efehlt". Dezent wie ein Angebot, nicht wie ein Fehlerzustand. */\n.szenen-bilder__retry {\n justify-self: start;\n padding: 0.15rem 0.5rem;\n font-size: 0.75rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n/* C4 \u2014 die Provenienz vollst\xE4ndig, aber sekund\xE4r. */\n.szenen-bilder__technik > summary {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.szenen-bilder__meta {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n font-size: 0.75rem;\n color: var(--color-text-secondary);\n}\n\n/* C5 \u2014 der Verlauf verdichtet, seine Ausreisser nicht. */\n.szenen-bilder__verlauf > summary {\n color: var(--color-text-secondary);\n font-size: 0.8125rem;\n cursor: pointer;\n}\n\n.szenen-bilder__verlauf[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bilder__auffaellig {\n margin: 0;\n padding: var(--space-sm);\n border-radius: var(--radius-sm);\n font-size: 0.8125rem;\n}\n\n.szenen-bilder__auftragskennung {\n flex-basis: 100%;\n color: var(--color-text-tertiary);\n font-size: 0.6875rem;\n}\n\n/* \u2500\u2500 C1/C2 \u2014 Galerie und grosse Ansicht \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Das Raster w\xE4chst mit dem Platz: auf 390 px drei bis vier Kacheln je Reihe,\n auf dem Desktop entsprechend mehr. Vorher war jedes Bild eine Zeile aus\n Daumennagel plus vier Metadatenfeldern \u2014 vier Bilder ergaben vier Textzeilen\n und das Protokoll war die Hauptsache. */\n.szenen-bildgalerie {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));\n gap: var(--space-sm);\n min-width: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildgalerie__kachel {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-bildgalerie__kachel:hover,\n.szenen-bildgalerie__kachel:focus-visible {\n border-color: var(--color-accent-teal, var(--color-text-primary));\n}\n\n.szenen-bildgalerie__nummer {\n position: absolute;\n bottom: 0.15rem;\n left: 0.15rem;\n padding: 0.05rem 0.3rem;\n font-size: 0.625rem;\n line-height: 1.4;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n/* Die grosse Ansicht liegt \xFCber allem und bringt ihren eigenen Grund mit \u2014\n `position: fixed` bezieht sich im Flow-Canvas auf dessen Rahmen, in React auf\n das Fenster; in beiden F\xE4llen genau das Gew\xFCnschte. */\n.szenen-bildviewer {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: grid;\n grid-template-rows: auto 1fr auto;\n gap: var(--space-sm);\n padding: var(--space-sm);\n /* Deckend, nicht get\xF6nt: Bei 0.92 schimmerte der Laufbereich durch und man\n las Prompttext quer \xFCber dem Bild \u2014 im Browser gemessen. */\n background: #000;\n}\n\n/* Titel, Z\xE4hlung, Schliessen \u2014 drei Spalten, damit ein langer Werktitel die\n Z\xE4hlung nicht in die n\xE4chste Zeile und \xFCber das Bild schiebt. */\n.szenen-bildviewer__kopf {\n display: grid;\n /* Titel nimmt den Rest; Zaehler, eine optionale Bildaktion (P6) und\n Schliessen stehen rechts \u2014 mit und ohne Aktion in einer Zeile. */\n grid-template-columns: minmax(0, 1fr);\n grid-auto-columns: auto;\n grid-auto-flow: column;\n align-items: center;\n gap: var(--space-sm);\n color: var(--color-text-primary);\n}\n\n.szenen-bildviewer__titel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 600;\n}\n\n.szenen-bildviewer__zaehler {\n color: var(--color-text-secondary);\n font-size: 0.8125rem;\n}\n\n.szenen-bildviewer__buehne {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-sm);\n min-height: 0;\n min-width: 0;\n}\n\n/* Der Rahmen nimmt den Platz, der zwischen den Bl\xE4tterkn\xF6pfen \xFCbrig ist \u2014\n `min-width: 0`, damit er auch wirklich schrumpft statt sie hinauszuschieben. */\n.szenen-bildviewer__rahmen {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n min-height: 0;\n height: 100%;\n}\n\n.szenen-bildviewer__bild {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}\n\n.szenen-bildviewer__leer {\n color: var(--color-text-secondary);\n text-align: center;\n}\n\n/* Die Bl\xE4tterkn\xF6pfe sind daumengross und liegen an den R\xE4ndern \u2014 auf einem\n Telefon ist der Rand erreichbar, die Bildmitte nicht. */\n.szenen-bildviewer__blaettern {\n flex: 0 0 auto;\n width: 2.75rem;\n height: 3.5rem;\n font-size: 1.75rem;\n line-height: 1;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n cursor: pointer;\n}\n\n.szenen-bildviewer__details {\n max-height: 8rem;\n overflow-y: auto;\n color: var(--color-text-secondary);\n}\n\n/* Die Aktionen stehen abgesetzt: Sie sind Angebote, keine Ausk\xFCnfte \u2014 dasselbe\n Muster wie beim Folgelauf und bei der Fehlerrettung. */\n/* D \u2014 die Aktionen stehen abgesetzt und standardm\xE4ssig kompakt: Sie sind\n Angebote, keine Ausk\xFCnfte. Vorher hielten beide Formulare dauerhaft offen und\n machten aus jedem Lauf zwei zus\xE4tzliche Bildschirmseiten. */\n.szenen-bilder__aktion {\n min-width: 0;\n padding: var(--space-sm) var(--space-md);\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__aktion > summary {\n color: var(--color-text-primary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-bilder__aktion[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n.szenen-bilder__aktion-inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-sm);\n}\n\n.szenen-bilder__aktion h5 {\n margin: var(--space-sm) 0 0;\n}\n\n.szenen-bilder__aktion ol {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding-left: var(--space-md);\n font-size: 0.8125rem;\n}\n\n/* Regelwerk-UX Schritt 16 \u2014 der ZIP-Sammelimport.\n *\n * \xA78: Der gemeldete Einsatz ist mobil. Deshalb **ein** Seedfeld statt einer\n * gestapelten Eingabe je Bild, und die Zuordnung Bild -> Seed als umbrechende\n * Zeile statt als Tabelle: Eine Tabelle waere auf 390 px abgeschnitten, und\n * abgeschnitten heisst hier, dass der Nutzer die Zuordnung nicht mehr pruefen\n * kann \u2014 genau die Pruefung, wegen der die Vorschau existiert. */\n.szenen-bilder__zip {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-bilder__zipkopf {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n.szenen-bilder__zipvorlagen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin: 0;\n}\n\n/* Eine laengere Liste bleibt scrollbar, statt die Sektion und damit den\n * Import-Knopf aus dem Blick zu schieben (\xA78, letzter Punkt). */\n.szenen-bilder__zipliste {\n max-height: 16rem;\n overflow-y: auto;\n}\n\n.szenen-bilder__zipliste > li {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-bilder__zipliste > li > span:first-child {\n overflow-wrap: anywhere;\n}\n\n.szenen-bilder__zipliste > li > span:last-child {\n color: var(--color-text-secondary);\n white-space: nowrap;\n}\n\n/* ==========================================================================\n STUFE 6.10 \u2014 ELEMENTEDITOR UND VERSIONSNAVIGATION\n ========================================================================== */\n\n/* \xA74.2 \u2014 vier Sachverhalte, vier Marken. Die Marken stehen in einer eigenen\n * Spalte, damit ANGEZEIGT + BEVORZUGT nebeneinander lesbar bleiben, statt sich\n * durch den Text zu schieben. */\n.szenen-detail__heads li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-version__titel {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n min-width: 0;\n margin-right: auto;\n}\n\n/* V17 \u2014 Kennungen bleiben vollst\xE4ndig sichtbar, aber optisch sekund\xE4r. */\n.szenen-version__id,\n.szenen-ref__id,\n.szenen-detail__field-key {\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-version__marken {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-version__marken > span {\n padding: 0.1rem 0.5rem;\n color: var(--color-text-primary);\n background: rgba(45, 212, 191, 0.12);\n border: 1px solid rgba(45, 212, 191, 0.35);\n border-radius: var(--radius-full);\n font-size: 0.7rem;\n font-weight: 800;\n letter-spacing: 0.08em;\n}\n\n.szenen-version--angezeigt {\n border-color: var(--color-accent-teal, #2dd4bf) !important;\n}\n\n/* V9 \u2014 der Basiswechsel ist eine Entscheidung, keine Nebenwirkung. */\n.szenen-detail__confirm {\n display: grid;\n gap: var(--space-sm);\n margin: var(--space-md) 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-accent-amber, #f59e0b);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__confirm p {\n margin: 0;\n}\n\n/* Untergruppen von Objektfeldern (`prompt_render_settings`, `overrides`,\n `blender_render_settings`) \u2014 seit A1/A2 auf- und zuklappbar. Eine optionale\n Gruppe startet zu: Blender und `overrides` f\xFCllten auf einem 390-px-Display\n sonst mehrere Bildschirmseiten, obwohl die meisten Shots sie nie anfassen. */\n.szenen-detail__group {\n min-width: 0;\n margin: var(--space-md) 0;\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__group > summary {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-weight: 600;\n cursor: pointer;\n}\n\n.szenen-detail__group[open] > summary {\n margin-bottom: var(--space-sm);\n}\n\n/* A2 \u2014 dass eine zugeklappte Gruppe schon Werte tr\xE4gt, muss man sehen, ohne\n sie zu \xF6ffnen. Sonst \xFCbersieht man eine gesetzte Blender-Ausgabe genau so\n lange, bis sie im Ergebnis auftaucht. */\n.szenen-detail__group-status {\n padding: 0.05rem 0.4rem;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--color-text-tertiary);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__group[data-konfiguriert="ja"] > summary .szenen-detail__group-status {\n color: var(--color-text-primary);\n border-color: var(--color-accent-teal, var(--color-border));\n}\n\n.szenen-detail__group-inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-sm);\n}\n\n/* A3 \u2014 die Kernaussage steht am Feld, die Begr\xFCndung dahinter. Nicht als\n Tooltip: Auf einem Telefon gibt es kein Hover, und was dort unerreichbar ist,\n ist gestrichen \u2014 nur ohne dass es jemand entschieden h\xE4tte. */\n.szenen-detail__warum > summary {\n color: var(--color-text-tertiary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.szenen-detail__warum > small {\n display: block;\n padding-top: var(--space-xs);\n color: var(--color-text-tertiary);\n}\n\n.szenen-detail__fieldrow {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n margin-bottom: var(--space-md);\n}\n\n/* A4 \u2014 der technische Feldname bleibt lesbar, tritt aber hinter das fachliche\n Label zur\xFCck. */\n.szenen-detail__field-label {\n color: var(--color-text-primary);\n}\n\n.szenen-detail__field {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-detail__field > span {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n}\n\n/* Mehrfachauswahl und Listeneditoren. */\n.szenen-feld__mehrfach,\n.szenen-feld__liste,\n.szenen-feld__reflist,\n.szenen-feld__ref,\n.szenen-feld__zielmodell,\n.szenen-bilder__modellwahl,\n.szenen-feld__kamera {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n/* \u201ENeues Modell hinzufuegen" im Importdialog \u2014 dieselben Abstaende wie jedes\n andere Formular dieser Ansicht, damit es kein Fremdkoerper wird. */\n.szenen-feld__zielmodell-neu {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n padding: var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-feld__zielmodell-neu-aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-feld__mehrfach > label,\n.szenen-feld__null {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n.szenen-feld__liste-zeile {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n.szenen-feld__reflist ol {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-feld__reflist li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n padding: var(--space-xs) var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* \xA76.1 \u2014 Titel und Typ zuerst, Kennungen daneben. */\n.szenen-ref__anzeige {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-ref__typ {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-ref__warn {\n padding: 0.1rem 0.5rem;\n color: #fecaca;\n background: var(--color-accent-red-dim);\n border-radius: var(--radius-full);\n font-size: 0.72rem;\n font-weight: 700;\n}\n\n/* \xA76.5 \u2014 abgeleitete Angaben, ausdr\xFCcklich nur Anzeige. */\n.szenen-detail__derived {\n margin-top: var(--space-md);\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-detail__derived dl {\n display: grid;\n grid-template-columns: minmax(10rem, auto) 1fr;\n gap: var(--space-xs) var(--space-sm);\n margin: 0;\n}\n\n.szenen-detail__derived dt {\n color: var(--color-text-secondary);\n}\n\n.szenen-detail__derived dd {\n margin: 0;\n}\n\n.szenen-feld__abgeleitet {\n margin: 0;\n color: var(--color-text-tertiary);\n font-size: 0.78rem;\n}\n\n/* Bereich `Prompts` \u2014 die herkunftsuebergreifende Sicht (P1-A).\n *\n * Die Eintraege selbst rendert `RundenEintrag` und tragen damit die\n * `szenen-runs__*`-Regeln. Hier stehen nur Rahmen und Kennzeichen; eine zweite\n * Laufdarstellung gibt es nicht, also braucht sie auch kein zweites Aussehen. */\n.szenen-prompts__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-prompts__heading {\n margin: 0;\n font-size: 1.05rem;\n margin-right: auto;\n}\n\n.szenen-view__fokus {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n}\n\n.szenen-prompts__fokus {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n margin-bottom: var(--space-sm);\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-accent, #0d9488);\n border-radius: var(--radius-sm, 4px);\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-prompts__hinweis {\n font-style: italic;\n}\n\n.szenen-prompts__ausgeblendet {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n Kette `szenen-design`, P8 \u2014 der Bereich `Prompts` als Bildraster\n ========================================================================== */\n\n/* Herkunfts-Chips: eine Zeile, die in sich scrollt \u2014 nie die Seite. */\n.szenen-prompts__chips {\n display: flex;\n flex-wrap: nowrap;\n gap: 0.375rem;\n min-width: 0;\n padding-bottom: 0.15rem;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n\n.szenen-view .szenen-prompts__chip {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.8rem;\n white-space: nowrap;\n border-radius: var(--radius-full);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-prompts__chip[aria-pressed="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-prompts__zeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.375rem;\n min-width: 0;\n}\n\n.szenen-prompts__anzahl {\n flex: 1 1 8rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-prompts__umschalter {\n min-height: 2rem;\n padding: 0 0.65rem;\n font-size: 0.75rem;\n}\n\n.szenen-prompts__raster-bereich {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n/* Der neueste Lauf \u2014 gross, mit Promptzeile und Kopierknopf. */\n.szenen-prompts__neuester {\n min-width: 0;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-prompts__oeffnen {\n display: block;\n width: 100%;\n padding: 0;\n color: var(--color-text-primary);\n text-align: left;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-prompts__bild {\n position: relative;\n display: block;\n height: 17.5rem;\n overflow: hidden;\n}\n\n.szenen-prompts__neuester .szenen-galerie__status {\n top: 0.75rem;\n left: 0.75rem;\n padding: 0.35rem 0.5rem;\n background: rgba(0, 0, 0, 0.55);\n border-radius: var(--radius-full);\n}\n\n.szenen-prompts__neuester .szenen-galerie__bildzahl {\n top: 0.75rem;\n right: 0.75rem;\n}\n\n.szenen-prompts__promptzeile {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.6rem 0.5rem 0.6rem 0.9rem;\n}\n\n.szenen-prompts__prompt {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-view .szenen-kopieren--symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n min-height: 2.75rem;\n padding: 0;\n color: var(--color-text-primary);\n border-radius: var(--radius-lg);\n}\n\n.szenen-prompts__promptzeile .szenen-lauf__kopieren {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 0.4rem;\n}\n\n/* Gruppe aufeinanderfolgender Laeufe derselben Szene. */\n.szenen-prompts__gruppe {\n display: grid;\n gap: 0.6rem;\n min-width: 0;\n}\n\n.szenen-prompts__gruppenkopf {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-prompts__gruppenkopf h4 {\n min-width: 0;\n margin: 0;\n font-size: 1rem;\n font-weight: 650;\n line-height: 1.3;\n overflow-wrap: anywhere;\n}\n\n.szenen-prompts__gruppenkopf span {\n flex: none;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* Zwei Spalten, Kacheln im Format 3:4. */\n.szenen-view .szenen-prompts__raster {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0.625rem;\n min-width: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n@media (min-width: 761px) {\n .szenen-view .szenen-prompts__raster {\n grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));\n }\n}\n\n.szenen-prompts__kachel {\n min-width: 0;\n}\n\n.szenen-view .szenen-prompts__kachel > button {\n position: relative;\n display: block;\n width: 100%;\n min-width: 0;\n aspect-ratio: 3 / 4;\n padding: 0;\n overflow: hidden;\n color: var(--color-text-primary);\n text-align: left;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-prompts__kachel.is-fokus > button,\n.szenen-view .szenen-prompts__neuester.is-fokus {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-prompts__text {\n position: absolute;\n right: 0.75rem;\n bottom: 0.7rem;\n left: 0.75rem;\n display: grid;\n gap: 0.2rem;\n min-width: 0;\n}\n\n.szenen-prompts--mitbild .szenen-prompts__text {\n color: #fff;\n}\n\n.szenen-prompts__titel {\n display: -webkit-box;\n overflow: hidden;\n font-size: 1.25rem;\n font-weight: 700;\n line-height: 1.2;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow-wrap: anywhere;\n}\n\n.szenen-prompts__kachelrunde {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.95rem;\n font-weight: 700;\n}\n\n.szenen-prompts__meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.3rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-prompts--mitbild .szenen-prompts__meta {\n color: rgba(255, 255, 255, 0.82);\n}\n\n.szenen-prompts__statuspunkt {\n display: inline-block;\n flex: none;\n width: 0.5rem;\n height: 0.5rem;\n background: var(--color-success);\n border-radius: 50%;\n}\n\n.szenen-prompts__statuspunkt[data-status="failed"] {\n background: var(--color-danger);\n}\n\n/* Eine Kachel ohne Bild nennt ihren Grund \u2014 oben, damit der Text unten frei bleibt. */\n.szenen-prompts__grund {\n display: grid;\n align-content: start;\n gap: 0.3rem;\n padding-top: 2.25rem;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n line-height: 1.3;\n}\n\n.szenen-prompts__fehlertext {\n display: -webkit-box;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 4;\n overflow-wrap: anywhere;\n}\n\n/* ==========================================================================\n ZIP-MODELLVORSCHLAG (modaler Best\xE4tigungsdialog)\n ========================================================================== */\n\n/* Wie die grosse Bildansicht: eigener Grund, `position: fixed`, damit der\n Dialog im Flow-Canvas und in React gleichermassen \xFCber allem liegt. */\n.szenen-zipmodell {\n position: fixed;\n inset: 0;\n z-index: 1100;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--space-md);\n background: rgba(0, 0, 0, 0.72);\n}\n\n.szenen-zipmodell__karte {\n display: grid;\n gap: var(--space-sm);\n width: min(34rem, 100%);\n max-height: 100%;\n overflow-y: auto;\n padding: var(--space-md);\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-zipmodell__titel {\n margin: 0;\n font-size: 1rem;\n}\n\n.szenen-zipmodell__quelle,\n.szenen-zipmodell__treffer,\n.szenen-zipmodell__vertrauen,\n.szenen-zipmodell__fallback {\n margin: 0;\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__quelle,\n.szenen-zipmodell__vertrauen {\n color: var(--color-text-secondary);\n}\n\n/* Ein schwacher oder mehrdeutiger Treffer muss sich vom sicheren unterscheiden,\n sonst ist die Warnung nur ein weiterer Satz. */\n.szenen-zipmodell__warnung {\n margin: 0;\n padding: var(--space-xs) var(--space-sm);\n color: var(--color-text-primary);\n background: rgba(234, 179, 8, 0.14);\n border-left: 3px solid #eab308;\n border-radius: var(--radius-sm);\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__alternativen {\n display: grid;\n gap: 0.2rem;\n margin: 0;\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n font-size: 0.85rem;\n}\n\n.szenen-zipmodell__alternativen > label {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-zipmodell__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n}\n\n/* ==========================================================================\n MEHR LADEN \u2014 der gemeinsame Fuss jeder seitenweise geladenen Liste\n ========================================================================== */\n\n.szenen-mehr-laden {\n display: grid;\n gap: var(--space-xs);\n justify-items: start;\n padding: var(--space-xs) 0;\n}\n\n.szenen-mehr-laden__button {\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-surface);\n color: var(--color-text-primary);\n font-size: 0.85rem;\n cursor: pointer;\n}\n\n.szenen-mehr-laden__button:disabled {\n cursor: progress;\n opacity: 0.6;\n}\n\n.szenen-mehr-laden__fehler {\n margin: 0;\n color: var(--color-danger, #f87171);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n PROMPTKARTE \u2014 Tags, Vorschau und Bildzahl\n (Kette `szenen-prompt-anzeige-bilder-tags`)\n\n Der Zuschnitt ist der der Library-Karte (`.library-item` + der absolut\n gesetzte Bildstreifen in `LibraryTab`): Textteil links, Deckbild rechts am\n Rand ueber die ganze Kartenhoehe, Bildzahl als Plakette darauf. Dieselben\n Werte (7rem Streifenbreite, linke Trennlinie, Plakette unten rechts), nur\n hier statt in Tailwind-Klassen \u2014 die Szenen-Ansicht teilt dieses Stylesheet\n byteweise mit Flow, und Flow hat kein Tailwind.\n ========================================================================== */\n\n.szenen-promptkarte {\n position: relative;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n padding: var(--space-sm);\n}\n\n/* Nur wo ein Bild liegt, wird Platz dafuer freigehalten. Ohne Bild nutzt der\n Textteil die ganze Breite \u2014 keine leere Spalte. */\n.szenen-promptkarte--mitbild .szenen-promptkarte__inhalt {\n padding-right: calc(7rem + var(--space-sm));\n}\n\n.szenen-promptkarte__bild {\n position: absolute;\n top: 0;\n right: 0;\n width: 7rem;\n height: 100%;\n /* Hoechstens so hoch wie breit \u2014 der Streifen bleibt eine Kachel.\n `height: 100%` allein band ihn an die **Kartenhoehe**, und die ist in der\n aufgeklappten Runde die Hoehe des ganzen Prompts: Das Deckbild sprang\n dann als mehrere hundert Pixel hoher, auf Streifenbreite beschnittener\n Balken an den rechten Rand. Geschlossen aendert die Grenze nichts \u2014 dort\n ist die Karte niedriger als 7rem. */\n max-height: 7rem;\n border-left: 1px solid var(--color-border);\n background: #000;\n}\n\n/* Die gemeinsame Kachel bringt `width: 100%` und `aspect-ratio: 1` mit \u2014 hier\n fuellt sie stattdessen den Streifen, genau wie das Library-Deckbild. */\n.szenen-promptkarte__bild .szenen-bildkachel {\n width: 100%;\n height: 100%;\n aspect-ratio: auto;\n}\n\n.szenen-promptkarte__bildzahl {\n position: absolute;\n right: 0.25rem;\n bottom: 0.25rem;\n padding: 0.1rem 0.35rem;\n border-radius: var(--radius-sm);\n background: rgba(0, 0, 0, 0.6);\n color: #fff;\n font-size: 0.62rem;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n/* Ein Kasten je Karte, nicht zwei.\n *\n * `.szenen-view button` (master.css) gibt **jedem** Knopf der Ansicht Rahmen\n * und Hintergrund und schlaegt dabei `.szenen-runs__kopf` (eine Klasse gegen\n * Klasse plus Element). In der Laufhistorie ist das richtig: Dort ist der Kopf\n * der Eintrag. In der Promptkarte ist die Karte der Eintrag \u2014 ein zweiter\n * Kasten darin waere die doppelte Umrandung, die die Library nicht hat.\n * Der Hover braucht eine eigene Zeile, weil die Regel dort spezifischer ist. */\n.szenen-promptkarte .szenen-runs__kopf,\n.szenen-promptkarte .szenen-runs__kopf:hover:not(:disabled) {\n min-height: 0;\n padding: var(--space-xs) 0;\n background: transparent;\n border: none;\n}\n\n/* Dieselbe Karte in der Elementliste.\n *\n * Dort ist der Auswahlknopf die Karte \u2014 er traegt Rahmen, Hintergrund und die\n * Auswahlmarkierung. Der Bildstreifen liegt deshalb **darueber** statt darin:\n * Ein `<button>` nimmt nur Phrasing Content auf, ein Streifen-`div` darin\n * waere ungueltiges Markup. Damit der rechte Kartenrand trotzdem auswaehlbar\n * bleibt, laesst der Streifen Klicks durch. */\n.szenen-elementkarte {\n position: relative;\n}\n\n.szenen-elementkarte--mitbild > button {\n padding-right: calc(7rem + var(--space-sm));\n}\n\n.szenen-elementkarte > .szenen-promptkarte__bild {\n border-radius: 0 var(--radius-sm) var(--radius-sm) 0;\n}\n\n.szenen-promptkarte__bild--durchklickbar {\n pointer-events: none;\n}\n\n/* Null Bilder: die Zahl, keine Flaeche. */\n/* Die Tagliste bricht um. Auf einem Telefon ist das der Unterschied zwischen\n einer kompakten Karte und einer Zeile, die seitlich herauslaeuft. */\n.szenen-tagliste {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n align-items: center;\n margin: 0 0 var(--space-xs);\n padding: 0;\n list-style: none;\n}\n\n.szenen-tag {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.05rem 0.4rem;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-app);\n font-size: 0.72rem;\n line-height: 1.5;\n white-space: nowrap;\n}\n\n/* Herkunft sichtbar, aber ohne zweite Bedeutungsebene: Ein Prompt-Tag steht\n voll, ein reiner Library-Tag zurueckgenommen. Die Karte soll schnell lesbar\n sein, nicht zwei Farbcodes lehren. */\n.szenen-tag[data-herkunft="library"] {\n border-style: dashed;\n opacity: 0.85;\n}\n\n.szenen-tag--rest {\n border-style: none;\n opacity: 0.7;\n}\n\n.szenen-tag__weg {\n border: none;\n background: none;\n padding: 0;\n color: var(--color-text-secondary, inherit);\n font-size: 0.85rem;\n line-height: 1;\n cursor: pointer;\n}\n\n.szenen-tag__weg:disabled {\n cursor: progress;\n opacity: 0.5;\n}\n\n.szenen-taggeber {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-xs);\n margin-bottom: var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-taggeber__zeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n margin: 0;\n}\n\n.szenen-taggeber__label {\n font-size: 0.72rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n opacity: 0.75;\n}\n\n.szenen-taggeber__leer,\n.szenen-taggeber__hinweis {\n font-size: 0.72rem;\n opacity: 0.75;\n}\n\n.szenen-taggeber input[type="text"] {\n flex: 1 1 8rem;\n min-width: 0;\n padding: var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n background: var(--color-bg-surface);\n color: var(--color-text-primary);\n font-size: 0.8rem;\n}\n\n/* ==========================================================================\n BILDAUFTR\xC4GE \u2014 die bestandsweite Arbeitsqueue\n Kette `szenen-bildauftraege-arbeitsqueue`, Schritt 01.\n ========================================================================== */\n\n.szenen-bildauftraege {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-bildauftraege__steuerung,\n.szenen-bildauftraege__filter,\n.szenen-bildauftraege__aktionen,\n.szenen-bildauftraege__nachladen,\n.szenen-bildauftraege__blaettern {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n}\n\n/* Der manuelle Refresh \u2014 Schritt 03 \xA72. Er steht oben und sichtbar, weil er\n die einzige Stelle ist, an der dieser Bereich nachlaedt: Es gibt keinen\n Timer mehr, den er ersetzen koennte. */\n.szenen-bildauftraege__nachladen {\n justify-content: flex-start;\n}\n\n.szenen-bildauftraege__nachladen span {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n/* Die Blaetterleiste der Bildkontrolle \u2014 Schritt 03 \xA73.1. */\n.szenen-bildauftraege__blaettern {\n margin: 0;\n}\n\n/* \u201EWeitere Bilder" \u2014 seit Schritt 06 eine **Leiste in der Zeile**, kein\n aufklappbares Formular: Modell, Anzahl, Knopf nebeneinander. */\n.szenen-bildauftraege__weitere {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n margin: var(--space-xs) 0 0;\n font-size: 0.85rem;\n}\n\n.szenen-bildauftraege__weitere label {\n color: var(--color-text-secondary);\n}\n\n/* Der Lauf-Zaehler: sichtbar, aber nicht im Weg (Schritt 06). */\n.szenen-bildauftraege__laufzaehler {\n padding: 0.05rem var(--space-xs);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm, 4px);\n font-size: 0.8rem;\n font-variant-numeric: tabular-nums;\n}\n\n/* Die Vorschau steht oben und beh\xE4lt ihren Platz, auch solange noch kein Bild\n vorliegt \u2014 sie ist die Kontrollfl\xE4che des zweiten Browserfensters (\xA75). */\n.szenen-bildauftraege__letztes {\n display: grid;\n gap: var(--space-xs);\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-bildauftraege__letztes h3 {\n margin: 0;\n font-size: 0.95rem;\n}\n\n.szenen-bildauftraege__letztes .szenen-bildkachel {\n width: min(100%, 22rem);\n height: auto;\n}\n\n.szenen-bildauftraege__lauf {\n padding: var(--space-xs) var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bildauftraege__lauf p {\n margin: 0.1rem 0;\n}\n\n.szenen-bildauftraege__liste {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bildauftraege__zeile {\n display: grid;\n gap: 0.25rem;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bildauftraege__kopf,\n.szenen-bildauftraege__prompt {\n margin: 0;\n}\n\n.szenen-bildauftraege__meta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.15rem var(--space-sm);\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-bildauftraege__prompt {\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n/* \u2500\u2500 Kette `szenen-design`, P4: Szene als Studio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * Kopf mit Speichern, Hero mit Titelbild und Versions-Pill, die B\xFChne auf\n * einem Punktraster, das Element-Sheet von unten, der Prompt-Start als ein\n * Block, L\xE4ufe als Bildstreifen, Aufklapper unten. Kn\xF6pfe in der B\xFChne und im\n * Sheet setzen die Grundoptik von `.szenen-view button` gezielt zur\xFCck \u2014 daher\n * die zwei Klassen in diesen Selektoren. */\n.szenen-studio {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n.szenen-studio__kopf {\n position: sticky;\n top: 0;\n z-index: 3;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n padding: var(--space-xs) 0;\n background: var(--color-bg-app);\n}\n\n.szenen-studio__kopf > .szenen-detail__ids {\n flex: 1 1 auto;\n margin: 0;\n}\n\n.szenen-studio__ungespeichert {\n color: var(--color-warning);\n font-size: 0.8rem;\n font-weight: 600;\n}\n\n.szenen-view .szenen-studio__speichern {\n min-height: 2.25rem;\n padding: 0 1rem;\n color: var(--color-accent-teal, #2dd4bf);\n background: transparent;\n border-color: var(--color-accent-teal, #2dd4bf);\n border-radius: var(--radius-full);\n font-weight: 650;\n}\n\n.szenen-studio__hero {\n position: relative;\n min-height: 12rem;\n overflow: hidden;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-studio__hero--mitbild {\n min-height: 16rem;\n border-color: transparent;\n}\n\n.szenen-studio__titelbild {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-studio__scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.45) 42%, rgba(0, 0, 0, 0) 70%);\n}\n\n.szenen-studio__ohnebild {\n position: absolute;\n inset: 0;\n padding: var(--space-md);\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 16px 16px,\n var(--color-bg-surface);\n}\n\n.szenen-studio__symbole {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-sm);\n color: var(--color-text-secondary);\n}\n\n.szenen-studio__bildfehler {\n margin: 0 0 var(--space-sm);\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-studio__herotext {\n position: absolute;\n right: var(--space-md);\n bottom: var(--space-md);\n left: var(--space-md);\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-studio__herotext h3 {\n margin: 0;\n font-size: 1.5rem;\n line-height: 1.2;\n overflow-wrap: anywhere;\n}\n\n.szenen-studio__hero--mitbild .szenen-studio__herotext {\n color: #fff;\n}\n\n.szenen-studio__herometa {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-studio__pill {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n color: inherit;\n background: rgba(0, 0, 0, 0.55);\n border: 1px solid rgba(255, 255, 255, 0.25);\n border-radius: var(--radius-full);\n}\n\n.szenen-studio__hero:not(.szenen-studio__hero--mitbild) .szenen-studio__pill {\n background: var(--color-bg-elevated);\n border-color: var(--color-border);\n}\n\n/* Kette `szenen-design`, P6 \u2014 Titelbild: \u22EF-Menue im Hero, Hinweis, Zeile\n unter \u201ETechnisch" und die Aktion im Bildviewer. */\n.szenen-studio__heromenu {\n position: relative;\n display: inline-flex;\n}\n\n.szenen-view .szenen-studio__menuknopf {\n justify-content: center;\n min-width: 2.25rem;\n padding: 0 0.5rem;\n}\n\n.szenen-studio__menu {\n position: absolute;\n top: calc(100% + 0.25rem);\n left: 0;\n z-index: 5;\n display: grid;\n min-width: 12rem;\n padding: var(--space-xs, 0.25rem);\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md, 0.5rem);\n}\n\n.szenen-studio__menu button {\n min-height: 2.25rem;\n padding: 0 0.75rem;\n text-align: left;\n color: inherit;\n background: transparent;\n border: 0;\n}\n\n.szenen-studio__menu button:disabled {\n color: var(--color-text-secondary);\n}\n\n.szenen-studio__titelbildhinweis {\n margin: 0;\n font-size: 0.8rem;\n color: var(--color-warning);\n}\n\n.szenen-studio__hero--mitbild .szenen-studio__titelbildhinweis {\n color: #fde68a;\n}\n\n.szenen-studio__titelbildzeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n padding: var(--space-sm) 0;\n font-size: 0.875rem;\n}\n\n.szenen-studio__titelbildref {\n display: block;\n overflow-wrap: anywhere;\n color: var(--color-text-secondary);\n}\n\n.szenen-view .szenen-bildviewer__aktion {\n min-height: 2.25rem;\n padding: 0 0.75rem;\n}\n\n.szenen-bildviewer__titelbild {\n color: var(--color-accent-teal, #2dd4bf);\n font-size: 0.8125rem;\n}\n\n.szenen-studio__komposition {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-studio__abschnittkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-studio__abschnittkopf h4 {\n margin: 0;\n}\n\n.szenen-studio__umschalter {\n display: inline-flex;\n padding: 3px;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-studio__umschalter button {\n min-height: 2rem;\n padding: 0 0.75rem;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-studio__umschalter button[aria-pressed="true"] {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-studio__aufklapper {\n display: grid;\n min-width: 0;\n}\n\n.szenen-studio__aufklapper > details {\n min-width: 0;\n border-top: 1px solid var(--color-border);\n}\n\n.szenen-studio__aufklapper > details:last-child {\n border-bottom: 1px solid var(--color-border);\n}\n\n.szenen-studio__aufklapper > details > summary {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n cursor: pointer;\n}\n\n.szenen-studio__zusammenfassung {\n margin-left: auto;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Die B\xFChne */\n.szenen-buehne {\n position: relative;\n width: 100%;\n aspect-ratio: 358 / 330;\n overflow: hidden;\n background:\n radial-gradient(var(--color-border) 1px, transparent 1px) 0 0 / 16px 16px,\n var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-buehne--leer {\n display: grid;\n place-items: center;\n aspect-ratio: auto;\n min-height: 8rem;\n color: var(--color-text-secondary);\n}\n\n.szenen-buehne__linien {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n}\n\n.szenen-buehne__linie {\n stroke: var(--color-text-tertiary);\n stroke-width: 1.5;\n}\n\n.szenen-buehne__linie--naehe {\n stroke-width: 1;\n stroke-dasharray: 3 4;\n}\n\n.szenen-buehne__linie--kontakt {\n stroke: var(--color-text-primary);\n stroke-width: 3;\n}\n\n.szenen-buehne__kegel-start {\n stop-color: var(--color-accent-amber, #f2c46d);\n stop-opacity: 0.35;\n}\n\n.szenen-buehne__kegel-ende {\n stop-color: var(--color-accent-amber, #f2c46d);\n stop-opacity: 0;\n}\n\n.szenen-view .szenen-buehne__node {\n position: absolute;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.3rem;\n min-height: 0;\n max-width: 6rem;\n padding: 0;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n transform: translate(-50%, -50%);\n}\n\n.szenen-view .szenen-buehne__node:hover:not(:disabled) {\n background: transparent;\n}\n\n.szenen-buehne__symbol {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-buehne__node--mitte .szenen-buehne__symbol {\n width: 4rem;\n height: 4rem;\n border: 2px solid var(--color-text-primary);\n}\n\n.szenen-buehne__node--light .szenen-buehne__symbol {\n color: var(--color-accent-amber, #f2c46d);\n}\n\n.szenen-buehne__node[aria-pressed="true"] .szenen-buehne__symbol {\n box-shadow: 0 0 0 2px var(--color-accent-blue);\n}\n\n.szenen-buehne__name {\n max-width: 100%;\n padding: 0 0.25rem;\n overflow: hidden;\n background: var(--color-bg-app);\n border-radius: var(--radius-sm);\n font-size: 0.75rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-buehne__node--mitte .szenen-buehne__name {\n font-weight: 650;\n}\n\n.szenen-buehne__legende {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs) var(--space-md);\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-buehne__legende > span {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-buehne__legende-hinweis {\n margin-left: auto;\n}\n\n.szenen-buehne__muster {\n display: inline-block;\n width: 1.1rem;\n border-top: 1px dashed var(--color-text-tertiary);\n}\n\n.szenen-buehne__muster--kontakt {\n border-top: 3px solid var(--color-text-primary);\n}\n\n/* Das Element-Sheet */\n.szenen-sheet {\n position: fixed;\n inset: 0;\n z-index: 50;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n}\n\n.szenen-view .szenen-sheet__hintergrund {\n position: absolute;\n inset: 0;\n padding: 0;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n border-radius: 0;\n cursor: default;\n}\n\n.szenen-sheet__flaeche {\n position: relative;\n display: grid;\n gap: var(--space-md);\n width: 100%;\n max-width: 40rem;\n max-height: 85vh;\n padding: var(--space-sm) var(--space-md) var(--space-md);\n overflow-y: auto;\n box-sizing: border-box;\n background: var(--color-bg-surface);\n border-top: 1px solid var(--color-border);\n border-radius: 1.5rem 1.5rem 0 0;\n}\n\n.szenen-sheet__griff {\n justify-self: center;\n width: 2.5rem;\n height: 4px;\n background: var(--color-border);\n border-radius: 2px;\n}\n\n.szenen-sheet__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-sheet__symbol {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 3.5rem;\n height: 3.5rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: 50%;\n}\n\n.szenen-sheet__symbol--light {\n color: var(--color-accent-amber, #f2c46d);\n}\n\n.szenen-sheet__titel {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n}\n\n.szenen-sheet__titel strong {\n font-size: 1.25rem;\n}\n\n.szenen-sheet__titel code {\n overflow: hidden;\n color: var(--color-text-secondary);\n font-family: var(--font-mono);\n font-size: 0.75rem;\n text-overflow: ellipsis;\n}\n\n.szenen-view .szenen-sheet__schliessen {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2.75rem;\n height: 2.75rem;\n margin-left: auto;\n padding: 0;\n border-radius: 50%;\n}\n\n.szenen-sheet__abschnitt {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-sheet__abschnitt h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n font-weight: 500;\n}\n\n.szenen-sheet__leer {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-sheet__beziehungen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-sheet__beziehungen li {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n}\n\n.szenen-sheet__beziehungsart {\n color: var(--color-text-secondary);\n}\n\n.szenen-sheet__bilder {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-sheet__bild {\n position: relative;\n aspect-ratio: 1 / 1;\n overflow: hidden;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-sheet__bild img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-sheet__bildtext {\n display: grid;\n gap: 0.2rem;\n padding: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.65rem;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n.szenen-sheet__bildtext code {\n font-family: var(--font-mono);\n}\n\n.szenen-view .szenen-sheet__fertig {\n min-height: 3rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border: none;\n border-radius: var(--radius-md);\n font-weight: 700;\n}\n\n/* Der Prompt-Start als ein Block */\n.szenen-start {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-view .szenen-start__primaer {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-accent-teal, #2dd4bf);\n border: none;\n border-radius: var(--radius-md);\n font-size: 1.05rem;\n font-weight: 700;\n}\n\n.szenen-start__kosten {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n text-align: center;\n}\n\n.szenen-start__manuell {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-view .szenen-start__zweit {\n min-height: 2.75rem;\n background: transparent;\n}\n\n.szenen-start__erklaerung > summary {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-start__erklaerung[open] .szenen-start__chevron {\n transform: rotate(90deg);\n}\n\n/* L\xE4ufe als Bildstreifen */\n.szenen-streifen {\n display: grid;\n gap: 0.35rem;\n padding: 0 var(--space-sm) var(--space-sm);\n}\n\n.szenen-streifen__bilder {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-streifen__bild {\n position: relative;\n aspect-ratio: 3 / 4;\n overflow: hidden;\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n}\n\n.szenen-streifen__bild img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.szenen-streifen__fehler {\n display: block;\n padding: 0.25rem;\n color: var(--color-text-secondary);\n font-size: 0.65rem;\n}\n\n.szenen-streifen__mehr {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n background: rgba(0, 0, 0, 0.6);\n font-size: 0.95rem;\n font-weight: 700;\n}\n\n.szenen-streifen__anzahl {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n/* \xC4ltere Runden: kompakte Zeile mit \xFCberlappenden Miniaturen. */\n.szenen-streifen--zeile {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-streifen--zeile .szenen-streifen__bilder {\n display: flex;\n gap: 0;\n}\n\n.szenen-streifen--zeile .szenen-streifen__bild {\n width: 2.1rem;\n height: 2.75rem;\n aspect-ratio: auto;\n border: 2px solid var(--color-bg-surface);\n}\n\n.szenen-streifen--zeile .szenen-streifen__bild + .szenen-streifen__bild {\n margin-left: -0.75rem;\n}\n\n.szenen-runs__eintrag--karte {\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n/* Szenenst\xE4nde enthalten mehrere Runden derselben eingefrorenen Szene (#538). */\n.szenen-runs__stand > h5 {\n margin: 0;\n font-size: 1rem;\n}\n\n.szenen-runs__stand-laeufe {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-runs__stand-laeufe > li {\n display: grid;\n gap: var(--space-sm);\n padding: var(--space-sm);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n/* ==========================================================================\n Kette `szenen-design`, P5 \u2014 der Prompt-Lauf als Ergebnisgalerie\n ========================================================================== */\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-chip,\n.szenen-view .szenen-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n min-height: 1.75rem;\n padding: 0 0.65rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n line-height: 1.2;\n white-space: nowrap;\n}\n\n.szenen-view .szenen-chip--knopf {\n min-height: 2.25rem;\n color: var(--color-text-primary);\n cursor: pointer;\n}\n\n.szenen-chip--library,\n.szenen-view .szenen-chip--library {\n color: var(--color-accent-teal, #2dd4bf);\n border-color: var(--color-accent-teal, #2dd4bf);\n}\n\n/* \u2500\u2500 Navigation der Laufansicht \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf__nav {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n min-width: 0;\n scroll-margin-top: var(--space-md);\n}\n\n.szenen-view .szenen-lauf__zurueck {\n display: inline-flex;\n align-items: center;\n gap: 0.15rem;\n min-height: 2.75rem;\n padding: 0 0.6rem 0 0.25rem;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n}\n\n.szenen-lauf__blaettern {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.2rem;\n color: var(--color-text-secondary);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-lauf__blaettern button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n min-height: 2.5rem;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n}\n\n/* \u2500\u2500 Kopf: Runde, Status, Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-laufinhalt {\n gap: var(--space-md);\n}\n\n.szenen-lauf__kopf {\n display: grid;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-lauf__szene {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-lauf__titelzeile {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__runde {\n margin: 0;\n color: var(--color-text-primary);\n font-size: 1.6rem;\n font-weight: 700;\n line-height: 1.15;\n}\n\n.szenen-lauf__status {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n min-height: 1.6rem;\n padding: 0 0.6rem;\n border: 1px solid currentColor;\n border-radius: var(--radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.szenen-lauf__status::before {\n content: "";\n width: 0.4rem;\n height: 0.4rem;\n border-radius: 50%;\n background: currentColor;\n}\n\n.szenen-lauf__status[data-status="succeeded"] { color: var(--color-success); }\n.szenen-lauf__status[data-status="failed"] { color: var(--color-danger); }\n\n.szenen-lauf__chips {\n display: flex;\n flex-wrap: wrap;\n gap: 0.4rem;\n min-width: 0;\n}\n\n.szenen-lauf__hinweis {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n}\n\n/* \u2500\u2500 Galerie \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf .szenen-bilder__ausgang {\n padding: 0;\n background: none;\n border: none;\n}\n\n.szenen-lauf {\n gap: var(--space-md);\n margin-top: 0;\n}\n\n.szenen-lauf .szenen-bilder__batch {\n padding: 0;\n background: none;\n border: none;\n}\n\n.szenen-bildgalerie--ergebnis {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n overflow: hidden;\n border-radius: var(--radius-md);\n}\n\n.szenen-bildgalerie--einzeln {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.szenen-bildgalerie--ergebnis .szenen-bildgalerie__kachel {\n border: none;\n border-radius: 0;\n}\n\n.szenen-bildgalerie--einzeln .szenen-bildgalerie__kachel {\n border-radius: var(--radius-md);\n}\n\n.szenen-bildgalerie--ergebnis .szenen-bildkachel {\n aspect-ratio: 3 / 4;\n}\n\n/* Ein einzelnes Ergebnisbild im echten Format zeigen \u2014 wie das Gemini-Preview:\n zentriert, ganz sichtbar, nichts abgeschnitten (vorher 3:4 mit cover). */\n.szenen-bildgalerie--einzeln .szenen-bildkachel {\n aspect-ratio: auto;\n background: none;\n}\n\n.szenen-bildgalerie--einzeln .szenen-bildkachel:not(:has(img)) {\n aspect-ratio: 4 / 3;\n}\n\n.szenen-bildgalerie--einzeln .szenen-bildkachel img {\n width: auto;\n max-width: 100%;\n height: auto;\n max-height: 28rem;\n margin-inline: auto;\n object-fit: contain;\n border: 1px solid var(--color-border-hover);\n border-radius: var(--radius-md);\n}\n\n.szenen-bildgalerie__alle-text {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.1rem;\n color: #fff;\n background: rgba(0, 0, 0, 0.65);\n font-size: 0.75rem;\n}\n\n.szenen-bildgalerie__alle-text strong {\n font-size: 1.25rem;\n}\n\n/* P5-Akzeptanz: Eine leere Kachel nennt ihren Grund \u2014 lesbar, nicht nur im\n Tooltip. */\n.szenen-bildkachel__grund {\n display: -webkit-box;\n max-width: 90%;\n overflow: hidden;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n line-height: 1.3;\n text-align: center;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n}\n\n/* \u2500\u2500 Karten: Prompt, Tags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-lauf__karte {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-lauf__kartenkopf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__label {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-lauf__legende {\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-size: 0.72rem;\n}\n\n.szenen-lauf__kopieren {\n display: inline-flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-lauf__prompttext {\n margin: 0;\n color: var(--color-text-primary);\n line-height: 1.5;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n/* Drei Zeilen Vorschau \u2014 der volle Text bleibt im Dokument (Kopieren,\n Markieren), gek\xFCrzt wird nur die Darstellung. */\n.szenen-lauf__prompttext--zu {\n display: -webkit-box;\n overflow: hidden;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n}\n\n.szenen-view .szenen-lauf__ganz {\n justify-self: start;\n min-height: 2.25rem;\n padding: 0;\n color: var(--color-accent-teal, var(--color-text-primary));\n background: transparent;\n border: none;\n}\n\n.szenen-lauf__negativ {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-lauf__negativ[hidden] {\n display: none;\n}\n\n.szenen-lauf__negativ p {\n margin: 0;\n color: var(--color-text-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.szenen-lauf__karte .szenen-taggeber {\n margin: 0;\n}\n\n.szenen-tagliste .szenen-tag__neu {\n min-height: 2rem;\n}\n\n/* \u2500\u2500 \u201ENeue Bilder" (Serverauftrag des Hosts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-neuebilder {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg, var(--radius-md));\n}\n\n.szenen-neuebilder__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-neuebilder__kopf h4 {\n margin: 0;\n color: var(--color-text-primary);\n font-size: 1.05rem;\n}\n\n.szenen-neuebilder__symbol {\n color: var(--color-accent-teal, #2dd4bf);\n}\n\n.szenen-neuebilder__weg {\n margin-left: auto;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-neuebilder__felder {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--space-sm);\n}\n\n.szenen-wahlfeld {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n padding: 0.4rem 0.6rem;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-wahlfeld__label {\n color: var(--color-text-secondary);\n font-size: 0.68rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n.szenen-view .szenen-wahlfeld select {\n min-height: 1.75rem;\n padding: 0;\n color: var(--color-text-primary);\n background: transparent;\n border: none;\n font-weight: 600;\n}\n\n.szenen-umschalter {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n padding: 3px;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-view .szenen-umschalter button {\n min-height: 2.5rem;\n background: transparent;\n border: none;\n}\n\n.szenen-view .szenen-umschalter button[aria-pressed="true"] {\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n font-weight: 600;\n}\n\n.szenen-view .szenen-neuebilder__start {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-sm);\n min-height: 3.25rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border: none;\n border-radius: var(--radius-md);\n font-size: 1rem;\n font-weight: 700;\n}\n\n.szenen-view .szenen-neuebilder__start:hover:not(:disabled) {\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n opacity: 0.9;\n}\n\n.szenen-neuebilder__laedt,\n.szenen-neuebilder__fehler {\n margin: 0;\n font-size: 0.85rem;\n}\n\n.szenen-neuebilder__laedt { color: var(--color-text-secondary); }\n\n/* Referenzbild eines Laufs (#569-Folge): eigener Bereich \xFCber den Ergebnissen. */\n.szenen-bilder__referenz {\n display: flex;\n gap: var(--space-md);\n align-items: center;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-left: 3px solid var(--color-accent-blue);\n border-radius: var(--radius-md);\n}\n\n.szenen-bilder__referenzbild {\n flex: none;\n width: 9rem;\n}\n\n.szenen-bilder__referenzbild img {\n display: block;\n width: 100%;\n border-radius: var(--radius-sm);\n}\n\n.szenen-bilder__referenzleer {\n display: grid;\n place-items: center;\n aspect-ratio: 4 / 3;\n color: var(--color-text-secondary);\n background: var(--color-bg-elevated);\n border-radius: var(--radius-sm);\n font-size: 0.8rem;\n}\n\n.szenen-bilder__referenztext {\n display: grid;\n gap: 0.2rem;\n min-width: 0;\n color: var(--color-text-secondary);\n font-size: 0.82rem;\n}\n\n.szenen-bilder__referenztext strong {\n color: var(--color-text-primary);\n}\n\n/* Referenzbild und Prompt am einzelnen Bildauftrag. */\n.szenen-zeitleiste__referenz {\n display: flex;\n gap: var(--space-sm);\n align-items: center;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-zeitleiste__referenz img,\n.szenen-zeitleiste__referenz-leer {\n display: block;\n width: 4.5rem;\n aspect-ratio: 4 / 3;\n object-fit: cover;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-sm);\n}\n\n.szenen-zeitleiste__prompt {\n white-space: pre-wrap;\n user-select: text;\n}\n\n/* Das mitgegebene Kamera-Preview (#569-Folge) \u2014 sichtbar, bevor bestellt wird. */\n.szenen-neuebilder__referenz {\n margin: 0;\n padding: 0.35rem 0.6rem;\n color: var(--color-text-primary);\n background: var(--color-accent-blue-dim);\n border-left: 2px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n font-size: 0.82rem;\n}\n.szenen-neuebilder__fehler { color: var(--color-danger); }\n\n.szenen-neuebilder__warnung > summary {\n display: flex;\n align-items: flex-start;\n gap: var(--space-sm);\n color: var(--color-warning);\n font-size: 0.85rem;\n line-height: 1.45;\n cursor: pointer;\n list-style: none;\n}\n\n.szenen-neuebilder__warnung > summary::-webkit-details-marker { display: none; }\n\n.szenen-neuebilder__warnung > p,\n.szenen-neuebilder__zuordnung ul {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n line-height: 1.5;\n}\n\n.szenen-neuebilder__zuordnung > summary {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-neuebilder__zuordnung ul {\n padding-left: 1.1rem;\n}\n\n/* \u2500\u2500 Aufklapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-aufklapper {\n display: grid;\n min-width: 0;\n border-bottom: 1px solid var(--color-border);\n}\n\n.szenen-aufklapper__eintrag,\n.szenen-aufklapper .szenen-bilder__aktion {\n min-width: 0;\n padding: 0;\n border: none;\n border-top: 1px solid var(--color-border);\n border-radius: 0;\n}\n\n.szenen-aufklapper__eintrag > summary,\n.szenen-aufklapper .szenen-bilder__aktion > summary {\n list-style: none;\n cursor: pointer;\n}\n\n.szenen-aufklapper__eintrag > summary::-webkit-details-marker { display: none; }\n\n.szenen-aufklapper .szenen-bilder__aktion[open] > summary {\n margin-bottom: 0;\n}\n\n.szenen-aufklapper__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-height: 2.75rem;\n padding: 0 var(--space-xs);\n color: var(--color-text-primary);\n font-weight: 400;\n}\n\n.szenen-aufklapper__pfeil {\n flex: none;\n transition: transform 0.15s ease;\n}\n\ndetails[open] > summary .szenen-aufklapper__pfeil {\n transform: rotate(90deg);\n}\n\n.szenen-aufklapper__titel {\n min-width: 0;\n}\n\n.szenen-aufklapper__meta {\n margin-left: auto;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-aufklapper__inhalt {\n display: grid;\n gap: var(--space-sm);\n min-width: 0;\n padding: 0 var(--space-xs) var(--space-md) 2rem;\n}\n\n@media (max-width: 760px) {\n .szenen-aufklapper__inhalt {\n padding-left: var(--space-xs);\n }\n}\n\n.szenen-aufklapper__inhalt > p {\n margin: 0;\n}\n\n/* \u2500\u2500 Zeitleiste der Bildauftr\xE4ge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-zeitleiste {\n display: grid;\n gap: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-zeitleiste__schritt {\n position: relative;\n display: flex;\n gap: var(--space-sm);\n min-width: 0;\n padding-bottom: var(--space-md);\n}\n\n/* Die Linie zur n\xE4chsten Zeile. */\n.szenen-zeitleiste__schritt:not(:last-child)::before {\n content: "";\n position: absolute;\n top: 2.1rem;\n bottom: 0;\n left: calc(1rem - 1px);\n width: 2px;\n background: var(--color-border);\n}\n\n.szenen-zeitleiste__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n border: 1px solid var(--color-border);\n border-radius: 50%;\n background: var(--color-bg-elevated);\n color: var(--color-text-secondary);\n font-weight: 700;\n}\n\n.szenen-zeitleiste__symbol[data-zustand="fertig"] {\n color: var(--color-success);\n border-color: var(--color-success);\n background: var(--color-accent-green-dim, var(--color-bg-elevated));\n}\n\n.szenen-zeitleiste__symbol[data-zustand="fehlgeschlagen"] {\n color: var(--color-danger);\n border-color: var(--color-danger);\n background: var(--color-accent-red-dim, var(--color-bg-elevated));\n}\n\n.szenen-zeitleiste__symbol[data-zustand="teilweise"] {\n color: var(--color-warning);\n border-color: var(--color-warning);\n}\n\n.szenen-zeitleiste__inhalt {\n display: grid;\n gap: 0.15rem;\n min-width: 0;\n padding-top: 0.3rem;\n}\n\n.szenen-zeitleiste__titel {\n color: var(--color-text-primary);\n font-size: 0.9rem;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__ergebnis,\n.szenen-zeitleiste__zusatz {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__ergebnis[data-zustand="fehlgeschlagen"] { color: var(--color-danger); }\n.szenen-zeitleiste__ergebnis[data-zustand="teilweise"] { color: var(--color-warning); }\n\n.szenen-zeitleiste__aktionen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-xs);\n margin-top: var(--space-xs);\n}\n\n.szenen-zeitleiste__meldung > summary {\n min-height: 2rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n line-height: 2rem;\n cursor: pointer;\n}\n\n.szenen-zeitleiste__meldung p {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n overflow-wrap: anywhere;\n}\n\n.szenen-zeitleiste__meldung code {\n display: block;\n margin-top: var(--space-xs);\n color: var(--color-text-tertiary, var(--color-text-secondary));\n font-family: var(--font-mono);\n font-size: 0.72rem;\n overflow-wrap: anywhere;\n}\n\n/* \u2500\u2500 Annahmen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.szenen-annahmen {\n display: grid;\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-annahmen__zeile {\n display: flex;\n gap: var(--space-sm);\n min-width: 0;\n}\n\n.szenen-annahmen__symbol {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n color: var(--color-text-primary);\n background: var(--color-bg-elevated);\n border-radius: 50%;\n}\n\n.szenen-annahmen__text {\n display: grid;\n gap: 0.1rem;\n min-width: 0;\n font-size: 0.85rem;\n line-height: 1.45;\n overflow-wrap: anywhere;\n}\n\n.szenen-annahmen__art {\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n.szenen-annahmen__text details > summary,\n.szenen-lauf__erlaeuterung > summary {\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n cursor: pointer;\n}\n\n.szenen-annahmen__text details p,\n.szenen-lauf__erlaeuterung p {\n margin: var(--space-xs) 0 0;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n line-height: 1.5;\n white-space: pre-wrap;\n}\n\n.szenen-lauf__handeingabe h5 {\n margin: 0 0 var(--space-xs);\n}\n\n.szenen-lauf__handeingabe p {\n margin: 0;\n font-size: 0.85rem;\n}\n\n/* Kette `szenen-design`, P7 (#533) \u2014 die Szene aus Bausteinen. Felder als\n Karten, Bausteine im Feld als Chips; die Leiste ist das vorhandene\n Bottom-Sheet mit Bildkacheln. Bedient wird durch Antippen, nicht Ziehen. */\n.szenen-bausteinfelder {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n}\n\n.szenen-bausteinfelder__liste {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));\n gap: var(--space-sm);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bausteinfeld {\n display: grid;\n align-content: start;\n gap: var(--space-xs);\n min-width: 0;\n padding: var(--space-sm);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-bausteinfeld__kopf {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-bausteinfeld__leer,\n.szenen-bausteinfeld__gesperrt {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-bausteinfeld__refs {\n display: grid;\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-bausteinchip {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-xs);\n min-width: 0;\n}\n\n.szenen-view .szenen-bausteinchip__name {\n min-height: 2.25rem;\n max-width: 100%;\n padding: 0 0.75rem;\n overflow: hidden;\n background: var(--color-bg-elevated);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bausteinchip__aktionen {\n display: inline-flex;\n gap: var(--space-xs);\n}\n\n.szenen-view .szenen-bausteinchip__aktionen button {\n min-width: 2.25rem;\n min-height: 2.25rem;\n padding: 0 0.6rem;\n border-radius: var(--radius-full);\n}\n\n.szenen-view .szenen-bausteinfeld__plus {\n display: inline-flex;\n align-items: center;\n justify-self: start;\n gap: 0.35rem;\n min-height: 2.25rem;\n padding: 0 0.75rem;\n background: transparent;\n border: 1px dashed var(--color-border);\n border-radius: var(--radius-full);\n}\n\n.szenen-bausteinfelder__weitere {\n display: grid;\n gap: var(--space-xs);\n}\n\n.szenen-bausteinfelder__weitere h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n font-weight: 500;\n}\n\n.szenen-bausteinfelder__weitere ul {\n display: grid;\n gap: 0.25rem;\n margin: 0;\n padding: 0;\n list-style: none;\n font-size: 0.85rem;\n}\n\n.szenen-bausteinfelder__ort {\n color: var(--color-text-secondary);\n}\n\n.szenen-view .szenen-bausteinleiste__suche {\n min-height: 2.75rem;\n width: 100%;\n box-sizing: border-box;\n}\n\n.szenen-bausteinleiste {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--space-xs);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.szenen-view .szenen-bausteinkachel {\n display: grid;\n gap: 0.25rem;\n width: 100%;\n padding: 0;\n overflow: hidden;\n text-align: left;\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-view .szenen-bausteinkachel[aria-pressed="true"] {\n border-color: var(--color-text-primary);\n}\n\n.szenen-view .szenen-bausteinkachel:disabled {\n cursor: default;\n opacity: 0.7;\n}\n\n.szenen-bausteinkachel__name {\n display: flex;\n align-items: center;\n gap: 0.3rem;\n padding: 0 0.4rem;\n overflow: hidden;\n font-size: 0.8rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-bausteinkachel__status,\n.szenen-bausteinkachel__grund {\n padding: 0 0.4rem 0.4rem;\n color: var(--color-text-secondary);\n font-size: 0.7rem;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n@media (min-width: 761px) {\n .szenen-bausteinleiste {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n}\n/* MCP_STAGE_START: shared stage styles embedded in the gateway resource. */\n/* Issue #569: mobile stage controls and exact camera letterbox. */\n/* 3D-B\xFChne (#569): Ansicht zuerst, Werte als Karten darunter. */\n.szenen-3d {\n display: grid;\n gap: var(--space-md);\n min-width: 0;\n padding: var(--space-md);\n background: var(--color-bg-surface);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-lg);\n}\n\n.szenen-3d__kopf {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n}\n\n.szenen-3d__kopf h4 {\n margin: 0 auto 0 0;\n}\n\n/* Als Ansicht \u201E3D\u201C der Komposition: kein zweiter Rahmen im Abschnitt. */\n.szenen-3d--eingebettet {\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n}\n\n.szenen-3d__kopf {\n flex-wrap: wrap;\n}\n\n.szenen-3d .szenen-3d__aufbau {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n min-width: 0;\n margin-right: auto;\n}\n\n.szenen-3d .szenen-3d__aufbau select {\n width: auto;\n min-width: 0;\n max-width: 100%;\n}\n\n.szenen-3d__stand {\n min-width: 0;\n margin-right: auto;\n color: var(--color-text-secondary);\n font-size: 0.85rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.szenen-3d__sync {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-3d__sync::before {\n width: 0.5rem;\n height: 0.5rem;\n background: var(--color-success);\n border-radius: var(--radius-full);\n content: "";\n}\n\n.szenen-3d__sync[data-state="speichert"]::before {\n background: var(--color-warning);\n}\n\n.szenen-3d__sync[data-state="ansicht"]::before {\n background: var(--color-accent-blue);\n}\n\n.szenen-3d__meldung,\n.szenen-3d__fehler {\n margin: 0;\n padding: var(--space-sm) var(--space-md);\n background: var(--color-bg-elevated);\n border-left: 3px solid var(--color-accent-blue);\n border-radius: var(--radius-sm);\n}\n\n.szenen-3d__fehler {\n border-left-color: var(--color-danger);\n}\n\n.szenen-3d__oeffnen {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-3d label {\n display: grid;\n gap: 0.3rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-3d__leiste {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-sm);\n}\n\n.szenen-3d__katalog {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.35rem;\n}\n\n.szenen-3d__katalog > span {\n margin-right: 0.15rem;\n color: var(--color-text-secondary);\n font-size: 0.8rem;\n}\n\n.szenen-view .szenen-3d__katalog button,\n.szenen-view .szenen-3d__elemente button {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2rem;\n padding: 0 0.7rem;\n border-radius: var(--radius-full);\n font-size: 0.85rem;\n}\n\n.szenen-3d__katalog i,\n.szenen-3d__elemente i {\n flex: none;\n width: 0.6rem;\n height: 0.6rem;\n border-radius: 2px;\n}\n\n.szenen-view .szenen-3d__elemente button[aria-pressed="true"] {\n color: var(--color-text-primary);\n background: var(--color-bg-surface-hover);\n border-color: var(--color-text-primary);\n}\n\n/* Viewport: feste H\xF6he f\xFCr Drauf- und Seitenansicht; die Kameraansicht wird\n * darin auf das gespeicherte Kameraformat eingepasst (Letterbox). */\n.szenen-3d__viewport {\n position: relative;\n display: grid;\n place-items: center;\n /* Dieselbe Gr\xF6\xDFe wie die 2D-B\xFChne (`.szenen-buehne`): Beim Wechsel springt nichts. */\n width: 100%;\n aspect-ratio: 358 / 330;\n overflow: hidden;\n background: #0d0f12;\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n container-type: size;\n outline: none;\n}\n\n.szenen-3d__viewport--laden {\n background:\n linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px) 0 0 / 32px 32px,\n linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px) 0 0 / 32px 32px,\n #0d0f12;\n}\n\n.szenen-3d__geruest {\n display: contents;\n}\n\n.szenen-3d__geruest button {\n pointer-events: none;\n}\n\n.szenen-3d__viewport:focus-visible {\n border-color: var(--color-accent-blue);\n box-shadow: 0 0 0 1px var(--color-accent-blue);\n}\n\n.szenen-3d__surface {\n position: relative;\n width: 100%;\n height: 100%;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.szenen-3d__viewport[data-view="camera"] {\n background: #050607;\n}\n\n.szenen-3d__viewport[data-view="camera"] .szenen-3d__surface {\n width: min(100cqw, calc(100cqh * var(--seitenverhaeltnis)));\n height: min(100cqh, calc(100cqw / var(--seitenverhaeltnis)));\n}\n\n.szenen-3d__hud {\n position: absolute;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n color: #d4d4d4;\n font-size: 0.78rem;\n font-variant-numeric: tabular-nums;\n pointer-events: none;\n}\n\n.szenen-3d__hud--werkzeuge {\n top: 0.6rem;\n right: 0.6rem;\n gap: 0.25rem;\n pointer-events: auto;\n}\n\n.szenen-view .szenen-3d__hud--werkzeuge button {\n min-width: 2rem;\n min-height: 2rem;\n padding: 0 0.6rem;\n color: #e5e5e5;\n background: rgba(23, 23, 23, 0.85);\n border-color: rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(4px);\n}\n\n.szenen-3d__hud--kamera {\n top: 0.6rem;\n left: 0.6rem;\n padding: 0.2rem 0.55rem;\n background: rgba(0, 0, 0, 0.65);\n border-radius: var(--radius-full);\n}\n\n.szenen-3d__hud--info {\n bottom: 0.6rem;\n left: 0.6rem;\n max-width: calc(100% - 7rem);\n padding: 0.25rem 0.6rem;\n background: rgba(0, 0, 0, 0.6);\n border-radius: var(--radius-full);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.szenen-3d__hud--info strong {\n color: #ffffff;\n font-weight: 600;\n}\n\n.szenen-3d__hud i {\n font-style: normal;\n font-weight: 700;\n}\n\n.szenen-3d__hud--achsen {\n right: 0.75rem;\n bottom: 0.7rem;\n gap: 0.6rem;\n font-weight: 700;\n}\n\n.szenen-3d__labels {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n}\n\n.szenen-3d__label {\n position: absolute;\n padding: 0.05rem 0.4rem;\n color: #f5f5f5;\n background: rgba(10, 10, 10, 0.72);\n border-left: 2px solid var(--farbe, #9bafbc);\n border-radius: 3px;\n font: 500 0.72rem/1.4 var(--font-sans);\n white-space: nowrap;\n transform: translate(-50%, 6px);\n}\n\n.szenen-3d__label--side {\n transform: translate(-50%, calc(-100% - 6px));\n}\n\n.szenen-3d__label--kamera {\n color: #bfdbfe;\n border-left-color: #60a5fa;\n transform: translate(14px, -50%);\n}\n\n.szenen-3d__label--kamera.is-links {\n transform: translate(calc(-100% - 14px), -50%);\n}\n\n.szenen-3d__label.is-selected {\n color: #000000;\n background: #ffffff;\n}\n\n.szenen-3d__inspektor {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));\n gap: var(--space-sm);\n}\n\n.szenen-3d__karte {\n display: grid;\n align-content: start;\n gap: var(--space-sm);\n min-width: 0;\n padding: var(--space-sm) var(--space-md) var(--space-md);\n background: var(--color-bg-app);\n border: 1px solid var(--color-border);\n border-radius: var(--radius-md);\n}\n\n.szenen-3d__karte h5 {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.72rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.szenen-3d__elemente {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem;\n}\n\n.szenen-3d__werte {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0.4rem;\n margin: 0;\n padding: 0;\n border: none;\n}\n\n.szenen-3d__werte legend {\n margin-bottom: 0.4rem;\n padding: 0;\n color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-3d__werte legend span {\n margin-left: 0.35rem;\n color: var(--color-text-secondary);\n font-size: 0.78rem;\n font-weight: 400;\n}\n\n.szenen-3d__zeilenkopf {\n grid-column: 1 / -1;\n margin-top: 0.2rem;\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-3d__werte > button {\n grid-column: 1 / -1;\n}\n\n/* Markerfarbe eines Proxys (#587): W\xE4hler, Hexfeld und R\xFCcksetzen in einer\n Zeile; auf schmalem Touch-Viewport bricht sie um, ohne Controls zu verdecken. */\n.szenen-3d__farbe {\n grid-column: 1 / -1;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-view .szenen-3d__farbe input[type="color"] {\n flex: 0 0 auto;\n width: 2.75rem;\n min-height: 2.75rem;\n padding: 0.15rem;\n cursor: pointer;\n}\n\n.szenen-view .szenen-3d__farbe input[type="text"] {\n flex: 1 1 6.5rem;\n min-width: 6.5rem;\n min-height: 2.75rem;\n font-family: var(--font-mono, monospace);\n text-transform: lowercase;\n}\n\n.szenen-view .szenen-3d__farbe button {\n flex: 0 0 auto;\n min-height: 2.75rem;\n}\n\n.szenen-3d__entfernen {\n grid-column: 1 / -1;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.4rem;\n}\n\n.szenen-3d__entfernen > span {\n flex: 1 1 100%;\n color: var(--color-text-primary);\n font-size: 0.85rem;\n}\n\n.szenen-view .szenen-3d__entfernen button {\n min-height: 2.75rem;\n}\n\n.szenen-view .szenen-3d__gefahr {\n color: #fff;\n background: var(--color-danger);\n border-color: var(--color-danger);\n}\n\n.szenen-3d__farbe-auto {\n color: var(--color-text-secondary);\n font-size: 0.75rem;\n}\n\n.szenen-3d__farbe-hinweis {\n grid-column: 1 / -1;\n margin: 0;\n color: var(--color-warning, #eab308);\n font-size: 0.78rem;\n}\n\n.szenen-3d .szenen-3d__feld {\n position: relative;\n display: block;\n}\n\n.szenen-3d__achse {\n position: absolute;\n top: 50%;\n left: 0.55rem;\n font-size: 0.72rem;\n font-weight: 700;\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n.szenen-3d__achse--x { color: #f87171; }\n.szenen-3d__achse--y { color: #4ade80; }\n.szenen-3d__achse--z { color: #60a5fa; }\n\n.szenen-view .szenen-3d__feld input {\n padding-left: 1.6rem;\n font-variant-numeric: tabular-nums;\n}\n\n.szenen-3d__hinweis {\n margin: 0;\n color: var(--color-text-secondary);\n font-size: 0.82rem;\n}\n\n.szenen-3d__abschluss {\n display: grid;\n gap: var(--space-sm);\n}\n\n.szenen-view .szenen-3d__primaer {\n min-height: 2.75rem;\n color: var(--color-bg-app);\n background: var(--color-text-primary);\n border-color: var(--color-text-primary);\n font-weight: 600;\n}\n\n.szenen-view .szenen-3d__primaer:hover:not(:disabled) {\n color: var(--color-bg-app);\n background: var(--color-primary-hover);\n}\n\n.szenen-view .szenen-3d__nebenaktion {\n justify-self: start;\n min-height: 2rem;\n padding: 0;\n background: none;\n border: none;\n font-size: 0.82rem;\n text-decoration: underline;\n}\n\n/* Hinweise passend zum Eingabeger\xE4t; ohne Angabe gilt die Maus-Variante. */\n.szenen-3d__nur-touch {\n display: none;\n}\n\n@media (hover: none) and (pointer: coarse) {\n .szenen-3d__nur-maus {\n display: none;\n }\n\n .szenen-3d__nur-touch {\n display: inline;\n }\n\n /* Fingergerechte Ziele (44 px) f\xFCr Ansichtssteuerung, Katalog und Elemente. */\n .szenen-view .szenen-3d__hud--werkzeuge button,\n .szenen-view .szenen-3d__katalog button,\n .szenen-view .szenen-3d__elemente button,\n .szenen-view .szenen-3d .szenen-studio__umschalter button {\n min-width: 2.75rem;\n min-height: 2.75rem;\n }\n}\n\n@media (max-width: 760px) {\n .szenen-3d {\n gap: var(--space-sm);\n padding: var(--space-sm);\n }\n\n .szenen-3d__leiste {\n display: grid;\n }\n\n .szenen-3d .szenen-studio__umschalter {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n }\n\n /* Katalog als eine Zeile, die in sich scrollt, statt die Ansicht nach unten zu schieben. */\n .szenen-3d__katalog {\n flex-wrap: nowrap;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .szenen-3d__katalog > * {\n flex: none;\n }\n\n .szenen-3d__viewport {\n aspect-ratio: 358 / 330;\n margin: 0 calc(-1 * var(--space-sm));\n border-right: none;\n border-left: none;\n border-radius: 0;\n }\n\n .szenen-3d__hud--info {\n max-width: calc(100% - 1.2rem);\n bottom: 2.4rem;\n }\n\n .szenen-3d__hud--achsen {\n bottom: 0.8rem;\n left: 0.75rem;\n right: auto;\n }\n}\n\n/* One DOM canvas, no nested React renderer. */\n.szenen-3d__canvas { display: block; width: 100%; height: 100%; }\n\n/* Prompt choices before the 3D run; mobile buttons wrap within each category. */\n.szenen-3d__prompt details { margin-block: .65rem; }\n.szenen-3d__prompt summary { cursor: pointer; font-weight: 600; }\n.szenen-3d__prompt fieldset { border: 0; padding: .6rem 0; min-width: 0; }\n.szenen-3d__prompt legend { color: var(--color-text-secondary); font-size: .85rem; }\n.szenen-3d__prompt textarea { min-height: 6rem; width: 100%; box-sizing: border-box; }\n.szenen-3d__referenz { white-space: pre-wrap; overflow-wrap: anywhere; font-size: .9rem; }\n\n/* Das Preview in seinem echten Format (z. B. 4:3) \u2014 keine F\xFCllfl\xE4che in Hintergrundfarbe, die ein Querformat vort\xE4uscht. */\n.szenen-3d__gemini img { display: block; width: auto; max-width: 100%; height: auto; max-height: 28rem; margin-inline: auto; border: 1px solid var(--color-border-hover); border-radius: .4rem; }\n.szenen-3d__gemini pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 32rem; overflow: auto; font-size: .8rem; }\n.szenen-3d__gemini ul { list-style: none; padding: 0; }\n.szenen-3d__gemini li { margin-block: .6rem; overflow-wrap: anywhere; }\n.szenen-3d__gemini li i { display: inline-block; width: .9rem; height: .9rem; margin-right: .4rem; border-radius: .15rem; }\n\n/* Desktop: 2D- und 3D-B\xFChne auf 60 % der Breite, gleich gro\xDF und zentriert.\n Unter 761 px bleibt die volle Breite (Touch, schmale Spalte). Steht am\n Dateiende, damit es die Grundregeln beider B\xFChnen \xFCberschreibt. */\n@media (min-width: 761px) {\n .szenen-buehne,\n .szenen-3d__viewport {\n width: 60%;\n justify-self: center;\n margin-inline: auto;\n }\n}\n\n/* One mobile object sheet and a separate ring gesture on the selected object. */\n.szenen-3d__drehring { position:absolute; overflow:visible; pointer-events:none; z-index:12; }\n.szenen-3d__drehring circle { pointer-events:stroke; cursor:grab; touch-action:none; }\n.szenen-3d__drehring circle:focus-visible { stroke:#ffffff; outline:none; }\n.szenen-3d__blatt-schliessen { display:none; }\n.szenen-3d__objekt-aktionen, .szenen-3d__pose { display:flex; flex-wrap:wrap; gap:.4rem; grid-column:1/-1; }\n.szenen-3d__morph { display:flex; align-items:center; gap:.6rem; grid-column:1/-1; }\n.szenen-3d__morph input { flex:1; min-width:0; min-height:44px; }\n.szenen-3d__pose button[aria-pressed="true"] { border-color:var(--color-accent-blue); }\n@media (max-width:760px) {\n .szenen-3d__objektblatt { position:fixed; left:0; right:0; bottom:0; z-index:50; max-height:42dvh; overflow:auto; overscroll-behavior:contain; background:var(--color-bg-secondary,#15171b); border:1px solid var(--color-border); border-radius:18px 18px 0 0; padding:.7rem 1rem calc(.8rem + env(safe-area-inset-bottom)); box-shadow:0 -8px 30px #0008; }\n .szenen-3d__blatt-schliessen { display:block; margin-left:auto; min-height:44px; }\n .szenen-3d__objektblatt button, .szenen-3d__objektblatt input, .szenen-3d__objektblatt select { min-height:44px; }\n}\n\n.szenen-3d__werte { min-width:0; }\n.szenen-3d__objektblatt input, .szenen-3d__objektblatt select { min-width:0; max-width:100%; }\n\n@media (max-width:760px) { .szenen-3d__objektblatt { width:100vw; max-width:100vw; box-sizing:border-box; } }\n\n.szenen-3d__karte, .szenen-3d__abschluss { grid-template-columns:minmax(0,1fr); }\n\n\n.szenen-3d { overflow-x:clip; }\n\n/* Display options (walls, fullscreen) and the fullscreen stage (#582 follow-up).\n Fullscreen: the stage frame covers the screen; sheets lie over the 3D view. */\n.szenen-3d__ansichtsoptionen { display:flex; flex-wrap:wrap; gap:.4rem; }\n.szenen-view .szenen-3d__ansichtsoptionen button[aria-pressed="true"] { border-color:var(--color-accent-blue); }\n.szenen-3d__buehne { display:grid; gap:var(--space-sm); min-width:0; }\n.szenen-3d__buehne.is-vollbild { position:fixed; inset:0; z-index:1000; display:flex; flex-direction:column; gap:0; background:#0d0f12;\n padding:env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left); }\n/* Two rows, both always visible: the four views, then walls/camera/exit. */\n.szenen-3d__buehne.is-vollbild .szenen-3d__leiste { display:grid; flex:none; gap:.35rem; padding:.4rem; }\n.szenen-3d__buehne.is-vollbild .szenen-studio__umschalter { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); }\n.szenen-3d__buehne.is-vollbild .szenen-studio__umschalter button { min-width:0; padding-inline:.3rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__ansichtsoptionen { display:grid; grid-auto-flow:column; grid-auto-columns:minmax(0,1fr); }\n.szenen-3d__buehne.is-vollbild .szenen-3d__katalog { display:none; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__viewport { flex:1; min-height:0; width:100%; aspect-ratio:auto; margin:0; border:0; border-radius:0; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__objektblatt { position:absolute; left:0; right:0; bottom:0; z-index:20; width:auto; max-width:none; max-height:45%;\n overflow:auto; overscroll-behavior:contain; box-sizing:border-box; background:var(--color-bg-secondary,#15171b); border:1px solid var(--color-border);\n border-radius:18px 18px 0 0; padding:.7rem 1rem calc(.8rem + env(safe-area-inset-bottom)); box-shadow:0 -8px 30px #0008; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__blatt-schliessen { display:block; margin-left:auto; min-height:44px; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__objektblatt button,\n.szenen-3d__buehne.is-vollbild .szenen-3d__objektblatt input,\n.szenen-3d__buehne.is-vollbild .szenen-3d__objektblatt select { min-height:44px; }\n.szenen-3d__kamerablatt label { display:grid; gap:.25rem; grid-column:1/-1; }\n@media (min-width:761px) {\n .szenen-3d__buehne.is-vollbild .szenen-3d__objektblatt { left:auto; top:0; width:min(26rem,40%); max-height:none; border-radius:18px 0 0 18px; }\n}\n\n/* Visibility list and sheet switch (editor display only, never saved).\n "Objektblatt" only matters where the sheet covers the stage: fullscreen and phone width. */\n.szenen-3d__sichtbar { position:relative; min-width:0; }\n.szenen-3d__sichtbar > summary { display:flex; align-items:center; justify-content:center; box-sizing:border-box; height:100%; min-height:2.25rem;\n padding:.45rem .75rem; color:var(--color-text-secondary); background:var(--color-bg-elevated); border:1px solid var(--color-border);\n border-radius:var(--radius-sm); cursor:pointer; list-style:none; text-align:center; }\n.szenen-3d__sichtbar > summary::-webkit-details-marker { display:none; }\n.szenen-3d__sichtbar[open] > summary { border-color:var(--color-accent-blue); color:var(--color-text-primary); }\n.szenen-3d__sichtbar-liste { position:absolute; top:calc(100% + .3rem); left:0; z-index:40; display:grid; gap:.1rem; width:max-content; min-width:14rem;\n max-width:min(22rem,calc(100vw - 1rem)); max-height:60vh; overflow:auto; overscroll-behavior:contain; box-sizing:border-box; padding:.4rem;\n background:var(--color-bg-secondary,#15171b); border:1px solid var(--color-border); border-radius:var(--radius-md); box-shadow:0 8px 30px #0008; }\n.szenen-3d__sichtbar-liste label { display:flex; align-items:center; gap:.5rem; min-height:44px; padding:0 .4rem; cursor:pointer; }\n.szenen-3d__sichtbar-liste input { width:1.15rem; height:1.15rem; margin:0; flex:none; }\n.szenen-3d__sichtbar-liste i { flex:none; width:.6rem; height:.6rem; border-radius:2px; }\n.szenen-3d__sichtbar-liste button { margin-top:.3rem; min-height:44px; }\n.szenen-3d__blatt-schalter { display:none; }\n.szenen-3d__buehne.is-vollbild .szenen-3d__blatt-schalter { display:block; }\n@media (max-width:760px) {\n .szenen-3d__blatt-schalter { display:block; }\n .szenen-3d__objektblatt.is-zu { display:none; }\n}\n\n/* MCP_STAGE_END */\n';
|
|
65
65
|
|
|
66
66
|
// src/lib/utils.ts
|
|
67
67
|
var getFormattedTimestamp = () => {
|
|
@@ -1549,7 +1549,7 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
1549
1549
|
}
|
|
1550
1550
|
|
|
1551
1551
|
// src/components/AvatarArchitectApp.tsx
|
|
1552
|
-
import { useState as
|
|
1552
|
+
import { useState as useState26, useCallback as useCallback4, useMemo as useMemo7, useEffect as useEffect11, useRef as useRef10 } from "react";
|
|
1553
1553
|
|
|
1554
1554
|
// src/components/PromptTab.tsx
|
|
1555
1555
|
import { useRef as useRef5, useState as useState8 } from "react";
|
|
@@ -5530,6 +5530,162 @@ function FlowWorkspacePicker({
|
|
|
5530
5530
|
] }) });
|
|
5531
5531
|
}
|
|
5532
5532
|
|
|
5533
|
+
// src/components/FlowBridgePanel.tsx
|
|
5534
|
+
import { useEffect as useEffect10, useMemo as useMemo6, useState as useState25 } from "react";
|
|
5535
|
+
|
|
5536
|
+
// src/lib/flowBridgeClient.ts
|
|
5537
|
+
var FLOW_BRIDGE_REQUEST_EVENT = "fine-art-flow-bridge:request:v1";
|
|
5538
|
+
var FLOW_BRIDGE_RESPONSE_EVENT = "fine-art-flow-bridge:response:v1";
|
|
5539
|
+
var FLOW_BRIDGE_HELLO_TIMEOUT_MS = 1500;
|
|
5540
|
+
var FLOW_BRIDGE_REQUEST_TIMEOUT_MS = 15e3;
|
|
5541
|
+
function isRecord(value) {
|
|
5542
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5543
|
+
}
|
|
5544
|
+
function readError(value) {
|
|
5545
|
+
if (isRecord(value) && typeof value.code === "string" && typeof value.message === "string") {
|
|
5546
|
+
return { code: value.code, message: value.message };
|
|
5547
|
+
}
|
|
5548
|
+
return { code: "invalid-message", message: "Antwort der Flow-Bridge ohne gueltige Fehlerangabe." };
|
|
5549
|
+
}
|
|
5550
|
+
function noBridge(timeoutMs) {
|
|
5551
|
+
return {
|
|
5552
|
+
code: "no-bridge",
|
|
5553
|
+
message: `Keine Antwort der Flow-Bridge innerhalb von ${timeoutMs} ms \u2014 Extension nicht installiert, deaktiviert oder fuer diesen Frame nicht freigegeben.`
|
|
5554
|
+
};
|
|
5555
|
+
}
|
|
5556
|
+
var nullableNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
5557
|
+
var nextId = 0;
|
|
5558
|
+
function createFlowBridgeClient({
|
|
5559
|
+
target = document,
|
|
5560
|
+
appVersion,
|
|
5561
|
+
helloTimeoutMs = FLOW_BRIDGE_HELLO_TIMEOUT_MS,
|
|
5562
|
+
requestTimeoutMs = FLOW_BRIDGE_REQUEST_TIMEOUT_MS,
|
|
5563
|
+
clock = () => performance.now()
|
|
5564
|
+
} = {}) {
|
|
5565
|
+
function exchange(payload, timeoutMs) {
|
|
5566
|
+
nextId += 1;
|
|
5567
|
+
const id = `fb-${Date.now().toString(36)}-${nextId}`;
|
|
5568
|
+
return new Promise((resolve) => {
|
|
5569
|
+
const onResponse = (event) => {
|
|
5570
|
+
const detail = event.detail;
|
|
5571
|
+
if (typeof detail !== "string") return;
|
|
5572
|
+
let parsed;
|
|
5573
|
+
try {
|
|
5574
|
+
parsed = JSON.parse(detail);
|
|
5575
|
+
} catch {
|
|
5576
|
+
return;
|
|
5577
|
+
}
|
|
5578
|
+
if (!isRecord(parsed) || parsed.id !== id) return;
|
|
5579
|
+
cleanup();
|
|
5580
|
+
resolve(parsed);
|
|
5581
|
+
};
|
|
5582
|
+
const timer = setTimeout(() => {
|
|
5583
|
+
cleanup();
|
|
5584
|
+
resolve(null);
|
|
5585
|
+
}, timeoutMs);
|
|
5586
|
+
const cleanup = () => {
|
|
5587
|
+
clearTimeout(timer);
|
|
5588
|
+
target.removeEventListener(FLOW_BRIDGE_RESPONSE_EVENT, onResponse);
|
|
5589
|
+
};
|
|
5590
|
+
target.addEventListener(FLOW_BRIDGE_RESPONSE_EVENT, onResponse);
|
|
5591
|
+
target.dispatchEvent(new CustomEvent(FLOW_BRIDGE_REQUEST_EVENT, { detail: JSON.stringify({ id, ...payload }) }));
|
|
5592
|
+
});
|
|
5593
|
+
}
|
|
5594
|
+
return {
|
|
5595
|
+
async status() {
|
|
5596
|
+
const started = clock();
|
|
5597
|
+
const reply = await exchange({ op: "hello", app: "flowfa", ...appVersion ? { appVersion } : {} }, helloTimeoutMs);
|
|
5598
|
+
const roundTripMs = Math.round(clock() - started);
|
|
5599
|
+
if (!reply) return { available: false, error: noBridge(helloTimeoutMs), roundTripMs };
|
|
5600
|
+
if (reply.ok !== true) return { available: false, error: readError(reply.error), roundTripMs };
|
|
5601
|
+
const bridge = reply.bridge;
|
|
5602
|
+
if (!isRecord(bridge) || typeof bridge.name !== "string" || typeof bridge.version !== "string" || typeof bridge.protocol !== "number") {
|
|
5603
|
+
return { available: false, error: { code: "invalid-message", message: "Handshake-Antwort ohne Bridge-Kennung." }, roundTripMs };
|
|
5604
|
+
}
|
|
5605
|
+
return { available: true, name: bridge.name, version: bridge.version, protocol: bridge.protocol, roundTripMs };
|
|
5606
|
+
},
|
|
5607
|
+
async request(request) {
|
|
5608
|
+
const started = clock();
|
|
5609
|
+
const reply = await exchange({ op: "request", target: request.target, method: request.method, path: request.path }, requestTimeoutMs);
|
|
5610
|
+
const roundTripMs = Math.round(clock() - started);
|
|
5611
|
+
if (!reply) {
|
|
5612
|
+
return { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs, error: noBridge(requestTimeoutMs) };
|
|
5613
|
+
}
|
|
5614
|
+
const ok = reply.ok === true;
|
|
5615
|
+
return {
|
|
5616
|
+
ok,
|
|
5617
|
+
transport: typeof reply.transport === "string" ? reply.transport : null,
|
|
5618
|
+
status: nullableNumber(reply.status),
|
|
5619
|
+
data: ok ? reply.data ?? null : null,
|
|
5620
|
+
latencyMs: nullableNumber(reply.latencyMs),
|
|
5621
|
+
roundTripMs,
|
|
5622
|
+
error: ok ? null : readError(reply.error)
|
|
5623
|
+
};
|
|
5624
|
+
}
|
|
5625
|
+
};
|
|
5626
|
+
}
|
|
5627
|
+
|
|
5628
|
+
// src/components/FlowBridgePanel.tsx
|
|
5629
|
+
import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5630
|
+
var STATUS_REQUEST = { target: "dev", method: "GET", path: "/api/status" };
|
|
5631
|
+
var FlowBridgePanel = ({ appVersion, client }) => {
|
|
5632
|
+
const bridge = useMemo6(() => client ?? createFlowBridgeClient({ appVersion }), [client, appVersion]);
|
|
5633
|
+
const [status, setStatus] = useState25(null);
|
|
5634
|
+
const [response, setResponse] = useState25(null);
|
|
5635
|
+
const [busy, setBusy] = useState25(null);
|
|
5636
|
+
const checkStatus = async () => {
|
|
5637
|
+
setBusy("status");
|
|
5638
|
+
try {
|
|
5639
|
+
setStatus(await bridge.status());
|
|
5640
|
+
} finally {
|
|
5641
|
+
setBusy(null);
|
|
5642
|
+
}
|
|
5643
|
+
};
|
|
5644
|
+
useEffect10(() => {
|
|
5645
|
+
let active = true;
|
|
5646
|
+
void bridge.status().then((result) => {
|
|
5647
|
+
if (active) setStatus(result);
|
|
5648
|
+
});
|
|
5649
|
+
return () => {
|
|
5650
|
+
active = false;
|
|
5651
|
+
};
|
|
5652
|
+
}, [bridge]);
|
|
5653
|
+
const runRequest = async () => {
|
|
5654
|
+
setBusy("request");
|
|
5655
|
+
setResponse(null);
|
|
5656
|
+
try {
|
|
5657
|
+
setResponse(await bridge.request(STATUS_REQUEST));
|
|
5658
|
+
} finally {
|
|
5659
|
+
setBusy(null);
|
|
5660
|
+
}
|
|
5661
|
+
};
|
|
5662
|
+
const buttonStyle = {
|
|
5663
|
+
height: 36,
|
|
5664
|
+
border: "1px solid rgba(255,255,255,0.12)",
|
|
5665
|
+
color: "rgba(255,255,255,0.7)",
|
|
5666
|
+
background: "rgba(255,255,255,0.04)"
|
|
5667
|
+
};
|
|
5668
|
+
return /* @__PURE__ */ jsxs27("details", { className: "w-full max-w-[280px] rounded-xl px-3 py-2", style: { border: "1px solid rgba(255,255,255,0.08)" }, children: [
|
|
5669
|
+
/* @__PURE__ */ jsx29("summary", { className: "text-white/40 text-[10px] uppercase tracking-widest font-bold cursor-pointer", children: "Flow-Bridge (Firefox)" }),
|
|
5670
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-2 mt-2 text-[10px] font-mono", children: [
|
|
5671
|
+
/* @__PURE__ */ jsxs27("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
5672
|
+
/* @__PURE__ */ jsx29("button", { type: "button", onClick: checkStatus, disabled: busy !== null, className: "rounded-lg text-[11px] font-bold disabled:opacity-40", style: buttonStyle, children: busy === "status" ? "Pr\xFCfe\u2026" : "Bridge pr\xFCfen" }),
|
|
5673
|
+
/* @__PURE__ */ jsx29("button", { type: "button", onClick: runRequest, disabled: busy !== null, className: "rounded-lg text-[11px] font-bold disabled:opacity-40", style: buttonStyle, children: busy === "request" ? "L\xE4uft\u2026" : "Dev /api/status" })
|
|
5674
|
+
] }),
|
|
5675
|
+
status && /* @__PURE__ */ jsx29("div", { role: "status", "data-testid": "flow-bridge-status", style: { color: status.available ? "#4ade80" : "#f87171" }, children: status.available ? `Bridge: verbunden \xB7 ${status.name} v${status.version} \xB7 Protokoll ${status.protocol} \xB7 ${status.roundTripMs} ms` : `Bridge: nicht verbunden \xB7 ${status.error.code}: ${status.error.message}` }),
|
|
5676
|
+
response && /* @__PURE__ */ jsxs27("div", { "data-testid": "flow-bridge-response", className: "flex flex-col gap-1", children: [
|
|
5677
|
+
/* @__PURE__ */ jsxs27("span", { style: { color: response.ok ? "#4ade80" : "#f87171" }, children: [
|
|
5678
|
+
`${STATUS_REQUEST.method} ${STATUS_REQUEST.path} (${STATUS_REQUEST.target}) \u2192 `,
|
|
5679
|
+
response.status !== null ? `HTTP ${response.status}` : "kein HTTP-Status",
|
|
5680
|
+
response.ok ? "" : ` \xB7 ${response.error?.code}: ${response.error?.message}`
|
|
5681
|
+
] }),
|
|
5682
|
+
/* @__PURE__ */ jsx29("span", { className: "text-white/40", children: `Transport: ${response.transport ?? "keiner"} \xB7 Server ${response.latencyMs ?? "\u2014"} ms \xB7 gesamt ${response.roundTripMs} ms` }),
|
|
5683
|
+
response.ok && /* @__PURE__ */ jsx29("pre", { className: "text-white/60 whitespace-pre-wrap break-all bg-black/30 rounded-lg p-2", children: JSON.stringify(response.data, null, 2) })
|
|
5684
|
+
] })
|
|
5685
|
+
] })
|
|
5686
|
+
] });
|
|
5687
|
+
};
|
|
5688
|
+
|
|
5533
5689
|
// src/lib/flowBootstrapTarget.ts
|
|
5534
5690
|
var PROD_NAMESPACE = "app.art-by-rolands.de/";
|
|
5535
5691
|
var DEV_NAMESPACE = "dev-app.art-by-rolands.de/";
|
|
@@ -5582,9 +5738,9 @@ function resolveBootstrapTarget(input) {
|
|
|
5582
5738
|
}
|
|
5583
5739
|
|
|
5584
5740
|
// src/components/AvatarArchitectApp.tsx
|
|
5585
|
-
import { Fragment as Fragment10, jsx as
|
|
5741
|
+
import { Fragment as Fragment10, jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
5586
5742
|
function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, initialHfToken, hfNamespace, allowDevNamespace, requireWorkspaceSelection = false, serverBaseUrl }) {
|
|
5587
|
-
|
|
5743
|
+
useEffect11(() => {
|
|
5588
5744
|
const id = "flow-styles";
|
|
5589
5745
|
if (!document.getElementById(id)) {
|
|
5590
5746
|
const style = document.createElement("style");
|
|
@@ -5593,33 +5749,33 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5593
5749
|
document.head.appendChild(style);
|
|
5594
5750
|
}
|
|
5595
5751
|
}, []);
|
|
5596
|
-
const [showStart, setShowStart] =
|
|
5597
|
-
const [layoutChoice, setLayoutChoice] =
|
|
5752
|
+
const [showStart, setShowStart] = useState26(true);
|
|
5753
|
+
const [layoutChoice, setLayoutChoice] = useState26(() => {
|
|
5598
5754
|
try {
|
|
5599
5755
|
return localStorage.getItem("aa-layout") || null;
|
|
5600
5756
|
} catch {
|
|
5601
5757
|
return null;
|
|
5602
5758
|
}
|
|
5603
5759
|
});
|
|
5604
|
-
const [hfToken, setHfToken] =
|
|
5605
|
-
const [hfTokenInput, setHfTokenInput] =
|
|
5606
|
-
const [hfNamespaceLocal, setHfNamespaceLocal] =
|
|
5760
|
+
const [hfToken, setHfToken] = useState26(initialHfToken || "");
|
|
5761
|
+
const [hfTokenInput, setHfTokenInput] = useState26(initialHfToken || "");
|
|
5762
|
+
const [hfNamespaceLocal, setHfNamespaceLocal] = useState26(() => {
|
|
5607
5763
|
try {
|
|
5608
5764
|
return normalizeSelectableNamespace(localStorage.getItem("aa-hf-namespace"));
|
|
5609
5765
|
} catch {
|
|
5610
5766
|
return DEFAULT_NAMESPACE;
|
|
5611
5767
|
}
|
|
5612
5768
|
});
|
|
5613
|
-
const [hfNamespaceFromServer, setHfNamespaceFromServer] =
|
|
5614
|
-
const [serverProbeFailed, setServerProbeFailed] =
|
|
5615
|
-
|
|
5769
|
+
const [hfNamespaceFromServer, setHfNamespaceFromServer] = useState26(null);
|
|
5770
|
+
const [serverProbeFailed, setServerProbeFailed] = useState26(false);
|
|
5771
|
+
useEffect11(() => {
|
|
5616
5772
|
if (hfNamespace !== void 0 || !serverBaseUrl) return;
|
|
5617
5773
|
fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
|
|
5618
5774
|
if (typeof d.hfNamespace === "string" && d.hfNamespace) setHfNamespaceFromServer(d.hfNamespace);
|
|
5619
5775
|
else setServerProbeFailed(true);
|
|
5620
5776
|
}).catch(() => setServerProbeFailed(true));
|
|
5621
5777
|
}, [hfNamespace, serverBaseUrl]);
|
|
5622
|
-
const [targetConfirmed, setTargetConfirmed] =
|
|
5778
|
+
const [targetConfirmed, setTargetConfirmed] = useState26(false);
|
|
5623
5779
|
const isDialogTarget = hfNamespace === void 0 && hfNamespaceFromServer === null && (!serverBaseUrl || serverProbeFailed);
|
|
5624
5780
|
const isProbingServer = hfNamespace === void 0 && !!serverBaseUrl && hfNamespaceFromServer === null && !serverProbeFailed;
|
|
5625
5781
|
const bootstrapTarget = resolveBootstrapTarget({
|
|
@@ -5631,7 +5787,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5631
5787
|
});
|
|
5632
5788
|
const effectiveNamespace = bootstrapTarget.namespace ?? "";
|
|
5633
5789
|
const kontextRef = useRef10(null);
|
|
5634
|
-
const szenenPort =
|
|
5790
|
+
const szenenPort = useMemo7(() => hfToken && effectiveNamespace ? createFlowSzenenViewPort({
|
|
5635
5791
|
generateText: onGeneratePrompt,
|
|
5636
5792
|
token: hfToken,
|
|
5637
5793
|
namespace: effectiveNamespace,
|
|
@@ -5653,36 +5809,36 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5653
5809
|
const tagBaseResult = useTagBase(hfToken, effectiveNamespace);
|
|
5654
5810
|
const szenenKontextId = tagBaseResult.selectedContextId === null ? null : String(tagBaseResult.selectedContextId);
|
|
5655
5811
|
kontextRef.current = szenenKontextId;
|
|
5656
|
-
const [imageUploadStatus, setImageUploadStatus] =
|
|
5657
|
-
const [bootstrapLog, setBootstrapLog] =
|
|
5658
|
-
const [isBootstrapping, setIsBootstrapping] =
|
|
5659
|
-
const [hfMissingImages, setHfMissingImages] =
|
|
5660
|
-
const syncTopSlot = /* @__PURE__ */
|
|
5661
|
-
localOnlyCount > 0 && /* @__PURE__ */
|
|
5812
|
+
const [imageUploadStatus, setImageUploadStatus] = useState26(/* @__PURE__ */ new Map());
|
|
5813
|
+
const [bootstrapLog, setBootstrapLog] = useState26([]);
|
|
5814
|
+
const [isBootstrapping, setIsBootstrapping] = useState26(false);
|
|
5815
|
+
const [hfMissingImages, setHfMissingImages] = useState26([]);
|
|
5816
|
+
const syncTopSlot = /* @__PURE__ */ jsxs28(Fragment10, { children: [
|
|
5817
|
+
localOnlyCount > 0 && /* @__PURE__ */ jsxs28("div", { style: { background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", padding: "4px 10px", fontSize: 11, color: "#fbbf24", borderRadius: 4, marginBottom: 4 }, children: [
|
|
5662
5818
|
"\u26A0 ",
|
|
5663
5819
|
localOnlyCount,
|
|
5664
5820
|
" lokale Event",
|
|
5665
5821
|
localOnlyCount > 1 ? "s" : "",
|
|
5666
5822
|
" noch nicht auf HF best\xE4tigt"
|
|
5667
5823
|
] }),
|
|
5668
|
-
pendingBufferCount > 0 && /* @__PURE__ */
|
|
5824
|
+
pendingBufferCount > 0 && /* @__PURE__ */ jsxs28("div", { style: { background: "linear-gradient(90deg,#f59e0b,#ef4444)", padding: "4px 10px", fontSize: 11, color: "#fff", borderRadius: 4, marginBottom: 4 }, children: [
|
|
5669
5825
|
pendingBufferCount,
|
|
5670
5826
|
" \xC4nderung",
|
|
5671
5827
|
pendingBufferCount > 1 ? "en" : "",
|
|
5672
5828
|
" lokal \u2014 bei Flow-Reload verloren wenn nicht synchronisiert"
|
|
5673
5829
|
] }),
|
|
5674
|
-
eventCount > 100 && /* @__PURE__ */
|
|
5830
|
+
eventCount > 100 && /* @__PURE__ */ jsxs28("div", { style: { background: "#dc2626", color: "#fff", padding: "5px 10px", borderRadius: 4, marginBottom: 4, fontWeight: 600, fontSize: 11 }, children: [
|
|
5675
5831
|
"\u26A0 ",
|
|
5676
5832
|
eventCount,
|
|
5677
5833
|
" Events nicht konsolidiert \u2014 Konsolidierung dringend empfohlen"
|
|
5678
5834
|
] }),
|
|
5679
|
-
eventCount > 50 && eventCount <= 100 && /* @__PURE__ */
|
|
5835
|
+
eventCount > 50 && eventCount <= 100 && /* @__PURE__ */ jsxs28("div", { style: { background: "#44403c", color: "#a8a29e", padding: "4px 10px", borderRadius: 4, marginBottom: 4, fontSize: 11 }, children: [
|
|
5680
5836
|
eventCount,
|
|
5681
5837
|
" Events seit letzter Konsolidierung \u2014 Konsolidierung empfohlen"
|
|
5682
5838
|
] }),
|
|
5683
|
-
hfToken && !hasStateZip && !isHfRefreshing && /* @__PURE__ */
|
|
5684
|
-
/* @__PURE__ */
|
|
5685
|
-
/* @__PURE__ */
|
|
5839
|
+
hfToken && !hasStateZip && !isHfRefreshing && /* @__PURE__ */ jsxs28("div", { style: { background: "#1c1917", border: "1px solid #44403c", borderRadius: 6, padding: "10px 12px" }, children: [
|
|
5840
|
+
/* @__PURE__ */ jsx30("div", { style: { fontSize: 12, color: "#a8a29e", marginBottom: 6 }, children: effectiveNamespace ? `Kein State-Snapshot in HF (${effectiveNamespace}) \u2014 aus Legacy-Daten (tags.json + metadata.json) migrieren?` : "Namespace wird geladen\u2026" }),
|
|
5841
|
+
/* @__PURE__ */ jsx30(
|
|
5686
5842
|
"button",
|
|
5687
5843
|
{
|
|
5688
5844
|
disabled: isBootstrapping || !effectiveNamespace,
|
|
@@ -5703,7 +5859,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5703
5859
|
children: isBootstrapping ? "Migriere\u2026" : "Legacy-Migration starten"
|
|
5704
5860
|
}
|
|
5705
5861
|
),
|
|
5706
|
-
bootstrapLog.length > 0 && /* @__PURE__ */
|
|
5862
|
+
bootstrapLog.length > 0 && /* @__PURE__ */ jsx30("div", { style: { marginTop: 6, fontFamily: "monospace", fontSize: 10, color: "#78716c", lineHeight: 1.6 }, children: bootstrapLog.map((l, i) => /* @__PURE__ */ jsx30("div", { children: l }, i)) })
|
|
5707
5863
|
] })
|
|
5708
5864
|
] });
|
|
5709
5865
|
const startApp = (choice) => {
|
|
@@ -5715,17 +5871,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5715
5871
|
setTargetConfirmed(true);
|
|
5716
5872
|
setShowStart(false);
|
|
5717
5873
|
};
|
|
5718
|
-
const [nodes, setNodes] =
|
|
5719
|
-
const [edges, setEdges] =
|
|
5720
|
-
const [history, setHistory] =
|
|
5721
|
-
const [galleryItems, setGalleryItems] =
|
|
5874
|
+
const [nodes, setNodes] = useState26([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
|
|
5875
|
+
const [edges, setEdges] = useState26([]);
|
|
5876
|
+
const [history, setHistory] = useState26([]);
|
|
5877
|
+
const [galleryItems, setGalleryItems] = useState26([]);
|
|
5722
5878
|
const galleryItemsRef = useRef10([]);
|
|
5723
|
-
|
|
5879
|
+
useEffect11(() => {
|
|
5724
5880
|
galleryItemsRef.current = galleryItems;
|
|
5725
5881
|
}, [galleryItems]);
|
|
5726
5882
|
const hfImageNotFoundRef = useRef10(/* @__PURE__ */ new Map());
|
|
5727
|
-
const [galleryVisibleCount, setGalleryVisibleCount] =
|
|
5728
|
-
const [historyVisibleCount, setHistoryVisibleCount] =
|
|
5883
|
+
const [galleryVisibleCount, setGalleryVisibleCount] = useState26(20);
|
|
5884
|
+
const [historyVisibleCount, setHistoryVisibleCount] = useState26(20);
|
|
5729
5885
|
const hfInFlightRef = useRef10(/* @__PURE__ */ new Set());
|
|
5730
5886
|
const loadThumbnailsForEntries = useCallback4(async (entries) => {
|
|
5731
5887
|
await loadThumbnailsSequentially(entries, {
|
|
@@ -5747,7 +5903,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5747
5903
|
}
|
|
5748
5904
|
});
|
|
5749
5905
|
}, [hfToken, effectiveNamespace]);
|
|
5750
|
-
|
|
5906
|
+
useEffect11(() => {
|
|
5751
5907
|
if (!hfState) return;
|
|
5752
5908
|
if (hfState.tags?.by_category) setWorkspaceTags(hfState.tags);
|
|
5753
5909
|
const hfIds = new Set(hfState.metadata.map((m) => m.id));
|
|
@@ -5774,24 +5930,24 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5774
5930
|
return [...localOnly, ...merged].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
|
|
5775
5931
|
});
|
|
5776
5932
|
}, [hfState]);
|
|
5777
|
-
const [activePrompt, setActivePrompt] =
|
|
5778
|
-
const [isSynthesizing, setIsSynthesizing] =
|
|
5779
|
-
const [activeGenerationsCount, setActiveGenerationsCount] =
|
|
5780
|
-
const [currentResult, setCurrentResult] =
|
|
5781
|
-
const [focusedNodeId, setFocusedNodeId] =
|
|
5782
|
-
const [leftTab, setLeftTab] =
|
|
5783
|
-
const [promptFeedback, setPromptFeedback] =
|
|
5784
|
-
const [lastPromptPayload, setLastPromptPayload] =
|
|
5785
|
-
const [isPromptTabGenerating, setIsPromptTabGenerating] =
|
|
5786
|
-
const [activeTab, setActiveTab] =
|
|
5787
|
-
const [mobileTab, setMobileTab] =
|
|
5788
|
-
const [middlePanel, setMiddlePanel] =
|
|
5789
|
-
const [recentLabItems, setRecentLabItems] =
|
|
5790
|
-
const [aspectRatio, setAspectRatio] =
|
|
5791
|
-
const [selectedModel, setSelectedModel] =
|
|
5792
|
-
const [seed, setSeed] =
|
|
5793
|
-
const [seedMode, setSeedMode] =
|
|
5794
|
-
const [imageCount, setImageCount] =
|
|
5933
|
+
const [activePrompt, setActivePrompt] = useState26("");
|
|
5934
|
+
const [isSynthesizing, setIsSynthesizing] = useState26(false);
|
|
5935
|
+
const [activeGenerationsCount, setActiveGenerationsCount] = useState26(0);
|
|
5936
|
+
const [currentResult, setCurrentResult] = useState26(null);
|
|
5937
|
+
const [focusedNodeId, setFocusedNodeId] = useState26(null);
|
|
5938
|
+
const [leftTab, setLeftTab] = useState26("prompt");
|
|
5939
|
+
const [promptFeedback, setPromptFeedback] = useState26(null);
|
|
5940
|
+
const [lastPromptPayload, setLastPromptPayload] = useState26(null);
|
|
5941
|
+
const [isPromptTabGenerating, setIsPromptTabGenerating] = useState26(false);
|
|
5942
|
+
const [activeTab, setActiveTab] = useState26("history");
|
|
5943
|
+
const [mobileTab, setMobileTab] = useState26("stage");
|
|
5944
|
+
const [middlePanel, setMiddlePanel] = useState26("stage");
|
|
5945
|
+
const [recentLabItems, setRecentLabItems] = useState26([]);
|
|
5946
|
+
const [aspectRatio, setAspectRatio] = useState26("1:1");
|
|
5947
|
+
const [selectedModel, setSelectedModel] = useState26("\u{1F34C} Nano Banana Pro");
|
|
5948
|
+
const [seed, setSeed] = useState26(Math.floor(Math.random() * 1e6));
|
|
5949
|
+
const [seedMode, setSeedMode] = useState26("random");
|
|
5950
|
+
const [imageCount, setImageCount] = useState26(() => {
|
|
5795
5951
|
try {
|
|
5796
5952
|
const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
|
|
5797
5953
|
return v >= 1 && v <= 8 ? v : 4;
|
|
@@ -5813,38 +5969,38 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5813
5969
|
{ label: "4 Bilder", value: "4" },
|
|
5814
5970
|
{ label: "8 Bilder", value: "8" }
|
|
5815
5971
|
];
|
|
5816
|
-
const [isLeftCollapsed, setIsLeftCollapsed] =
|
|
5817
|
-
const [isRightCollapsed, setIsRightCollapsed] =
|
|
5818
|
-
const [leftPanelWidth, setLeftPanelWidth] =
|
|
5972
|
+
const [isLeftCollapsed, setIsLeftCollapsed] = useState26(false);
|
|
5973
|
+
const [isRightCollapsed, setIsRightCollapsed] = useState26(false);
|
|
5974
|
+
const [leftPanelWidth, setLeftPanelWidth] = useState26(() => {
|
|
5819
5975
|
try {
|
|
5820
5976
|
return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
|
|
5821
5977
|
} catch {
|
|
5822
5978
|
return 260;
|
|
5823
5979
|
}
|
|
5824
5980
|
});
|
|
5825
|
-
const [rightPanelWidth, setRightPanelWidth] =
|
|
5981
|
+
const [rightPanelWidth, setRightPanelWidth] = useState26(() => {
|
|
5826
5982
|
try {
|
|
5827
5983
|
return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
|
|
5828
5984
|
} catch {
|
|
5829
5985
|
return 320;
|
|
5830
5986
|
}
|
|
5831
5987
|
});
|
|
5832
|
-
const [isPromptCollapsed, setIsPromptCollapsed] =
|
|
5833
|
-
const [workspaceTags, setWorkspaceTags] =
|
|
5834
|
-
const [highContrast, setHighContrast] =
|
|
5988
|
+
const [isPromptCollapsed, setIsPromptCollapsed] = useState26(false);
|
|
5989
|
+
const [workspaceTags, setWorkspaceTags] = useState26(null);
|
|
5990
|
+
const [highContrast, setHighContrast] = useState26(() => {
|
|
5835
5991
|
try {
|
|
5836
5992
|
return localStorage.getItem("aa-contrast") === "high";
|
|
5837
5993
|
} catch {
|
|
5838
5994
|
return false;
|
|
5839
5995
|
}
|
|
5840
5996
|
});
|
|
5841
|
-
const [activeReferenceId, setActiveReferenceId] =
|
|
5842
|
-
const [activeReferenceThumbnail, setActiveReferenceThumbnail] =
|
|
5843
|
-
const [isScanningImage, setIsScanningImage] =
|
|
5844
|
-
const [touchStartX, setTouchStartX] =
|
|
5845
|
-
const [isFullscreen, setIsFullscreen] =
|
|
5846
|
-
const [zoomScale, setZoomScale] =
|
|
5847
|
-
const [zoomOffset, setZoomOffset] =
|
|
5997
|
+
const [activeReferenceId, setActiveReferenceId] = useState26(null);
|
|
5998
|
+
const [activeReferenceThumbnail, setActiveReferenceThumbnail] = useState26(null);
|
|
5999
|
+
const [isScanningImage, setIsScanningImage] = useState26(false);
|
|
6000
|
+
const [touchStartX, setTouchStartX] = useState26(null);
|
|
6001
|
+
const [isFullscreen, setIsFullscreen] = useState26(false);
|
|
6002
|
+
const [zoomScale, setZoomScale] = useState26(1);
|
|
6003
|
+
const [zoomOffset, setZoomOffset] = useState26({ x: 0, y: 0 });
|
|
5848
6004
|
const { historyVisible, galleryVisible } = computePrefetchVisibility({
|
|
5849
6005
|
layoutChoice,
|
|
5850
6006
|
appShellVisible: !showStart && !requireWorkspaceSelection && !(isFullscreen && !!currentResult?.base64),
|
|
@@ -5926,7 +6082,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
5926
6082
|
setActiveReferenceId(null);
|
|
5927
6083
|
setActiveReferenceThumbnail(null);
|
|
5928
6084
|
};
|
|
5929
|
-
const labServices =
|
|
6085
|
+
const labServices = useMemo7(() => {
|
|
5930
6086
|
const available = groupGenerationsToLabItems([...galleryItems, ...history]);
|
|
5931
6087
|
return {
|
|
5932
6088
|
availableItems: available,
|
|
@@ -6006,7 +6162,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6006
6162
|
setIsScanningImage(false);
|
|
6007
6163
|
}
|
|
6008
6164
|
};
|
|
6009
|
-
const currentIndex =
|
|
6165
|
+
const currentIndex = useMemo7(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
|
|
6010
6166
|
const goToPrev = useCallback4(() => {
|
|
6011
6167
|
if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
|
|
6012
6168
|
}, [currentIndex, history]);
|
|
@@ -6035,13 +6191,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6035
6191
|
});
|
|
6036
6192
|
}
|
|
6037
6193
|
}, [hfToken, effectiveNamespace, hfWriteEvent]);
|
|
6038
|
-
const currentGroup =
|
|
6194
|
+
const currentGroup = useMemo7(() => {
|
|
6039
6195
|
if (!currentResult?.prompt) return [];
|
|
6040
6196
|
const groups = groupByPrompt(galleryItems.filter((g) => g.status === "done" && !!g.base64));
|
|
6041
6197
|
const group = groups.find((gr) => gr.prompt === currentResult.prompt);
|
|
6042
6198
|
return group ? group.items : [];
|
|
6043
6199
|
}, [galleryItems, currentResult?.prompt]);
|
|
6044
|
-
|
|
6200
|
+
useEffect11(() => {
|
|
6045
6201
|
if (!currentResult?.prompt || !hfToken || !effectiveNamespace || !hfState) return;
|
|
6046
6202
|
const siblings = galleryItemsRef.current.filter(
|
|
6047
6203
|
(g) => g.prompt === currentResult.prompt && !g.base64 && !hfImageNotFoundRef.current.has(g.id)
|
|
@@ -6067,15 +6223,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6067
6223
|
})();
|
|
6068
6224
|
}, [currentResult?.id, currentResult?.prompt]);
|
|
6069
6225
|
const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
|
|
6070
|
-
const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */
|
|
6226
|
+
const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ jsxs28(
|
|
6071
6227
|
"div",
|
|
6072
6228
|
{
|
|
6073
6229
|
className: "flex items-center gap-1 rounded-full bg-sky-500/15 border border-sky-400/30 px-2 shrink-0",
|
|
6074
6230
|
style: { height: 24 },
|
|
6075
6231
|
title: `${activeGenerationsCount} Generierung${activeGenerationsCount === 1 ? "" : "en"} l\xE4uft gerade`,
|
|
6076
6232
|
children: [
|
|
6077
|
-
/* @__PURE__ */
|
|
6078
|
-
/* @__PURE__ */
|
|
6233
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-sky-300", style: { fontSize: 14, lineHeight: 1 }, children: "autorenew" }),
|
|
6234
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[11px] font-bold text-sky-300 tabular-nums", children: activeGenerationsCount })
|
|
6079
6235
|
]
|
|
6080
6236
|
}
|
|
6081
6237
|
) : null;
|
|
@@ -6088,7 +6244,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6088
6244
|
return `${indent}- ${node.data.label || "(unbenannt)"}
|
|
6089
6245
|
` + childrenIds.map((id) => getSubtreeFormat(id, depth + 1)).join("");
|
|
6090
6246
|
}, [nodes, edges]);
|
|
6091
|
-
const activePath =
|
|
6247
|
+
const activePath = useMemo7(() => {
|
|
6092
6248
|
if (!focusedNodeId) return /* @__PURE__ */ new Set();
|
|
6093
6249
|
const path = /* @__PURE__ */ new Set([focusedNodeId]);
|
|
6094
6250
|
let currId = focusedNodeId;
|
|
@@ -6364,7 +6520,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6364
6520
|
if (isFullscreen && currentResult?.base64) {
|
|
6365
6521
|
const fsRaw = currentResult.fullBase64 || currentResult.base64;
|
|
6366
6522
|
const fsBase64 = fsRaw.startsWith("data:") ? fsRaw : `data:image/png;base64,${fsRaw}`;
|
|
6367
|
-
return /* @__PURE__ */
|
|
6523
|
+
return /* @__PURE__ */ jsxs28(
|
|
6368
6524
|
"div",
|
|
6369
6525
|
{
|
|
6370
6526
|
className: "fixed inset-0 bg-black z-50 flex items-center justify-center overflow-hidden touch-none",
|
|
@@ -6372,7 +6528,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6372
6528
|
onTouchMove: handleFsTouchMove,
|
|
6373
6529
|
onTouchEnd: handleFsTouchEnd,
|
|
6374
6530
|
children: [
|
|
6375
|
-
/* @__PURE__ */
|
|
6531
|
+
/* @__PURE__ */ jsx30(
|
|
6376
6532
|
"img",
|
|
6377
6533
|
{
|
|
6378
6534
|
src: fsBase64,
|
|
@@ -6389,57 +6545,57 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6389
6545
|
}
|
|
6390
6546
|
}
|
|
6391
6547
|
),
|
|
6392
|
-
/* @__PURE__ */
|
|
6393
|
-
zoomScale > 1 && /* @__PURE__ */
|
|
6548
|
+
/* @__PURE__ */ jsx30("button", { onClick: closeFullscreen, className: "absolute top-4 right-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", children: "close" }) }),
|
|
6549
|
+
zoomScale > 1 && /* @__PURE__ */ jsx30("button", { onClick: () => {
|
|
6394
6550
|
setZoomScale(1);
|
|
6395
6551
|
setZoomOffset({ x: 0, y: 0 });
|
|
6396
|
-
}, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */
|
|
6397
|
-
history.length > 1 && /* @__PURE__ */
|
|
6398
|
-
/* @__PURE__ */
|
|
6552
|
+
}, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "zoom_out_map" }) }),
|
|
6553
|
+
history.length > 1 && /* @__PURE__ */ jsxs28(Fragment10, { children: [
|
|
6554
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => {
|
|
6399
6555
|
if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
|
|
6400
|
-
}, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */
|
|
6401
|
-
/* @__PURE__ */
|
|
6556
|
+
}, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
|
|
6557
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => {
|
|
6402
6558
|
if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
|
|
6403
|
-
}, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */
|
|
6404
|
-
/* @__PURE__ */
|
|
6559
|
+
}, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
|
|
6560
|
+
/* @__PURE__ */ jsxs28("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
|
|
6405
6561
|
currentIndex + 1,
|
|
6406
6562
|
" / ",
|
|
6407
6563
|
history.length
|
|
6408
6564
|
] })
|
|
6409
6565
|
] }),
|
|
6410
|
-
zoomScale === 1 && /* @__PURE__ */
|
|
6566
|
+
zoomScale === 1 && /* @__PURE__ */ jsx30("div", { className: "absolute bottom-6 right-4 text-[9px] text-white/20 font-mono", children: "Pinch zum Zoomen \xB7 Doppeltipp 2.5\xD7" })
|
|
6411
6567
|
]
|
|
6412
6568
|
}
|
|
6413
6569
|
);
|
|
6414
6570
|
}
|
|
6415
6571
|
if (showStart) {
|
|
6416
|
-
return /* @__PURE__ */
|
|
6417
|
-
/* @__PURE__ */
|
|
6418
|
-
/* @__PURE__ */
|
|
6419
|
-
/* @__PURE__ */
|
|
6420
|
-
/* @__PURE__ */
|
|
6572
|
+
return /* @__PURE__ */ jsxs28("div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col items-center justify-center p-6", style: { gap: 28, ...hcStyle }, children: [
|
|
6573
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-1", children: [
|
|
6574
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-white/15 text-[44px]", children: "palette" }),
|
|
6575
|
+
/* @__PURE__ */ jsx30("span", { className: "text-white/25 text-[10px] font-bold uppercase tracking-[0.25em]", children: "Avatar Architect" }),
|
|
6576
|
+
/* @__PURE__ */ jsxs28("span", { className: "text-white text-[13px] font-mono", children: [
|
|
6421
6577
|
"v",
|
|
6422
6578
|
version
|
|
6423
6579
|
] })
|
|
6424
6580
|
] }),
|
|
6425
|
-
/* @__PURE__ */
|
|
6581
|
+
/* @__PURE__ */ jsxs28(
|
|
6426
6582
|
"button",
|
|
6427
6583
|
{
|
|
6428
6584
|
onClick: toggleContrast,
|
|
6429
6585
|
className: "flex items-center gap-3 px-5 py-3 rounded-2xl border transition-colors",
|
|
6430
6586
|
style: { borderColor: highContrast ? "rgba(255,255,255,0.3)" : "rgba(255,255,255,0.08)", background: highContrast ? "rgba(255,255,255,0.08)" : "transparent" },
|
|
6431
6587
|
children: [
|
|
6432
|
-
/* @__PURE__ */
|
|
6433
|
-
/* @__PURE__ */
|
|
6434
|
-
/* @__PURE__ */
|
|
6435
|
-
/* @__PURE__ */
|
|
6588
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.35)" }, children: highContrast ? "light_mode" : "dark_mode" }),
|
|
6589
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-start", children: [
|
|
6590
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[13px] font-bold", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.5)" }, children: highContrast ? "Hoher Kontrast" : "Normaler Kontrast" }),
|
|
6591
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[10px]", style: { color: "rgba(255,255,255,0.25)" }, children: "Tippen zum Umschalten" })
|
|
6436
6592
|
] })
|
|
6437
6593
|
]
|
|
6438
6594
|
}
|
|
6439
6595
|
),
|
|
6440
|
-
/* @__PURE__ */
|
|
6441
|
-
!initialHfToken && /* @__PURE__ */
|
|
6442
|
-
/* @__PURE__ */
|
|
6596
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
6597
|
+
!initialHfToken && /* @__PURE__ */ jsxs28("div", { className: "flex gap-2 w-full", children: [
|
|
6598
|
+
/* @__PURE__ */ jsx30(
|
|
6443
6599
|
"input",
|
|
6444
6600
|
{
|
|
6445
6601
|
type: "password",
|
|
@@ -6455,7 +6611,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6455
6611
|
style: { height: 44, background: "rgba(255,255,255,0.05)", border: "1px solid rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.7)" }
|
|
6456
6612
|
}
|
|
6457
6613
|
),
|
|
6458
|
-
hfTokenInput.trim() && /* @__PURE__ */
|
|
6614
|
+
hfTokenInput.trim() && /* @__PURE__ */ jsx30(
|
|
6459
6615
|
"button",
|
|
6460
6616
|
{
|
|
6461
6617
|
type: "button",
|
|
@@ -6466,9 +6622,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6466
6622
|
}
|
|
6467
6623
|
)
|
|
6468
6624
|
] }),
|
|
6469
|
-
isDialogTarget && /* @__PURE__ */
|
|
6470
|
-
/* @__PURE__ */
|
|
6471
|
-
["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */
|
|
6625
|
+
isDialogTarget && /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-3 w-full", children: [
|
|
6626
|
+
/* @__PURE__ */ jsx30("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold flex-shrink-0", children: "State:" }),
|
|
6627
|
+
["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */ jsx30(
|
|
6472
6628
|
"button",
|
|
6473
6629
|
{
|
|
6474
6630
|
onClick: () => {
|
|
@@ -6489,47 +6645,48 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6489
6645
|
))
|
|
6490
6646
|
] })
|
|
6491
6647
|
] }),
|
|
6492
|
-
/* @__PURE__ */
|
|
6493
|
-
/* @__PURE__ */
|
|
6494
|
-
/* @__PURE__ */
|
|
6648
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
6649
|
+
/* @__PURE__ */ jsx30("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold", children: "Layout w\xE4hlen & starten" }),
|
|
6650
|
+
/* @__PURE__ */ jsx30("div", { className: "grid grid-cols-2 gap-2 w-full", children: [
|
|
6495
6651
|
{ id: "mobile", icon: "smartphone", label: "Mobile" },
|
|
6496
6652
|
{ id: "mobile-desktop", icon: "phonelink", label: "Mobile+" },
|
|
6497
6653
|
{ id: "desktop", icon: "desktop_windows", label: "Desktop" },
|
|
6498
6654
|
{ id: "tablet-landscape", icon: "tablet", label: "Landscape" }
|
|
6499
|
-
].map((opt) => /* @__PURE__ */
|
|
6655
|
+
].map((opt) => /* @__PURE__ */ jsxs28(
|
|
6500
6656
|
"button",
|
|
6501
6657
|
{
|
|
6502
6658
|
onClick: () => startApp(opt.id),
|
|
6503
6659
|
className: "flex flex-col items-center gap-2 py-4 rounded-2xl border transition-colors",
|
|
6504
6660
|
style: { borderColor: layoutChoice === opt.id ? "rgba(255,255,255,0.35)" : "rgba(255,255,255,0.08)", background: layoutChoice === opt.id ? "rgba(255,255,255,0.07)" : "transparent" },
|
|
6505
6661
|
children: [
|
|
6506
|
-
/* @__PURE__ */
|
|
6507
|
-
/* @__PURE__ */
|
|
6662
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[24px]", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.icon }),
|
|
6663
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[11px] font-bold", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.label })
|
|
6508
6664
|
]
|
|
6509
6665
|
},
|
|
6510
6666
|
opt.id
|
|
6511
6667
|
)) }),
|
|
6512
|
-
layoutChoice === "mobile-desktop" && /* @__PURE__ */
|
|
6513
|
-
layoutChoice === "tablet-landscape" && /* @__PURE__ */
|
|
6514
|
-
] })
|
|
6668
|
+
layoutChoice === "mobile-desktop" && /* @__PURE__ */ jsx30("span", { className: "text-white/20 text-[9px] text-center", children: "Mobil-Layout skaliert f\xFCr Desktop-Modus" }),
|
|
6669
|
+
layoutChoice === "tablet-landscape" && /* @__PURE__ */ jsx30("span", { className: "text-white/20 text-[9px] text-center", children: "2-Spalten-Layout f\xFCr Landscape-Tablet im Desktop-Mode" })
|
|
6670
|
+
] }),
|
|
6671
|
+
/* @__PURE__ */ jsx30(FlowBridgePanel, { appVersion: version })
|
|
6515
6672
|
] });
|
|
6516
6673
|
}
|
|
6517
6674
|
if (requireWorkspaceSelection) {
|
|
6518
6675
|
if (!bootstrapTarget.ready) {
|
|
6519
|
-
return /* @__PURE__ */
|
|
6676
|
+
return /* @__PURE__ */ jsx30("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ jsx30("section", { className: "flow-workspace-picker__card", children: "Zielraum wird bestimmt\u2026" }) });
|
|
6520
6677
|
}
|
|
6521
6678
|
if (!hfToken) {
|
|
6522
|
-
return /* @__PURE__ */
|
|
6679
|
+
return /* @__PURE__ */ jsx30("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ jsx30("section", { className: "flow-workspace-picker__card", role: "alert", children: "HF-Token fehlt \u2014 User und Context koennen nicht aus der Tag-Base geladen werden." }) });
|
|
6523
6680
|
}
|
|
6524
6681
|
if (tagBaseResult.isLoading) {
|
|
6525
|
-
return /* @__PURE__ */
|
|
6682
|
+
return /* @__PURE__ */ jsx30("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ jsxs28("section", { className: "flow-workspace-picker__card", children: [
|
|
6526
6683
|
"Lade User und Contexts aus ",
|
|
6527
6684
|
effectiveNamespace,
|
|
6528
6685
|
"\u2026"
|
|
6529
6686
|
] }) });
|
|
6530
6687
|
}
|
|
6531
6688
|
if (tagBaseResult.error) {
|
|
6532
|
-
return /* @__PURE__ */
|
|
6689
|
+
return /* @__PURE__ */ jsx30("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ jsxs28("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
6533
6690
|
"Tag-Base ",
|
|
6534
6691
|
effectiveNamespace,
|
|
6535
6692
|
" konnte nicht geladen werden: ",
|
|
@@ -6537,14 +6694,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6537
6694
|
] }) });
|
|
6538
6695
|
}
|
|
6539
6696
|
if (!tagBaseResult.tagBase) {
|
|
6540
|
-
return /* @__PURE__ */
|
|
6697
|
+
return /* @__PURE__ */ jsx30("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ jsxs28("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
6541
6698
|
"Im Namespace ",
|
|
6542
6699
|
effectiveNamespace,
|
|
6543
6700
|
" fehlt tags-state-*.zip. Der Server muss zuerst die Tag-Base erzeugen."
|
|
6544
6701
|
] }) });
|
|
6545
6702
|
}
|
|
6546
6703
|
if (tagBaseResult.needsPicker) {
|
|
6547
|
-
return /* @__PURE__ */
|
|
6704
|
+
return /* @__PURE__ */ jsx30(
|
|
6548
6705
|
FlowWorkspacePicker,
|
|
6549
6706
|
{
|
|
6550
6707
|
tagBase: tagBaseResult.tagBase,
|
|
@@ -6556,7 +6713,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6556
6713
|
);
|
|
6557
6714
|
}
|
|
6558
6715
|
}
|
|
6559
|
-
const szenenPane = szenenPort ? /* @__PURE__ */
|
|
6716
|
+
const szenenPane = szenenPort ? /* @__PURE__ */ jsx30("div", { className: "flow-szenen-pane", children: /* @__PURE__ */ jsx30(SzenenView, { port: szenenPort, contextId: szenenKontextId }) }) : /* @__PURE__ */ jsx30("div", { className: "flow-szenen-pane flow-szenen-pane--empty", children: /* @__PURE__ */ jsxs28("p", { children: [
|
|
6560
6717
|
"Szenen brauchen einen HF-Token f\xFCr Namespace ",
|
|
6561
6718
|
effectiveNamespace || "(noch nicht bestimmt)",
|
|
6562
6719
|
" \u2014 auf der Flow-Startseite setzen."
|
|
@@ -6566,22 +6723,22 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6566
6723
|
const mdScale = mdMode ? window.innerWidth / 430 : 1;
|
|
6567
6724
|
const mdW = mdMode ? 430 : void 0;
|
|
6568
6725
|
const mdH = mdMode ? Math.ceil(window.innerHeight / mdScale) : void 0;
|
|
6569
|
-
const mobileRoot = /* @__PURE__ */
|
|
6726
|
+
const mobileRoot = /* @__PURE__ */ jsxs28("div", { className: "flex flex-col bg-[#0e0e0e] text-white overflow-hidden", style: {
|
|
6570
6727
|
width: mdMode ? mdW : "100vw",
|
|
6571
6728
|
height: mdMode ? mdH : "100dvh",
|
|
6572
6729
|
transform: mdMode ? `scale(${mdScale})` : void 0,
|
|
6573
6730
|
transformOrigin: mdMode ? "top left" : void 0,
|
|
6574
6731
|
...hcStyle || {}
|
|
6575
6732
|
}, children: [
|
|
6576
|
-
mobileTab === "labs" && /* @__PURE__ */
|
|
6733
|
+
mobileTab === "labs" && /* @__PURE__ */ jsx30("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ jsx30(LabsTab, { services: labServices, onResult: (item) => {
|
|
6577
6734
|
const frame = item.frames[0];
|
|
6578
6735
|
if (frame?.base64) {
|
|
6579
6736
|
setCurrentResult(frameToGeneration(frame, item));
|
|
6580
6737
|
setMobileTab("stage");
|
|
6581
6738
|
}
|
|
6582
6739
|
} }) }),
|
|
6583
|
-
mobileTab === "server" && /* @__PURE__ */
|
|
6584
|
-
mobileTab === "tags" && workspaceTags && /* @__PURE__ */
|
|
6740
|
+
mobileTab === "server" && /* @__PURE__ */ jsx30("div", { className: "flex flex-col flex-1 min-h-0 relative", children: /* @__PURE__ */ jsx30(ServerTab, { serverBaseUrl }) }),
|
|
6741
|
+
mobileTab === "tags" && workspaceTags && /* @__PURE__ */ jsx30("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ jsx30(
|
|
6585
6742
|
TagManagerPanel,
|
|
6586
6743
|
{
|
|
6587
6744
|
workspaceTags,
|
|
@@ -6593,24 +6750,24 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6593
6750
|
}
|
|
6594
6751
|
) }),
|
|
6595
6752
|
mobileTab === "szenen" && szenenPane,
|
|
6596
|
-
mobileTab === "stage" && /* @__PURE__ */
|
|
6597
|
-
/* @__PURE__ */
|
|
6598
|
-
/* @__PURE__ */
|
|
6599
|
-
/* @__PURE__ */
|
|
6600
|
-
/* @__PURE__ */
|
|
6601
|
-
/* @__PURE__ */
|
|
6602
|
-
/* @__PURE__ */
|
|
6753
|
+
mobileTab === "stage" && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
6754
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
|
|
6755
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
6756
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
|
|
6757
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
|
|
6758
|
+
/* @__PURE__ */ jsx30("div", { className: "flex-1" }),
|
|
6759
|
+
/* @__PURE__ */ jsx30(TaskExecutor, { openTasks: hfState?.openTasks || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
|
|
6603
6760
|
runningBadge,
|
|
6604
|
-
activeReferenceThumbnail ? /* @__PURE__ */
|
|
6605
|
-
/* @__PURE__ */
|
|
6606
|
-
/* @__PURE__ */
|
|
6607
|
-
/* @__PURE__ */
|
|
6608
|
-
] }) : /* @__PURE__ */
|
|
6609
|
-
/* @__PURE__ */
|
|
6610
|
-
/* @__PURE__ */
|
|
6761
|
+
activeReferenceThumbnail ? /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
|
|
6762
|
+
/* @__PURE__ */ jsx30("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
|
|
6763
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
|
|
6764
|
+
/* @__PURE__ */ jsx30("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 active:text-white/80 transition-colors", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
6765
|
+
] }) : /* @__PURE__ */ jsx30("button", { onClick: handleSelectReference, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }) }),
|
|
6766
|
+
/* @__PURE__ */ jsx30("button", { onClick: toggleContrast, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: highContrast ? "light_mode" : "dark_mode" }) }),
|
|
6767
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => setShowStart(true), className: "text-white/20 active:text-white/60 transition-colors mr-1", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "desktop_windows" }) })
|
|
6611
6768
|
] }),
|
|
6612
|
-
/* @__PURE__ */
|
|
6613
|
-
/* @__PURE__ */
|
|
6769
|
+
/* @__PURE__ */ jsx30("div", { className: "px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ jsxs28("div", { className: `relative rounded-xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
|
|
6770
|
+
/* @__PURE__ */ jsx30(
|
|
6614
6771
|
"textarea",
|
|
6615
6772
|
{
|
|
6616
6773
|
value: activePrompt,
|
|
@@ -6620,9 +6777,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6620
6777
|
placeholder: "Prompt eingeben..."
|
|
6621
6778
|
}
|
|
6622
6779
|
),
|
|
6623
|
-
activePrompt && !isSynthesizing && /* @__PURE__ */
|
|
6780
|
+
activePrompt && !isSynthesizing && /* @__PURE__ */ jsx30("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-white/20 active:text-white transition-colors", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
|
|
6624
6781
|
] }) }),
|
|
6625
|
-
/* @__PURE__ */
|
|
6782
|
+
/* @__PURE__ */ jsx30("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ jsxs28(
|
|
6626
6783
|
"button",
|
|
6627
6784
|
{
|
|
6628
6785
|
onClick: () => handleGenerateBatch(),
|
|
@@ -6630,13 +6787,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6630
6787
|
className: "w-full flex items-center justify-center gap-2 rounded-xl font-bold text-[14px] uppercase tracking-wide transition-all disabled:opacity-30 active:scale-95",
|
|
6631
6788
|
style: { height: 48, background: activePrompt.trim() ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
|
|
6632
6789
|
children: [
|
|
6633
|
-
/* @__PURE__ */
|
|
6634
|
-
/* @__PURE__ */
|
|
6790
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
|
|
6791
|
+
/* @__PURE__ */ jsx30("span", { children: "Generieren" })
|
|
6635
6792
|
]
|
|
6636
6793
|
}
|
|
6637
6794
|
) }),
|
|
6638
|
-
/* @__PURE__ */
|
|
6639
|
-
/* @__PURE__ */
|
|
6795
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
|
|
6796
|
+
/* @__PURE__ */ jsxs28(
|
|
6640
6797
|
"div",
|
|
6641
6798
|
{
|
|
6642
6799
|
className: "w-full rounded-2xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center",
|
|
@@ -6650,25 +6807,25 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6650
6807
|
setTouchStartX(null);
|
|
6651
6808
|
},
|
|
6652
6809
|
children: [
|
|
6653
|
-
currentResult?.status === "processing" && /* @__PURE__ */
|
|
6654
|
-
/* @__PURE__ */
|
|
6655
|
-
/* @__PURE__ */
|
|
6810
|
+
currentResult?.status === "processing" && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
|
|
6811
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
|
|
6812
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
|
|
6656
6813
|
] }),
|
|
6657
|
-
currentResult?.status === "error" && /* @__PURE__ */
|
|
6658
|
-
/* @__PURE__ */
|
|
6659
|
-
/* @__PURE__ */
|
|
6660
|
-
/* @__PURE__ */
|
|
6814
|
+
currentResult?.status === "error" && /* @__PURE__ */ jsxs28("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
|
|
6815
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
|
|
6816
|
+
/* @__PURE__ */ jsx30("p", { className: "text-white/50 text-[13px]", children: currentResult.error?.message }),
|
|
6817
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => handleGenerateImage(currentResult.prompt), className: "px-4 py-2 rounded-lg border border-white/20 text-[13px] text-white/70 active:bg-white/10", children: "Erneut versuchen" })
|
|
6661
6818
|
] }),
|
|
6662
|
-
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */
|
|
6663
|
-
!currentResult && /* @__PURE__ */
|
|
6664
|
-
/* @__PURE__ */
|
|
6665
|
-
/* @__PURE__ */
|
|
6819
|
+
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ jsx30("img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
|
|
6820
|
+
!currentResult && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
|
|
6821
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
|
|
6822
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
|
|
6666
6823
|
] }),
|
|
6667
|
-
currentResult?.status === "done" && /* @__PURE__ */
|
|
6668
|
-
history.length > 1 && currentResult && /* @__PURE__ */
|
|
6669
|
-
/* @__PURE__ */
|
|
6670
|
-
/* @__PURE__ */
|
|
6671
|
-
/* @__PURE__ */
|
|
6824
|
+
currentResult?.status === "done" && /* @__PURE__ */ jsx30("button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
|
|
6825
|
+
history.length > 1 && currentResult && /* @__PURE__ */ jsxs28(Fragment10, { children: [
|
|
6826
|
+
/* @__PURE__ */ jsx30("button", { onClick: goToPrev, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
|
|
6827
|
+
/* @__PURE__ */ jsx30("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
|
|
6828
|
+
/* @__PURE__ */ jsxs28("div", { className: "absolute bottom-2 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
|
|
6672
6829
|
currentIndex + 1,
|
|
6673
6830
|
" / ",
|
|
6674
6831
|
history.length
|
|
@@ -6677,8 +6834,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6677
6834
|
]
|
|
6678
6835
|
}
|
|
6679
6836
|
),
|
|
6680
|
-
currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */
|
|
6681
|
-
/* @__PURE__ */
|
|
6837
|
+
currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ jsx30("div", { className: "mt-2 flex gap-1.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ jsxs28("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
6838
|
+
/* @__PURE__ */ jsx30(
|
|
6682
6839
|
"div",
|
|
6683
6840
|
{
|
|
6684
6841
|
onClick: () => handleGallerySelect(item),
|
|
@@ -6691,10 +6848,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6691
6848
|
border: item.id === currentResult.id ? "2px solid rgba(255,255,255,0.8)" : "2px solid rgba(255,255,255,0.15)",
|
|
6692
6849
|
opacity: item.id === currentResult.id ? 1 : 0.55
|
|
6693
6850
|
},
|
|
6694
|
-
children: /* @__PURE__ */
|
|
6851
|
+
children: /* @__PURE__ */ jsx30("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
|
|
6695
6852
|
}
|
|
6696
6853
|
),
|
|
6697
|
-
/* @__PURE__ */
|
|
6854
|
+
/* @__PURE__ */ jsx30(
|
|
6698
6855
|
"button",
|
|
6699
6856
|
{
|
|
6700
6857
|
onClick: (e) => {
|
|
@@ -6716,34 +6873,34 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6716
6873
|
alignItems: "center",
|
|
6717
6874
|
justifyContent: "center"
|
|
6718
6875
|
},
|
|
6719
|
-
children: /* @__PURE__ */
|
|
6876
|
+
children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 9, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
|
|
6720
6877
|
}
|
|
6721
6878
|
)
|
|
6722
6879
|
] }, item.id)) }),
|
|
6723
|
-
currentResult?.status === "done" && /* @__PURE__ */
|
|
6724
|
-
/* @__PURE__ */
|
|
6725
|
-
/* @__PURE__ */
|
|
6726
|
-
/* @__PURE__ */
|
|
6880
|
+
currentResult?.status === "done" && /* @__PURE__ */ jsxs28("div", { className: "flex gap-2 mt-3", children: [
|
|
6881
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
|
|
6882
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
|
|
6883
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[12px] text-white/60", children: "Prompt" })
|
|
6727
6884
|
] }),
|
|
6728
|
-
/* @__PURE__ */
|
|
6729
|
-
/* @__PURE__ */
|
|
6730
|
-
/* @__PURE__ */
|
|
6885
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
|
|
6886
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
|
|
6887
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
|
|
6731
6888
|
] }),
|
|
6732
|
-
/* @__PURE__ */
|
|
6733
|
-
/* @__PURE__ */
|
|
6734
|
-
/* @__PURE__ */
|
|
6889
|
+
/* @__PURE__ */ jsxs28("button", { onClick: handleDownloadSingle, className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
|
|
6890
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "download" }),
|
|
6891
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[12px] text-white/60", children: "Laden" })
|
|
6735
6892
|
] })
|
|
6736
6893
|
] })
|
|
6737
6894
|
] })
|
|
6738
6895
|
] }),
|
|
6739
|
-
mobileTab === "browse" && /* @__PURE__ */
|
|
6740
|
-
/* @__PURE__ */
|
|
6741
|
-
["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */
|
|
6742
|
-
hfToken && /* @__PURE__ */
|
|
6896
|
+
mobileTab === "browse" && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
6897
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
|
|
6898
|
+
["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */ jsx30("button", { onClick: () => setActiveTab(tab), className: `flex-1 flex items-center justify-center gap-1.5 transition-colors text-[11px] font-bold uppercase tracking-wide ${activeTab === tab ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : "info" }) }, tab)),
|
|
6899
|
+
hfToken && /* @__PURE__ */ jsx30("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx30("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
|
|
6743
6900
|
] }),
|
|
6744
|
-
/* @__PURE__ */
|
|
6745
|
-
activeTab === "history" && /* @__PURE__ */
|
|
6746
|
-
activeTab === "gallery" && /* @__PURE__ */
|
|
6901
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
6902
|
+
activeTab === "history" && /* @__PURE__ */ jsx30(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
|
|
6903
|
+
activeTab === "gallery" && /* @__PURE__ */ jsx30(
|
|
6747
6904
|
MediaLibrary,
|
|
6748
6905
|
{
|
|
6749
6906
|
items: galleryItems,
|
|
@@ -6762,44 +6919,44 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6762
6919
|
onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
|
|
6763
6920
|
}
|
|
6764
6921
|
),
|
|
6765
|
-
activeTab === "inspect" && /* @__PURE__ */
|
|
6922
|
+
activeTab === "inspect" && /* @__PURE__ */ jsx30(InspectPanel, { currentResult, history, onSelect: (g) => {
|
|
6766
6923
|
setCurrentResult(g);
|
|
6767
6924
|
} })
|
|
6768
6925
|
] })
|
|
6769
6926
|
] }),
|
|
6770
|
-
/* @__PURE__ */
|
|
6771
|
-
/* @__PURE__ */
|
|
6772
|
-
workspaceTags && /* @__PURE__ */
|
|
6927
|
+
/* @__PURE__ */ jsxs28("div", { style: { display: mobileTab === "tools" ? "flex" : "none" }, className: "flex flex-col flex-1 min-h-0", children: [
|
|
6928
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
|
|
6929
|
+
workspaceTags && /* @__PURE__ */ jsxs28("button", { onClick: () => {
|
|
6773
6930
|
setLeftTab("prompt");
|
|
6774
6931
|
if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
|
|
6775
6932
|
}, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
6776
|
-
/* @__PURE__ */
|
|
6933
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "auto_fix_high" }),
|
|
6777
6934
|
"Prompt"
|
|
6778
6935
|
] }),
|
|
6779
|
-
/* @__PURE__ */
|
|
6936
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => {
|
|
6780
6937
|
setLeftTab("hierarchy");
|
|
6781
6938
|
if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
|
|
6782
6939
|
}, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
6783
|
-
/* @__PURE__ */
|
|
6940
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "account_tree" }),
|
|
6784
6941
|
"Hierarchie"
|
|
6785
6942
|
] }),
|
|
6786
|
-
/* @__PURE__ */
|
|
6787
|
-
/* @__PURE__ */
|
|
6943
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setActiveTab("setup"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "setup" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
6944
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "settings" }),
|
|
6788
6945
|
"Setup"
|
|
6789
6946
|
] }),
|
|
6790
|
-
/* @__PURE__ */
|
|
6791
|
-
/* @__PURE__ */
|
|
6947
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setActiveTab("sync"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
6948
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "cloud_sync" }),
|
|
6792
6949
|
"Sync"
|
|
6793
6950
|
] }),
|
|
6794
|
-
/* @__PURE__ */
|
|
6795
|
-
/* @__PURE__ */
|
|
6951
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setActiveTab("hftest"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "hftest" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
6952
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "biotech" }),
|
|
6796
6953
|
"HF"
|
|
6797
6954
|
] }),
|
|
6798
|
-
serverBaseUrl && /* @__PURE__ */
|
|
6799
|
-
workspaceTags && /* @__PURE__ */
|
|
6955
|
+
serverBaseUrl && /* @__PURE__ */ jsx30("button", { onClick: () => setActiveTab("server"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "server" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) }),
|
|
6956
|
+
workspaceTags && /* @__PURE__ */ jsx30("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
|
|
6800
6957
|
] }),
|
|
6801
|
-
/* @__PURE__ */
|
|
6802
|
-
leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" && /* @__PURE__ */
|
|
6958
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
6959
|
+
leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" && /* @__PURE__ */ jsx30("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx30(
|
|
6803
6960
|
ListView,
|
|
6804
6961
|
{
|
|
6805
6962
|
nodes,
|
|
@@ -6830,19 +6987,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6830
6987
|
isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
|
|
6831
6988
|
}
|
|
6832
6989
|
) }),
|
|
6833
|
-
workspaceTags && /* @__PURE__ */
|
|
6990
|
+
workspaceTags && /* @__PURE__ */ jsx30("div", { style: { display: leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" ? "flex" : "none" }, className: "absolute inset-0 flex-col", children: /* @__PURE__ */ jsx30(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
|
|
6834
6991
|
handleGenerateBatch(prompt);
|
|
6835
6992
|
setMobileTab("stage");
|
|
6836
6993
|
}, onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage }) }),
|
|
6837
|
-
activeTab === "setup" && /* @__PURE__ */
|
|
6838
|
-
activeTab === "sync" && /* @__PURE__ */
|
|
6994
|
+
activeTab === "setup" && /* @__PURE__ */ jsx30(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo, tagBase: tagBaseResult }),
|
|
6995
|
+
activeTab === "sync" && /* @__PURE__ */ jsx30(
|
|
6839
6996
|
HfMediaSyncTab,
|
|
6840
6997
|
{
|
|
6841
6998
|
topSlot: syncTopSlot,
|
|
6842
6999
|
onHfInitialSync: hfToken ? handleHfInitialSync : void 0
|
|
6843
7000
|
}
|
|
6844
7001
|
),
|
|
6845
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */
|
|
7002
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ jsx30(
|
|
6846
7003
|
TagManagerPanel,
|
|
6847
7004
|
{
|
|
6848
7005
|
workspaceTags,
|
|
@@ -6853,7 +7010,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6853
7010
|
onTagMove: handleTagMove
|
|
6854
7011
|
}
|
|
6855
7012
|
),
|
|
6856
|
-
activeTab === "hftest" && /* @__PURE__ */
|
|
7013
|
+
activeTab === "hftest" && /* @__PURE__ */ jsx30("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx30(
|
|
6857
7014
|
HFTestTab,
|
|
6858
7015
|
{
|
|
6859
7016
|
token: hfToken,
|
|
@@ -6865,10 +7022,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6865
7022
|
missingImages: hfMissingImages
|
|
6866
7023
|
}
|
|
6867
7024
|
) }),
|
|
6868
|
-
activeTab === "server" && /* @__PURE__ */
|
|
7025
|
+
activeTab === "server" && /* @__PURE__ */ jsx30("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx30(ServerTab, { serverBaseUrl }) })
|
|
6869
7026
|
] })
|
|
6870
7027
|
] }),
|
|
6871
|
-
/* @__PURE__ */
|
|
7028
|
+
/* @__PURE__ */ jsx30("div", { className: "flex overflow-x-auto border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
|
|
6872
7029
|
{ id: "tools", icon: "auto_fix_high", label: "Prompt" },
|
|
6873
7030
|
{ id: "szenen", icon: "movie", label: "Szenen" },
|
|
6874
7031
|
{ id: "stage", icon: "palette", label: "Stage" },
|
|
@@ -6876,13 +7033,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6876
7033
|
...workspaceTags ? [{ id: "tags", icon: "label", label: "Tags" }] : [],
|
|
6877
7034
|
{ id: "browse", icon: "photo_library", label: "Galerie" },
|
|
6878
7035
|
...serverBaseUrl ? [{ id: "server", icon: "storage", label: "Server" }] : []
|
|
6879
|
-
].map((tab) => /* @__PURE__ */
|
|
6880
|
-
/* @__PURE__ */
|
|
6881
|
-
/* @__PURE__ */
|
|
7036
|
+
].map((tab) => /* @__PURE__ */ jsxs28("button", { onClick: () => setMobileTab(tab.id), className: `flex-none min-w-[64px] flex flex-col items-center justify-center gap-0.5 transition-colors ${mobileTab === tab.id ? "text-white" : "text-white/30"}`, children: [
|
|
7037
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[24px]", children: tab.icon }),
|
|
7038
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[10px] font-bold uppercase tracking-wide", children: tab.label })
|
|
6882
7039
|
] }, tab.id)) })
|
|
6883
7040
|
] });
|
|
6884
7041
|
if (mdMode) {
|
|
6885
|
-
return /* @__PURE__ */
|
|
7042
|
+
return /* @__PURE__ */ jsx30("div", { style: { position: "fixed", inset: 0, overflow: "hidden", background: "#0e0e0e" }, children: mobileRoot });
|
|
6886
7043
|
}
|
|
6887
7044
|
return mobileRoot;
|
|
6888
7045
|
}
|
|
@@ -6890,20 +7047,20 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6890
7047
|
const tlScale = Math.min(window.innerWidth / 920, window.innerHeight / 520);
|
|
6891
7048
|
const tlW = 920;
|
|
6892
7049
|
const tlH = 520;
|
|
6893
|
-
return /* @__PURE__ */
|
|
6894
|
-
/* @__PURE__ */
|
|
6895
|
-
/* @__PURE__ */
|
|
6896
|
-
/* @__PURE__ */
|
|
6897
|
-
/* @__PURE__ */
|
|
6898
|
-
/* @__PURE__ */
|
|
6899
|
-
/* @__PURE__ */
|
|
6900
|
-
/* @__PURE__ */
|
|
7050
|
+
return /* @__PURE__ */ jsx30("div", { style: { position: "fixed", inset: 0, background: "#0e0e0e", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", ...hcStyle || {} }, children: /* @__PURE__ */ jsxs28("div", { style: { width: tlW, height: tlH, transform: `scale(${tlScale})`, transformOrigin: "center center", display: "flex", flexDirection: "row", color: "#fff", overflow: "hidden", borderRadius: 0 }, children: [
|
|
7051
|
+
/* @__PURE__ */ jsxs28("div", { style: { width: 320, height: tlH, display: "flex", flexDirection: "column", borderRight: "1px solid rgba(255,255,255,0.05)", background: "#000", flexShrink: 0 }, children: [
|
|
7052
|
+
/* @__PURE__ */ jsxs28("div", { style: { height: 52, borderBottom: "1px solid rgba(255,255,255,0.05)", display: "flex", alignItems: "center", gap: 8, padding: "0 12px", flexShrink: 0 }, children: [
|
|
7053
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
7054
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
|
|
7055
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
|
|
7056
|
+
/* @__PURE__ */ jsx30("div", { style: { flex: 1 } }),
|
|
7057
|
+
/* @__PURE__ */ jsx30(TaskExecutor, { openTasks: hfState?.openTasks || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
|
|
6901
7058
|
runningBadge,
|
|
6902
|
-
/* @__PURE__ */
|
|
6903
|
-
/* @__PURE__ */
|
|
7059
|
+
/* @__PURE__ */ jsx30("button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
|
|
7060
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
|
|
6904
7061
|
] }),
|
|
6905
|
-
/* @__PURE__ */
|
|
6906
|
-
/* @__PURE__ */
|
|
7062
|
+
/* @__PURE__ */ jsx30("div", { style: { padding: "12px 12px 8px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs28("div", { style: { position: "relative", borderRadius: 12, border: `1px solid ${isSynthesizing ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.1)"}`, background: "rgba(255,255,255,0.05)" }, children: [
|
|
7063
|
+
/* @__PURE__ */ jsx30(
|
|
6907
7064
|
"textarea",
|
|
6908
7065
|
{
|
|
6909
7066
|
value: activePrompt,
|
|
@@ -6912,24 +7069,24 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6912
7069
|
placeholder: "Prompt eingeben..."
|
|
6913
7070
|
}
|
|
6914
7071
|
),
|
|
6915
|
-
activePrompt && /* @__PURE__ */
|
|
7072
|
+
activePrompt && /* @__PURE__ */ jsx30("button", { onClick: () => setActivePrompt(""), style: { position: "absolute", top: 6, right: 6, width: 22, height: 22, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 0 }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
|
|
6916
7073
|
] }) }),
|
|
6917
|
-
/* @__PURE__ */
|
|
7074
|
+
/* @__PURE__ */ jsx30("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs28(
|
|
6918
7075
|
"button",
|
|
6919
7076
|
{
|
|
6920
7077
|
onClick: () => handleGenerateBatch(),
|
|
6921
7078
|
disabled: !activePrompt.trim(),
|
|
6922
7079
|
style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() ? "pointer" : "default", opacity: !activePrompt.trim() ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
|
|
6923
7080
|
children: [
|
|
6924
|
-
/* @__PURE__ */
|
|
6925
|
-
/* @__PURE__ */
|
|
7081
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
|
|
7082
|
+
/* @__PURE__ */ jsx30("span", { children: "Generieren" })
|
|
6926
7083
|
]
|
|
6927
7084
|
}
|
|
6928
7085
|
) }),
|
|
6929
|
-
/* @__PURE__ */
|
|
7086
|
+
/* @__PURE__ */ jsx30("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ jsx30(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
|
|
6930
7087
|
] }),
|
|
6931
|
-
/* @__PURE__ */
|
|
6932
|
-
/* @__PURE__ */
|
|
7088
|
+
/* @__PURE__ */ jsxs28("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
|
|
7089
|
+
/* @__PURE__ */ jsx30(
|
|
6933
7090
|
"div",
|
|
6934
7091
|
{
|
|
6935
7092
|
style: { flex: 1, padding: 16, display: "flex", alignItems: "center", justifyContent: "center", position: "relative" },
|
|
@@ -6941,26 +7098,26 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6941
7098
|
else if (dx > 50) goToPrev();
|
|
6942
7099
|
setTouchStartX(null);
|
|
6943
7100
|
},
|
|
6944
|
-
children: /* @__PURE__ */
|
|
6945
|
-
currentResult?.status === "processing" && /* @__PURE__ */
|
|
6946
|
-
/* @__PURE__ */
|
|
6947
|
-
/* @__PURE__ */
|
|
7101
|
+
children: /* @__PURE__ */ jsxs28("div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
|
|
7102
|
+
currentResult?.status === "processing" && /* @__PURE__ */ jsxs28("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
|
|
7103
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
|
|
7104
|
+
/* @__PURE__ */ jsx30("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.6)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
|
|
6948
7105
|
] }),
|
|
6949
|
-
currentResult?.status === "error" && /* @__PURE__ */
|
|
6950
|
-
/* @__PURE__ */
|
|
6951
|
-
/* @__PURE__ */
|
|
6952
|
-
/* @__PURE__ */
|
|
7106
|
+
currentResult?.status === "error" && /* @__PURE__ */ jsxs28("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
|
|
7107
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
|
|
7108
|
+
/* @__PURE__ */ jsx30("p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: currentResult.error?.message }),
|
|
7109
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => handleGenerateImage(currentResult.prompt), style: { padding: "8px 16px", borderRadius: 8, border: "1px solid rgba(255,255,255,0.2)", fontSize: 11, color: "rgba(255,255,255,0.7)", background: "none", cursor: "pointer", fontFamily: "inherit" }, children: "Erneut versuchen" })
|
|
6953
7110
|
] }),
|
|
6954
|
-
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */
|
|
6955
|
-
!currentResult && /* @__PURE__ */
|
|
6956
|
-
/* @__PURE__ */
|
|
6957
|
-
/* @__PURE__ */
|
|
7111
|
+
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ jsx30("img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
|
|
7112
|
+
!currentResult && /* @__PURE__ */ jsxs28("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
|
|
7113
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
|
|
7114
|
+
/* @__PURE__ */ jsx30("span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
|
|
6958
7115
|
] }),
|
|
6959
|
-
currentResult?.status === "done" && /* @__PURE__ */
|
|
6960
|
-
history.length > 1 && currentResult && /* @__PURE__ */
|
|
6961
|
-
/* @__PURE__ */
|
|
6962
|
-
/* @__PURE__ */
|
|
6963
|
-
/* @__PURE__ */
|
|
7116
|
+
currentResult?.status === "done" && /* @__PURE__ */ jsx30("button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
|
|
7117
|
+
history.length > 1 && currentResult && /* @__PURE__ */ jsxs28(Fragment10, { children: [
|
|
7118
|
+
/* @__PURE__ */ jsx30("button", { onClick: goToPrev, disabled: currentIndex <= 0, style: { position: "absolute", left: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex <= 0 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_left" }) }),
|
|
7119
|
+
/* @__PURE__ */ jsx30("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, style: { position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex >= history.length - 1 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_right" }) }),
|
|
7120
|
+
/* @__PURE__ */ jsxs28("div", { style: { position: "absolute", bottom: 8, left: "50%", transform: "translateX(-50%)", background: "rgba(0,0,0,0.6)", borderRadius: 999, padding: "2px 12px", fontSize: 10, color: "rgba(255,255,255,0.4)", fontFamily: "monospace" }, children: [
|
|
6964
7121
|
currentIndex + 1,
|
|
6965
7122
|
" / ",
|
|
6966
7123
|
history.length
|
|
@@ -6969,42 +7126,42 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
6969
7126
|
] })
|
|
6970
7127
|
}
|
|
6971
7128
|
),
|
|
6972
|
-
currentResult?.status === "done" && /* @__PURE__ */
|
|
6973
|
-
/* @__PURE__ */
|
|
6974
|
-
/* @__PURE__ */
|
|
6975
|
-
/* @__PURE__ */
|
|
7129
|
+
currentResult?.status === "done" && /* @__PURE__ */ jsxs28("div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
|
|
7130
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
7131
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
|
|
7132
|
+
/* @__PURE__ */ jsx30("span", { children: "Prompt" })
|
|
6976
7133
|
] }),
|
|
6977
|
-
/* @__PURE__ */
|
|
6978
|
-
/* @__PURE__ */
|
|
6979
|
-
/* @__PURE__ */
|
|
7134
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
7135
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
|
|
7136
|
+
/* @__PURE__ */ jsx30("span", { children: "Referenz" })
|
|
6980
7137
|
] }),
|
|
6981
|
-
/* @__PURE__ */
|
|
6982
|
-
/* @__PURE__ */
|
|
6983
|
-
/* @__PURE__ */
|
|
7138
|
+
/* @__PURE__ */ jsxs28("button", { onClick: handleDownloadSingle, style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
7139
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "download" }),
|
|
7140
|
+
/* @__PURE__ */ jsx30("span", { children: "Laden" })
|
|
6984
7141
|
] })
|
|
6985
7142
|
] })
|
|
6986
7143
|
] })
|
|
6987
7144
|
] }) });
|
|
6988
7145
|
}
|
|
6989
|
-
return /* @__PURE__ */
|
|
6990
|
-
/* @__PURE__ */
|
|
6991
|
-
/* @__PURE__ */
|
|
6992
|
-
/* @__PURE__ */
|
|
6993
|
-
!isLeftCollapsed && /* @__PURE__ */
|
|
6994
|
-
workspaceTags && /* @__PURE__ */
|
|
6995
|
-
/* @__PURE__ */
|
|
7146
|
+
return /* @__PURE__ */ jsxs28("div", { className: "flex h-screen w-screen bg-[#0e0e0e] text-white overflow-hidden", style: hcStyle, children: [
|
|
7147
|
+
/* @__PURE__ */ jsx30("div", { className: "absolute top-2 right-2 z-50", children: /* @__PURE__ */ jsx30("button", { onClick: () => setShowStart(true), className: "text-white/10 hover:text-white/30 transition-colors text-[10px]", children: "\u21C4" }) }),
|
|
7148
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col border-r border-white/5 overflow-hidden relative bg-black/10 shrink-0", style: { width: isLeftCollapsed ? 48 : leftPanelWidth, transition: "none" }, children: [
|
|
7149
|
+
/* @__PURE__ */ jsxs28("div", { className: "h-14 border-b border-white/5 flex items-center justify-between shrink-0 px-1", children: [
|
|
7150
|
+
!isLeftCollapsed && /* @__PURE__ */ jsxs28("div", { className: "flex flex-1 gap-1", children: [
|
|
7151
|
+
workspaceTags && /* @__PURE__ */ jsxs28("button", { onClick: () => setLeftTab("prompt"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
|
|
7152
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "auto_fix_high" }),
|
|
6996
7153
|
"Prompt"
|
|
6997
7154
|
] }),
|
|
6998
|
-
/* @__PURE__ */
|
|
6999
|
-
/* @__PURE__ */
|
|
7155
|
+
/* @__PURE__ */ jsxs28("button", { onClick: () => setLeftTab("hierarchy"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
|
|
7156
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "account_tree" }),
|
|
7000
7157
|
"Hierarchie"
|
|
7001
7158
|
] }),
|
|
7002
|
-
workspaceTags && /* @__PURE__ */
|
|
7159
|
+
workspaceTags && /* @__PURE__ */ jsx30("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
|
|
7003
7160
|
] }),
|
|
7004
|
-
/* @__PURE__ */
|
|
7161
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => setIsLeftCollapsed(!isLeftCollapsed), className: "material-symbols-outlined text-[18px] text-white/40 hover:text-white transition-all w-10 flex items-center justify-center", children: isLeftCollapsed ? "chevron_right" : "chevron_left" })
|
|
7005
7162
|
] }),
|
|
7006
|
-
!isLeftCollapsed && /* @__PURE__ */
|
|
7007
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */
|
|
7163
|
+
!isLeftCollapsed && /* @__PURE__ */ jsxs28("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
7164
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ jsx30(
|
|
7008
7165
|
TagManagerPanel,
|
|
7009
7166
|
{
|
|
7010
7167
|
workspaceTags,
|
|
@@ -7015,11 +7172,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7015
7172
|
onTagMove: handleTagMove
|
|
7016
7173
|
}
|
|
7017
7174
|
),
|
|
7018
|
-
activeTab === "tags" && !workspaceTags && /* @__PURE__ */
|
|
7019
|
-
/* @__PURE__ */
|
|
7020
|
-
/* @__PURE__ */
|
|
7175
|
+
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ jsx30("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ jsxs28("div", { children: [
|
|
7176
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
|
|
7177
|
+
/* @__PURE__ */ jsx30("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
|
|
7021
7178
|
] }) }),
|
|
7022
|
-
leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */
|
|
7179
|
+
leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */ jsx30("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx30(
|
|
7023
7180
|
ListView,
|
|
7024
7181
|
{
|
|
7025
7182
|
nodes,
|
|
@@ -7044,19 +7201,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7044
7201
|
isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
|
|
7045
7202
|
}
|
|
7046
7203
|
) }),
|
|
7047
|
-
leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */
|
|
7204
|
+
leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ jsx30(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateBatch(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
|
|
7048
7205
|
] })
|
|
7049
7206
|
] }),
|
|
7050
|
-
!isLeftCollapsed && /* @__PURE__ */
|
|
7051
|
-
/* @__PURE__ */
|
|
7052
|
-
/* @__PURE__ */
|
|
7053
|
-
/* @__PURE__ */
|
|
7054
|
-
/* @__PURE__ */
|
|
7055
|
-
/* @__PURE__ */
|
|
7056
|
-
/* @__PURE__ */
|
|
7207
|
+
!isLeftCollapsed && /* @__PURE__ */ jsx30("div", { onMouseDown: startLeftResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
|
|
7208
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 flex flex-col bg-[#0b0b0b] overflow-hidden", children: [
|
|
7209
|
+
/* @__PURE__ */ jsxs28("div", { className: "h-14 border-b border-white/5 flex items-center px-4 gap-2 justify-between shrink-0 bg-black/20", children: [
|
|
7210
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1.5", children: [
|
|
7211
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
7212
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
|
|
7213
|
+
/* @__PURE__ */ jsx30(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions })
|
|
7057
7214
|
] }),
|
|
7058
|
-
/* @__PURE__ */
|
|
7059
|
-
/* @__PURE__ */
|
|
7215
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1 mx-auto", children: [
|
|
7216
|
+
/* @__PURE__ */ jsx30(
|
|
7060
7217
|
"button",
|
|
7061
7218
|
{
|
|
7062
7219
|
onClick: () => setMiddlePanel("stage"),
|
|
@@ -7064,7 +7221,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7064
7221
|
children: "Stage"
|
|
7065
7222
|
}
|
|
7066
7223
|
),
|
|
7067
|
-
/* @__PURE__ */
|
|
7224
|
+
/* @__PURE__ */ jsx30(
|
|
7068
7225
|
"button",
|
|
7069
7226
|
{
|
|
7070
7227
|
onClick: () => setMiddlePanel("labs"),
|
|
@@ -7072,7 +7229,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7072
7229
|
children: "Labs"
|
|
7073
7230
|
}
|
|
7074
7231
|
),
|
|
7075
|
-
/* @__PURE__ */
|
|
7232
|
+
/* @__PURE__ */ jsx30(
|
|
7076
7233
|
"button",
|
|
7077
7234
|
{
|
|
7078
7235
|
onClick: () => setMiddlePanel("szenen"),
|
|
@@ -7081,53 +7238,53 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7081
7238
|
}
|
|
7082
7239
|
)
|
|
7083
7240
|
] }),
|
|
7084
|
-
/* @__PURE__ */
|
|
7085
|
-
activeReferenceThumbnail ? /* @__PURE__ */
|
|
7086
|
-
/* @__PURE__ */
|
|
7087
|
-
/* @__PURE__ */
|
|
7088
|
-
/* @__PURE__ */
|
|
7089
|
-
] }) : /* @__PURE__ */
|
|
7090
|
-
/* @__PURE__ */
|
|
7091
|
-
/* @__PURE__ */
|
|
7241
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
7242
|
+
activeReferenceThumbnail ? /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden", style: { height: 28 }, children: [
|
|
7243
|
+
/* @__PURE__ */ jsx30("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
|
|
7244
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
|
|
7245
|
+
/* @__PURE__ */ jsx30("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 hover:text-white/80 transition-colors", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
7246
|
+
] }) : /* @__PURE__ */ jsxs28("button", { onClick: handleSelectReference, className: "flex items-center gap-1 h-7 px-2 rounded-lg border border-white/10 text-white/30 hover:text-white/60 hover:border-white/20 transition-colors text-[10px] font-bold uppercase tracking-wide", children: [
|
|
7247
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
|
|
7248
|
+
/* @__PURE__ */ jsx30("span", { children: "Ref" })
|
|
7092
7249
|
] }),
|
|
7093
|
-
/* @__PURE__ */
|
|
7094
|
-
/* @__PURE__ */
|
|
7250
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
|
|
7251
|
+
/* @__PURE__ */ jsx30(TaskExecutor, { openTasks: hfState?.openTasks || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
|
|
7095
7252
|
runningBadge,
|
|
7096
|
-
/* @__PURE__ */
|
|
7253
|
+
/* @__PURE__ */ jsx30(PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
|
|
7097
7254
|
] })
|
|
7098
7255
|
] }),
|
|
7099
|
-
/* @__PURE__ */
|
|
7100
|
-
!isPromptCollapsed && /* @__PURE__ */
|
|
7101
|
-
/* @__PURE__ */
|
|
7102
|
-
activePrompt && !isSynthesizing && /* @__PURE__ */
|
|
7256
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
|
|
7257
|
+
!isPromptCollapsed && /* @__PURE__ */ jsx30("div", { className: "px-6 py-4 border-b border-white/5 bg-black/10 overflow-hidden shrink-0", children: /* @__PURE__ */ jsxs28("div", { className: `relative min-h-[60px] p-4 rounded-2xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
|
|
7258
|
+
/* @__PURE__ */ jsx30("textarea", { value: activePrompt, onChange: (e) => setActivePrompt(e.target.value), className: "w-full bg-transparent border-none outline-none text-[12px] leading-relaxed text-white/80 resize-none h-20 dark-scrollbar", placeholder: "W\xE4hle einen Knoten oder tippe einen Prompt..." }),
|
|
7259
|
+
activePrompt && !isSynthesizing && /* @__PURE__ */ jsx30("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-white/5 hover:bg-white/10 flex items-center justify-center transition-colors text-white/20 hover:text-white", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
7103
7260
|
] }) }),
|
|
7104
|
-
middlePanel === "szenen" ? szenenPane : middlePanel === "labs" ? /* @__PURE__ */
|
|
7261
|
+
middlePanel === "szenen" ? szenenPane : middlePanel === "labs" ? /* @__PURE__ */ jsx30("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx30(LabsTab, { services: labServices, onResult: (item) => {
|
|
7105
7262
|
const frame = item.frames[0];
|
|
7106
7263
|
if (frame?.base64) setCurrentResult(frameToGeneration(frame, item));
|
|
7107
|
-
} }) }) : /* @__PURE__ */
|
|
7108
|
-
/* @__PURE__ */
|
|
7109
|
-
/* @__PURE__ */
|
|
7110
|
-
/* @__PURE__ */
|
|
7111
|
-
] }) : currentResult.status === "error" ? /* @__PURE__ */
|
|
7112
|
-
/* @__PURE__ */
|
|
7113
|
-
/* @__PURE__ */
|
|
7114
|
-
/* @__PURE__ */
|
|
7115
|
-
/* @__PURE__ */
|
|
7264
|
+
} }) }) : /* @__PURE__ */ jsxs28("div", { className: "flex-1 overflow-hidden flex flex-col", children: [
|
|
7265
|
+
/* @__PURE__ */ jsx30("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ jsx30("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-4 opacity-40", children: [
|
|
7266
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
|
|
7267
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[10px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
|
|
7268
|
+
] }) : currentResult.status === "error" ? /* @__PURE__ */ jsxs28("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
|
|
7269
|
+
/* @__PURE__ */ jsx30("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
|
|
7270
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col gap-2", children: [
|
|
7271
|
+
/* @__PURE__ */ jsx30("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
|
|
7272
|
+
/* @__PURE__ */ jsx30("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
|
|
7116
7273
|
] }),
|
|
7117
|
-
/* @__PURE__ */
|
|
7118
|
-
] }) : /* @__PURE__ */
|
|
7119
|
-
/* @__PURE__ */
|
|
7120
|
-
/* @__PURE__ */
|
|
7121
|
-
/* @__PURE__ */
|
|
7122
|
-
/* @__PURE__ */
|
|
7123
|
-
/* @__PURE__ */
|
|
7274
|
+
/* @__PURE__ */ jsx30(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
|
|
7275
|
+
] }) : /* @__PURE__ */ jsxs28("div", { className: "h-full w-full relative flex items-center justify-center", children: [
|
|
7276
|
+
/* @__PURE__ */ jsx30("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
|
|
7277
|
+
/* @__PURE__ */ jsxs28("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
|
|
7278
|
+
/* @__PURE__ */ jsx30(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
|
|
7279
|
+
/* @__PURE__ */ jsx30(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
|
|
7280
|
+
/* @__PURE__ */ jsx30(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
|
|
7124
7281
|
] })
|
|
7125
|
-
] }) : /* @__PURE__ */
|
|
7126
|
-
/* @__PURE__ */
|
|
7127
|
-
/* @__PURE__ */
|
|
7282
|
+
] }) : /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
|
|
7283
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
|
|
7284
|
+
/* @__PURE__ */ jsx30("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
|
|
7128
7285
|
] }) }) }),
|
|
7129
|
-
currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */
|
|
7130
|
-
/* @__PURE__ */
|
|
7286
|
+
currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ jsx30("div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ jsxs28("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
7287
|
+
/* @__PURE__ */ jsx30(
|
|
7131
7288
|
"div",
|
|
7132
7289
|
{
|
|
7133
7290
|
onClick: () => handleGallerySelect(item),
|
|
@@ -7142,10 +7299,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7142
7299
|
transition: "opacity 0.15s, border-color 0.15s"
|
|
7143
7300
|
},
|
|
7144
7301
|
className: "hover:opacity-80",
|
|
7145
|
-
children: /* @__PURE__ */
|
|
7302
|
+
children: /* @__PURE__ */ jsx30("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
|
|
7146
7303
|
}
|
|
7147
7304
|
),
|
|
7148
|
-
/* @__PURE__ */
|
|
7305
|
+
/* @__PURE__ */ jsx30(
|
|
7149
7306
|
"button",
|
|
7150
7307
|
{
|
|
7151
7308
|
onClick: (e) => {
|
|
@@ -7168,31 +7325,31 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7168
7325
|
alignItems: "center",
|
|
7169
7326
|
justifyContent: "center"
|
|
7170
7327
|
},
|
|
7171
|
-
children: /* @__PURE__ */
|
|
7328
|
+
children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined", style: { fontSize: 10, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
|
|
7172
7329
|
}
|
|
7173
7330
|
)
|
|
7174
7331
|
] }, item.id)) })
|
|
7175
7332
|
] })
|
|
7176
7333
|
] })
|
|
7177
7334
|
] }),
|
|
7178
|
-
!isRightCollapsed && /* @__PURE__ */
|
|
7179
|
-
/* @__PURE__ */
|
|
7180
|
-
/* @__PURE__ */
|
|
7181
|
-
/* @__PURE__ */
|
|
7182
|
-
["history", "gallery", "inspect", "setup", "sync", "tags"].map((tab) => /* @__PURE__ */
|
|
7335
|
+
!isRightCollapsed && /* @__PURE__ */ jsx30("div", { onMouseDown: startRightResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
|
|
7336
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col border-l border-white/5 bg-[#0e0e0e] shrink-0", style: { width: isRightCollapsed ? 60 : rightPanelWidth, transition: "none" }, children: [
|
|
7337
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex border-b border-white/5 h-14 shrink-0 overflow-hidden", children: [
|
|
7338
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-1", children: [
|
|
7339
|
+
["history", "gallery", "inspect", "setup", "sync", "tags"].map((tab) => /* @__PURE__ */ jsx30("button", { onClick: () => {
|
|
7183
7340
|
setActiveTab(tab);
|
|
7184
7341
|
setIsRightCollapsed(false);
|
|
7185
|
-
}, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */
|
|
7186
|
-
serverBaseUrl && /* @__PURE__ */
|
|
7342
|
+
}, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : tab === "inspect" ? "info" : tab === "setup" ? "settings" : tab === "sync" ? "cloud_sync" : "label" }) }, tab)),
|
|
7343
|
+
serverBaseUrl && /* @__PURE__ */ jsx30("button", { onClick: () => {
|
|
7187
7344
|
setActiveTab("server");
|
|
7188
7345
|
setIsRightCollapsed(false);
|
|
7189
|
-
}, className: `w-10 flex items-center justify-center relative transition-colors ${activeTab === "server" ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */
|
|
7346
|
+
}, className: `w-10 flex items-center justify-center relative transition-colors ${activeTab === "server" ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) })
|
|
7190
7347
|
] }),
|
|
7191
|
-
hfToken && /* @__PURE__ */
|
|
7192
|
-
/* @__PURE__ */
|
|
7348
|
+
hfToken && /* @__PURE__ */ jsx30("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-10 flex items-center justify-center text-white/20 hover:text-white/60 transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx30("span", { className: `material-symbols-outlined text-[18px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) }),
|
|
7349
|
+
/* @__PURE__ */ jsx30("button", { onClick: () => setIsRightCollapsed(!isRightCollapsed), className: "w-10 flex items-center justify-center text-white/20 hover:text-white", children: /* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[18px]", children: isRightCollapsed ? "chevron_left" : "chevron_right" }) })
|
|
7193
7350
|
] }),
|
|
7194
|
-
!isRightCollapsed && /* @__PURE__ */
|
|
7195
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */
|
|
7351
|
+
!isRightCollapsed && /* @__PURE__ */ jsxs28("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
7352
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ jsx30(
|
|
7196
7353
|
TagManagerPanel,
|
|
7197
7354
|
{
|
|
7198
7355
|
workspaceTags,
|
|
@@ -7203,12 +7360,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7203
7360
|
onTagMove: handleTagMove
|
|
7204
7361
|
}
|
|
7205
7362
|
),
|
|
7206
|
-
activeTab === "tags" && !workspaceTags && /* @__PURE__ */
|
|
7207
|
-
/* @__PURE__ */
|
|
7208
|
-
/* @__PURE__ */
|
|
7363
|
+
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ jsx30("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ jsxs28("div", { children: [
|
|
7364
|
+
/* @__PURE__ */ jsx30("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
|
|
7365
|
+
/* @__PURE__ */ jsx30("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
|
|
7209
7366
|
] }) }),
|
|
7210
|
-
activeTab === "history" && /* @__PURE__ */
|
|
7211
|
-
activeTab === "gallery" && /* @__PURE__ */
|
|
7367
|
+
activeTab === "history" && /* @__PURE__ */ jsx30(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
|
|
7368
|
+
activeTab === "gallery" && /* @__PURE__ */ jsx30(
|
|
7212
7369
|
MediaLibrary,
|
|
7213
7370
|
{
|
|
7214
7371
|
items: galleryItems,
|
|
@@ -7224,24 +7381,24 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
7224
7381
|
onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
|
|
7225
7382
|
}
|
|
7226
7383
|
),
|
|
7227
|
-
activeTab === "inspect" && /* @__PURE__ */
|
|
7228
|
-
activeTab === "setup" && /* @__PURE__ */
|
|
7229
|
-
activeTab === "sync" && /* @__PURE__ */
|
|
7384
|
+
activeTab === "inspect" && /* @__PURE__ */ jsx30(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
|
|
7385
|
+
activeTab === "setup" && /* @__PURE__ */ jsx30(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo, tagBase: tagBaseResult }),
|
|
7386
|
+
activeTab === "sync" && /* @__PURE__ */ jsx30(
|
|
7230
7387
|
HfMediaSyncTab,
|
|
7231
7388
|
{
|
|
7232
7389
|
topSlot: syncTopSlot,
|
|
7233
7390
|
onHfInitialSync: hfToken ? handleHfInitialSync : void 0
|
|
7234
7391
|
}
|
|
7235
7392
|
),
|
|
7236
|
-
activeTab === "server" && /* @__PURE__ */
|
|
7393
|
+
activeTab === "server" && /* @__PURE__ */ jsx30(ServerTab, { serverBaseUrl })
|
|
7237
7394
|
] })
|
|
7238
7395
|
] })
|
|
7239
7396
|
] });
|
|
7240
7397
|
}
|
|
7241
7398
|
|
|
7242
7399
|
// src/components/FaApp.tsx
|
|
7243
|
-
import { useState as
|
|
7244
|
-
import { jsx as
|
|
7400
|
+
import { useState as useState27, useEffect as useEffect12, useMemo as useMemo8 } from "react";
|
|
7401
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
7245
7402
|
function FaApp({
|
|
7246
7403
|
onGenerateImage,
|
|
7247
7404
|
onGeneratePrompt,
|
|
@@ -7256,19 +7413,19 @@ function FaApp({
|
|
|
7256
7413
|
serverBaseUrl,
|
|
7257
7414
|
buildInfo
|
|
7258
7415
|
}) {
|
|
7259
|
-
const [hfNamespace, setHfNamespace] =
|
|
7260
|
-
|
|
7416
|
+
const [hfNamespace, setHfNamespace] = useState27(void 0);
|
|
7417
|
+
useEffect12(() => {
|
|
7261
7418
|
if (!serverBaseUrl) return;
|
|
7262
7419
|
fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
|
|
7263
7420
|
if (typeof d.hfNamespace === "string") setHfNamespace(d.hfNamespace);
|
|
7264
7421
|
}).catch(() => {
|
|
7265
7422
|
});
|
|
7266
7423
|
}, [serverBaseUrl]);
|
|
7267
|
-
const wrappedPrompt =
|
|
7424
|
+
const wrappedPrompt = useMemo8(
|
|
7268
7425
|
() => alsFlowTextZugang(onGeneratePrompt),
|
|
7269
7426
|
[onGeneratePrompt]
|
|
7270
7427
|
);
|
|
7271
|
-
return /* @__PURE__ */
|
|
7428
|
+
return /* @__PURE__ */ jsx31(
|
|
7272
7429
|
AvatarArchitectApp,
|
|
7273
7430
|
{
|
|
7274
7431
|
onGenerateImage,
|
|
@@ -7518,15 +7675,15 @@ function createInMemoryWorkspacePersistence(now = () => Date.now()) {
|
|
|
7518
7675
|
}
|
|
7519
7676
|
|
|
7520
7677
|
// node_modules/zustand/esm/react.mjs
|
|
7521
|
-
import
|
|
7678
|
+
import React24 from "react";
|
|
7522
7679
|
var identity = (arg) => arg;
|
|
7523
7680
|
function useStore(api, selector = identity) {
|
|
7524
|
-
const slice =
|
|
7681
|
+
const slice = React24.useSyncExternalStore(
|
|
7525
7682
|
api.subscribe,
|
|
7526
|
-
|
|
7527
|
-
|
|
7683
|
+
React24.useCallback(() => selector(api.getState()), [api, selector]),
|
|
7684
|
+
React24.useCallback(() => selector(api.getInitialState()), [api, selector])
|
|
7528
7685
|
);
|
|
7529
|
-
|
|
7686
|
+
React24.useDebugValue(slice);
|
|
7530
7687
|
return slice;
|
|
7531
7688
|
}
|
|
7532
7689
|
|
|
@@ -7830,7 +7987,7 @@ function zugehoerigkeitenOf(item) {
|
|
|
7830
7987
|
}
|
|
7831
7988
|
|
|
7832
7989
|
// src/features/library/ZugehoerigkeitLinks.tsx
|
|
7833
|
-
import { Fragment as Fragment11, jsx as
|
|
7990
|
+
import { Fragment as Fragment11, jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
7834
7991
|
var CHIP_BASIS = "text-[9px] px-1.5 py-0.5 rounded-full font-bold border transition";
|
|
7835
7992
|
var CHIP_LAUF = "bg-teal-900/60 text-teal-200 border-teal-800 hover:bg-teal-800 hover:text-white";
|
|
7836
7993
|
var CHIP_SZENE = "bg-indigo-900/60 text-indigo-200 border-indigo-800 hover:bg-indigo-800 hover:text-white";
|
|
@@ -7856,8 +8013,8 @@ var ZugehoerigkeitLinks = ({
|
|
|
7856
8013
|
};
|
|
7857
8014
|
if (variante === "liste") {
|
|
7858
8015
|
if (!hatNavigationsziele(zugehoerigkeit)) return null;
|
|
7859
|
-
return /* @__PURE__ */
|
|
7860
|
-
run && /* @__PURE__ */
|
|
8016
|
+
return /* @__PURE__ */ jsxs29(Fragment11, { children: [
|
|
8017
|
+
run && /* @__PURE__ */ jsx32(
|
|
7861
8018
|
"button",
|
|
7862
8019
|
{
|
|
7863
8020
|
type: "button",
|
|
@@ -7868,7 +8025,7 @@ var ZugehoerigkeitLinks = ({
|
|
|
7868
8025
|
children: beschriftung(run, "Promptlauf")
|
|
7869
8026
|
}
|
|
7870
8027
|
),
|
|
7871
|
-
scene && /* @__PURE__ */
|
|
8028
|
+
scene && /* @__PURE__ */ jsx32(
|
|
7872
8029
|
"button",
|
|
7873
8030
|
{
|
|
7874
8031
|
type: "button",
|
|
@@ -7881,15 +8038,15 @@ var ZugehoerigkeitLinks = ({
|
|
|
7881
8038
|
)
|
|
7882
8039
|
] });
|
|
7883
8040
|
}
|
|
7884
|
-
return /* @__PURE__ */
|
|
8041
|
+
return /* @__PURE__ */ jsxs29(
|
|
7885
8042
|
"div",
|
|
7886
8043
|
{
|
|
7887
8044
|
className: "bg-black border border-neutral-800 p-2 rounded flex flex-col gap-1",
|
|
7888
8045
|
"data-testid": "zugehoerigkeit-bereich",
|
|
7889
8046
|
children: [
|
|
7890
|
-
/* @__PURE__ */
|
|
7891
|
-
/* @__PURE__ */
|
|
7892
|
-
run && /* @__PURE__ */
|
|
8047
|
+
/* @__PURE__ */ jsx32("span", { className: "text-[10px] uppercase font-bold text-neutral-500", children: "Zugeh\xF6rigkeit" }),
|
|
8048
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex flex-wrap gap-2", children: [
|
|
8049
|
+
run && /* @__PURE__ */ jsx32(
|
|
7893
8050
|
"button",
|
|
7894
8051
|
{
|
|
7895
8052
|
type: "button",
|
|
@@ -7900,7 +8057,7 @@ var ZugehoerigkeitLinks = ({
|
|
|
7900
8057
|
children: beschriftung(run, "Promptlauf \xF6ffnen")
|
|
7901
8058
|
}
|
|
7902
8059
|
),
|
|
7903
|
-
scene && /* @__PURE__ */
|
|
8060
|
+
scene && /* @__PURE__ */ jsx32(
|
|
7904
8061
|
"button",
|
|
7905
8062
|
{
|
|
7906
8063
|
type: "button",
|
|
@@ -7912,7 +8069,7 @@ var ZugehoerigkeitLinks = ({
|
|
|
7912
8069
|
}
|
|
7913
8070
|
)
|
|
7914
8071
|
] }),
|
|
7915
|
-
hinweis && /* @__PURE__ */
|
|
8072
|
+
hinweis && /* @__PURE__ */ jsx32("span", { className: "text-[10px] text-neutral-500", "data-testid": "zugehoerigkeit-hinweis", children: hinweis })
|
|
7916
8073
|
]
|
|
7917
8074
|
}
|
|
7918
8075
|
);
|
|
@@ -7997,6 +8154,7 @@ export {
|
|
|
7997
8154
|
CompactDropdown,
|
|
7998
8155
|
FaApp,
|
|
7999
8156
|
FaToolsBadge,
|
|
8157
|
+
FlowBridgePanel,
|
|
8000
8158
|
FlowWorkspacePicker,
|
|
8001
8159
|
GLOBAL_STYLES,
|
|
8002
8160
|
HfMediaSyncTab,
|
|
@@ -8040,6 +8198,7 @@ export {
|
|
|
8040
8198
|
buildScanInstruction,
|
|
8041
8199
|
cleanAiResponse,
|
|
8042
8200
|
createFaStore,
|
|
8201
|
+
createFlowBridgeClient,
|
|
8043
8202
|
createFlowServices,
|
|
8044
8203
|
createInMemoryLibraryDataSource,
|
|
8045
8204
|
createInMemoryWorkspacePersistence,
|