feat: update warm multimodal composer ui
#6
by ADJCJH - opened
- DESIGN.md +36 -29
- app.py +1016 -70
- design-qa.md +24 -0
- docs/handoff.md +28 -16
- dream_customs/app_logic.py +4 -0
- dream_customs/render.py +26 -30
DESIGN.md
CHANGED
|
@@ -2,17 +2,18 @@
|
|
| 2 |
name: Dream Customs
|
| 3 |
description: A nocturnal dream customs workbench for turning dream evidence into a next-day pact.
|
| 4 |
colors:
|
| 5 |
-
bg-night: "oklch(0.
|
| 6 |
-
bg-void: "oklch(0.
|
| 7 |
-
surface-ink: "oklch(0.
|
| 8 |
-
surface-raised: "oklch(0.
|
| 9 |
-
primary-
|
| 10 |
-
primary-
|
| 11 |
-
accent-coral-stamp: "oklch(0.
|
| 12 |
-
accent-
|
| 13 |
-
|
| 14 |
-
ink-
|
| 15 |
-
|
|
|
|
| 16 |
warning: "oklch(0.760 0.150 75)"
|
| 17 |
typography:
|
| 18 |
display:
|
|
@@ -20,7 +21,7 @@ typography:
|
|
| 20 |
fontSize: "2.25rem"
|
| 21 |
fontWeight: 760
|
| 22 |
lineHeight: 1.05
|
| 23 |
-
letterSpacing: "
|
| 24 |
headline:
|
| 25 |
fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif"
|
| 26 |
fontSize: "1.5rem"
|
|
@@ -54,7 +55,7 @@ spacing:
|
|
| 54 |
xl: "32px"
|
| 55 |
components:
|
| 56 |
button-primary:
|
| 57 |
-
backgroundColor: "{colors.primary-
|
| 58 |
textColor: "{colors.ink-main}"
|
| 59 |
rounded: "{rounded.md}"
|
| 60 |
padding: "12px 16px"
|
|
@@ -74,15 +75,17 @@ components:
|
|
| 74 |
|
| 75 |
## 1. Overview
|
| 76 |
|
| 77 |
-
**Creative North Star: "The
|
| 78 |
|
| 79 |
-
Dream Customs should feel like a
|
| 80 |
|
| 81 |
-
This is product UI first. The user needs to type,
|
|
|
|
|
|
|
| 82 |
|
| 83 |
**Key Characteristics:**
|
| 84 |
|
| 85 |
-
-
|
| 86 |
- Conversation timeline for declarations, questions, and pact drafts.
|
| 87 |
- Evidence tray for text, image, audio, mood, and model status.
|
| 88 |
- Pact inspector that can be drafted, revised, or sealed.
|
|
@@ -94,22 +97,23 @@ The palette is nocturnal and atmospheric: neutral dark surfaces, cobalt primary
|
|
| 94 |
|
| 95 |
### Primary
|
| 96 |
|
| 97 |
-
- **
|
| 98 |
-
- **Deep
|
| 99 |
|
| 100 |
### Secondary
|
| 101 |
|
| 102 |
-
- **Coral Stamp Ink** (`oklch(0.
|
| 103 |
-
- **
|
|
|
|
| 104 |
|
| 105 |
### Neutral
|
| 106 |
|
| 107 |
-
- **Night Background** (`oklch(0.
|
| 108 |
-
- **Void Rail** (`oklch(0.
|
| 109 |
-
- **Ink Surface** (`oklch(0.
|
| 110 |
-
- **Raised Surface** (`oklch(0.
|
| 111 |
-
- **Main Ink** (`oklch(0.
|
| 112 |
-
- **Muted Ink** (`oklch(0.760 0.
|
| 113 |
|
| 114 |
### Named Rules
|
| 115 |
|
|
@@ -194,7 +198,8 @@ The pact inspector is a live customs file, not just a final HTML card. It shows
|
|
| 194 |
|
| 195 |
### Do:
|
| 196 |
|
| 197 |
-
- **Do** make the
|
|
|
|
| 198 |
- **Do** keep every phase actionable with one clear next step.
|
| 199 |
- **Do** use generated raster imagery for the dream atmosphere, header state, or empty state.
|
| 200 |
- **Do** verify dark-mode contrast for body text, labels, placeholders, chips, and disabled controls.
|
|
@@ -205,6 +210,8 @@ The pact inspector is a live customs file, not just a final HTML card. It shows
|
|
| 205 |
- **Don't** ship a plain Gradio two-column form as the primary experience.
|
| 206 |
- **Don't** use beige parchment, tarot, faux therapy, or generic purple AI visuals.
|
| 207 |
- **Don't** use one-shot generation as the whole flow.
|
| 208 |
-
- **Don't**
|
|
|
|
|
|
|
| 209 |
- **Don't** pair a 1px border with a large soft shadow on every card.
|
| 210 |
- **Don't** use side-stripe borders, gradient text, or decorative glass panels.
|
|
|
|
| 2 |
name: Dream Customs
|
| 3 |
description: A nocturnal dream customs workbench for turning dream evidence into a next-day pact.
|
| 4 |
colors:
|
| 5 |
+
bg-night: "oklch(0.185 0.018 55)"
|
| 6 |
+
bg-void: "oklch(0.130 0.012 55)"
|
| 7 |
+
surface-ink: "oklch(0.235 0.018 58)"
|
| 8 |
+
surface-raised: "oklch(0.295 0.020 62)"
|
| 9 |
+
primary-sage: "oklch(0.690 0.105 150)"
|
| 10 |
+
primary-sage-deep: "oklch(0.455 0.090 155)"
|
| 11 |
+
accent-coral-stamp: "oklch(0.700 0.140 32)"
|
| 12 |
+
accent-amber-lamp: "oklch(0.830 0.120 76)"
|
| 13 |
+
accent-aurora: "oklch(0.745 0.080 185)"
|
| 14 |
+
ink-main: "oklch(0.960 0.010 78)"
|
| 15 |
+
ink-muted: "oklch(0.760 0.018 78)"
|
| 16 |
+
border-dream: "oklch(0.465 0.024 70)"
|
| 17 |
warning: "oklch(0.760 0.150 75)"
|
| 18 |
typography:
|
| 19 |
display:
|
|
|
|
| 21 |
fontSize: "2.25rem"
|
| 22 |
fontWeight: 760
|
| 23 |
lineHeight: 1.05
|
| 24 |
+
letterSpacing: "0"
|
| 25 |
headline:
|
| 26 |
fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif"
|
| 27 |
fontSize: "1.5rem"
|
|
|
|
| 55 |
xl: "32px"
|
| 56 |
components:
|
| 57 |
button-primary:
|
| 58 |
+
backgroundColor: "{colors.primary-sage-deep}"
|
| 59 |
textColor: "{colors.ink-main}"
|
| 60 |
rounded: "{rounded.md}"
|
| 61 |
padding: "12px 16px"
|
|
|
|
| 75 |
|
| 76 |
## 1. Overview
|
| 77 |
|
| 78 |
+
**Creative North Star: "The Morning Customs Desk"**
|
| 79 |
|
| 80 |
+
Dream Customs should feel like a small warm customs desk that appears after waking: quiet, slightly strange, and easy enough to use before the day fully starts. The surface can stay dark like Codex, but it should read as warm charcoal and lamplight rather than a cold technical dashboard. Sage action color, amber light, muted coral seal ink, and a little aurora evidence color carry the identity.
|
| 81 |
|
| 82 |
+
This is product UI first. The user needs to type, attach, optionally add voice, answer, and decide what happens next. The dream atmosphere belongs in the background wash, pact inspector, stamps, and evidence chips, while controls stay clear and predictable.
|
| 83 |
+
|
| 84 |
+
**V4 Unified Composer Rule.** The dream input should behave like a Codex-style multimodal composer, not like a Gradio form. Text, image upload, voice upload, mood, add-material, and send belong visually inside one rounded input surface. Technical model routes and advanced workflow shortcuts should be collapsed by default.
|
| 85 |
|
| 86 |
**Key Characteristics:**
|
| 87 |
|
| 88 |
+
- Unified composer as the primary input, modeled after Codex app behavior.
|
| 89 |
- Conversation timeline for declarations, questions, and pact drafts.
|
| 90 |
- Evidence tray for text, image, audio, mood, and model status.
|
| 91 |
- Pact inspector that can be drafted, revised, or sealed.
|
|
|
|
| 97 |
|
| 98 |
### Primary
|
| 99 |
|
| 100 |
+
- **Sage Gate** (`oklch(0.690 0.105 150)`): primary selection, active step, focus accents, and subtle interactive outlines.
|
| 101 |
+
- **Deep Sage Gate** (`oklch(0.455 0.090 155)`): filled primary buttons and selected composer controls with near-white text.
|
| 102 |
|
| 103 |
### Secondary
|
| 104 |
|
| 105 |
+
- **Coral Stamp Ink** (`oklch(0.700 0.140 32)`): final seal action, permit stamp, alert edge for safety notes, and one memorable highlight per screen.
|
| 106 |
+
- **Amber Lamp** (`oklch(0.830 0.120 76)`): warmth, trust cue, and section highlights.
|
| 107 |
+
- **Aurora Evidence Light** (`oklch(0.745 0.080 185)`): image/audio evidence status, successful extraction, and soft dream-glow details.
|
| 108 |
|
| 109 |
### Neutral
|
| 110 |
|
| 111 |
+
- **Warm Night Background** (`oklch(0.185 0.018 55)`): app body and mobile shell.
|
| 112 |
+
- **Soft Void Rail** (`oklch(0.130 0.012 55)`): app outer edge, header underlay, and screenshot-safe negative space.
|
| 113 |
+
- **Charcoal Ink Surface** (`oklch(0.235 0.018 58)`): composer, timeline items, and tool panels.
|
| 114 |
+
- **Raised Warm Surface** (`oklch(0.295 0.020 62)`): active inspector panels and output cards.
|
| 115 |
+
- **Main Ink** (`oklch(0.960 0.010 78)`): body text on dark surfaces.
|
| 116 |
+
- **Muted Ink** (`oklch(0.760 0.018 78)`): secondary labels that still remain readable.
|
| 117 |
|
| 118 |
### Named Rules
|
| 119 |
|
|
|
|
| 198 |
|
| 199 |
### Do:
|
| 200 |
|
| 201 |
+
- **Do** make the unified composer the most obvious control on mobile and desktop.
|
| 202 |
+
- **Do** keep the first declaration controls above the timeline so a tired user can start immediately.
|
| 203 |
- **Do** keep every phase actionable with one clear next step.
|
| 204 |
- **Do** use generated raster imagery for the dream atmosphere, header state, or empty state.
|
| 205 |
- **Do** verify dark-mode contrast for body text, labels, placeholders, chips, and disabled controls.
|
|
|
|
| 210 |
- **Don't** ship a plain Gradio two-column form as the primary experience.
|
| 211 |
- **Don't** use beige parchment, tarot, faux therapy, or generic purple AI visuals.
|
| 212 |
- **Don't** use one-shot generation as the whole flow.
|
| 213 |
+
- **Don't** expose technical model routes as first-level controls unless the user opens model settings.
|
| 214 |
+
- **Don't** render navigation-looking text that cannot be clicked.
|
| 215 |
+
- **Don't** reserve tall empty panels for future content on the first screen.
|
| 216 |
- **Don't** pair a 1px border with a large soft shadow on every card.
|
| 217 |
- **Don't** use side-stripe borders, gradient text, or decorative glass panels.
|
app.py
CHANGED
|
@@ -624,6 +624,891 @@ body,
|
|
| 624 |
transition-duration: 0.001ms !important;
|
| 625 |
}
|
| 626 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
"""
|
| 628 |
|
| 629 |
|
|
@@ -645,87 +1530,148 @@ def build_demo() -> gr.Blocks:
|
|
| 645 |
with gr.Column(elem_classes=["dc-app-shell"]):
|
| 646 |
status_html = gr.HTML()
|
| 647 |
|
| 648 |
-
with gr.Row(elem_classes=["dc-
|
| 649 |
-
with gr.Column(scale=7, elem_classes=["dc-
|
| 650 |
-
|
| 651 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 652 |
inspector_html = gr.HTML()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
|
| 654 |
-
|
| 655 |
-
notice_html = gr.HTML()
|
| 656 |
-
dream_text = gr.Textbox(
|
| 657 |
-
label="Dream material",
|
| 658 |
-
lines=4,
|
| 659 |
-
value="我梦见一部迟到的电梯,按钮都融化了,我一直到不了 14 楼。",
|
| 660 |
-
placeholder="Type the dream, a fragment, or a new piece of material.",
|
| 661 |
-
)
|
| 662 |
-
with gr.Row():
|
| 663 |
-
image_input = gr.Image(label="Attach image", type="filepath", height=150)
|
| 664 |
-
audio_input = gr.Audio(label="Record voice", type="filepath")
|
| 665 |
-
mood = gr.Dropdown(
|
| 666 |
-
label="Mood chip",
|
| 667 |
-
choices=["foggy", "anxious", "curious", "tired", "restless", "calm"],
|
| 668 |
-
value="foggy",
|
| 669 |
-
)
|
| 670 |
-
with gr.Row():
|
| 671 |
-
answer_text = gr.Textbox(
|
| 672 |
-
label="Answer to the clerk",
|
| 673 |
-
lines=2,
|
| 674 |
-
value="我想和它结盟,但今天只想完成一件很小的事。",
|
| 675 |
-
placeholder="Answer a customs question, or leave blank and skip.",
|
| 676 |
-
)
|
| 677 |
-
revision_request = gr.Textbox(
|
| 678 |
-
label="Revision request",
|
| 679 |
-
lines=2,
|
| 680 |
-
value="Make it gentler and more specific for today.",
|
| 681 |
-
placeholder="Try: make it stranger, make it gentler, or make the action smaller.",
|
| 682 |
-
)
|
| 683 |
-
with gr.Row():
|
| 684 |
-
text_backend = gr.Dropdown(
|
| 685 |
-
label="Text route",
|
| 686 |
-
choices=["demo", "model", "ollama"],
|
| 687 |
-
value="demo",
|
| 688 |
-
)
|
| 689 |
-
vision_backend = gr.Dropdown(
|
| 690 |
-
label="Vision route",
|
| 691 |
-
choices=["demo", "model", "ollama"],
|
| 692 |
-
value="demo",
|
| 693 |
-
)
|
| 694 |
-
with gr.Row(elem_classes=["dc-action-row"]):
|
| 695 |
-
send_btn = gr.Button("Send to customs", elem_classes=["dc-primary"])
|
| 696 |
-
add_btn = gr.Button("Add material")
|
| 697 |
-
ask_btn = gr.Button("Ask another question")
|
| 698 |
-
answer_btn = gr.Button("Answer question")
|
| 699 |
-
skip_btn = gr.Button("Skip question")
|
| 700 |
-
draft_btn = gr.Button("Draft pact")
|
| 701 |
-
revise_btn = gr.Button("Revise pact")
|
| 702 |
-
seal_btn = gr.Button("Seal today's pact", elem_classes=["dc-seal-button"])
|
| 703 |
-
new_btn = gr.Button("Start a new declaration")
|
| 704 |
-
|
| 705 |
-
sealed_html = gr.HTML(elem_classes=["dc-sealed-output"])
|
| 706 |
|
| 707 |
with gr.Accordion("Diagnostics", open=False, elem_classes=["dc-diagnostics"]):
|
| 708 |
debug_json = gr.Code(label="Session state", language="json")
|
| 709 |
|
| 710 |
-
gr.
|
| 711 |
-
|
| 712 |
-
[
|
| 713 |
-
|
| 714 |
-
|
| 715 |
-
|
| 716 |
-
|
| 717 |
-
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
|
|
|
|
|
|
| 721 |
],
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
)
|
| 725 |
|
| 726 |
outputs = _outputs(session_state, status_html, timeline_html, inspector_html, sealed_html, debug_json, notice_html)
|
| 727 |
demo.load(initial_workbench_state, outputs=outputs, api_name=False)
|
| 728 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 729 |
send_btn.click(
|
| 730 |
start_declaration_action,
|
| 731 |
inputs=[session_state, dream_text, image_input, audio_input, mood, text_backend, vision_backend],
|
|
|
|
| 624 |
transition-duration: 0.001ms !important;
|
| 625 |
}
|
| 626 |
}
|
| 627 |
+
|
| 628 |
+
/* V3 rescue: first-screen trust, real phase actions, and no empty panel cliffs. */
|
| 629 |
+
:root {
|
| 630 |
+
--dc-lamp: oklch(0.825 0.105 78);
|
| 631 |
+
--dc-plum: oklch(0.265 0.055 312);
|
| 632 |
+
--dc-warm-line: oklch(0.680 0.070 62);
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
.gradio-container {
|
| 636 |
+
min-height: auto !important;
|
| 637 |
+
padding-left: 0 !important;
|
| 638 |
+
padding-right: 0 !important;
|
| 639 |
+
}
|
| 640 |
+
|
| 641 |
+
.dc-app-shell {
|
| 642 |
+
gap: 12px !important;
|
| 643 |
+
min-height: auto;
|
| 644 |
+
padding: 14px clamp(10px, 2vw, 22px) 18px;
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
.dc-statusbar {
|
| 648 |
+
background:
|
| 649 |
+
linear-gradient(110deg, oklch(0.080 0.010 250 / 0.92), oklch(0.265 0.055 312 / 0.70)),
|
| 650 |
+
url("/file=docs/design/assets/dream-customs-probe-night-desk.png");
|
| 651 |
+
background-position: center 42%;
|
| 652 |
+
background-size: cover;
|
| 653 |
+
border-color: oklch(0.680 0.070 62 / 0.42);
|
| 654 |
+
grid-template-columns: minmax(260px, 1fr) minmax(260px, auto);
|
| 655 |
+
min-height: auto;
|
| 656 |
+
padding: 14px 16px;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
.dc-statusbar::before {
|
| 660 |
+
background:
|
| 661 |
+
radial-gradient(circle at 18% 18%, oklch(0.825 0.105 78 / 0.16), transparent 18rem),
|
| 662 |
+
linear-gradient(90deg, oklch(0.080 0.010 250 / 0.90), oklch(0.145 0.030 238 / 0.66));
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
.dc-brand-mark {
|
| 666 |
+
background: linear-gradient(135deg, var(--dc-primary-deep), oklch(0.265 0.055 312));
|
| 667 |
+
border-color: oklch(0.825 0.105 78 / 0.58);
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
.dc-system-status span {
|
| 671 |
+
background: oklch(0.080 0.010 250 / 0.72);
|
| 672 |
+
border-color: oklch(0.680 0.070 62 / 0.34);
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
.dc-stage-nav {
|
| 676 |
+
align-items: stretch !important;
|
| 677 |
+
background: oklch(0.145 0.030 238 / 0.92);
|
| 678 |
+
border: 1px solid oklch(0.430 0.055 235 / 0.70);
|
| 679 |
+
border-radius: var(--dc-radius-lg);
|
| 680 |
+
display: grid !important;
|
| 681 |
+
gap: 8px !important;
|
| 682 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 683 |
+
padding: 8px;
|
| 684 |
+
}
|
| 685 |
+
|
| 686 |
+
.dc-stage-nav button {
|
| 687 |
+
background: oklch(0.205 0.035 238) !important;
|
| 688 |
+
border: 1px solid oklch(0.430 0.055 235 / 0.78) !important;
|
| 689 |
+
border-radius: var(--dc-radius-md) !important;
|
| 690 |
+
color: var(--dc-ink-main) !important;
|
| 691 |
+
font-weight: 760 !important;
|
| 692 |
+
min-height: 42px !important;
|
| 693 |
+
white-space: normal !important;
|
| 694 |
+
}
|
| 695 |
+
|
| 696 |
+
.dc-stage-nav button:hover {
|
| 697 |
+
background: oklch(0.275 0.045 236) !important;
|
| 698 |
+
border-color: var(--dc-primary) !important;
|
| 699 |
+
}
|
| 700 |
+
|
| 701 |
+
.dc-stage-nav .dc-stage-seal button {
|
| 702 |
+
border-color: oklch(0.705 0.160 28 / 0.72) !important;
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
.dc-focus-grid {
|
| 706 |
+
align-items: start !important;
|
| 707 |
+
display: grid !important;
|
| 708 |
+
gap: 14px !important;
|
| 709 |
+
grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.65fr);
|
| 710 |
+
}
|
| 711 |
+
|
| 712 |
+
.dc-declaration-column,
|
| 713 |
+
.dc-side-rail {
|
| 714 |
+
min-width: 0 !important;
|
| 715 |
+
}
|
| 716 |
+
|
| 717 |
+
.dc-side-rail {
|
| 718 |
+
gap: 12px !important;
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
.dc-composer-panel {
|
| 722 |
+
background:
|
| 723 |
+
radial-gradient(circle at 0% 0%, oklch(0.825 0.105 78 / 0.10), transparent 18rem),
|
| 724 |
+
linear-gradient(145deg, oklch(0.205 0.035 238 / 0.98), oklch(0.265 0.055 312 / 0.38));
|
| 725 |
+
border-color: oklch(0.680 0.070 62 / 0.38);
|
| 726 |
+
bottom: auto;
|
| 727 |
+
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.24);
|
| 728 |
+
padding: 16px;
|
| 729 |
+
position: relative;
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
.dc-composer-head {
|
| 733 |
+
align-items: end;
|
| 734 |
+
display: flex;
|
| 735 |
+
gap: 12px;
|
| 736 |
+
justify-content: space-between;
|
| 737 |
+
margin-bottom: 12px;
|
| 738 |
+
}
|
| 739 |
+
|
| 740 |
+
.dc-composer-head h2 {
|
| 741 |
+
color: var(--dc-ink-main);
|
| 742 |
+
font-size: 1.18rem;
|
| 743 |
+
line-height: 1.18;
|
| 744 |
+
margin: 0;
|
| 745 |
+
}
|
| 746 |
+
|
| 747 |
+
.dc-composer-head p {
|
| 748 |
+
color: var(--dc-ink-muted);
|
| 749 |
+
font-size: 0.92rem;
|
| 750 |
+
line-height: 1.45;
|
| 751 |
+
margin: 4px 0 0;
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
.dc-trust-pill {
|
| 755 |
+
background: oklch(0.825 0.105 78 / 0.12);
|
| 756 |
+
border: 1px solid oklch(0.825 0.105 78 / 0.40);
|
| 757 |
+
border-radius: 999px;
|
| 758 |
+
color: oklch(0.920 0.055 78);
|
| 759 |
+
flex: 0 0 auto;
|
| 760 |
+
font-size: 0.78rem;
|
| 761 |
+
font-weight: 760;
|
| 762 |
+
padding: 8px 10px;
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
.dc-declaration-row {
|
| 766 |
+
align-items: stretch !important;
|
| 767 |
+
display: grid !important;
|
| 768 |
+
gap: 10px !important;
|
| 769 |
+
grid-template-columns: minmax(0, 1fr) minmax(168px, 210px);
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
.dc-primary-stack {
|
| 773 |
+
display: grid !important;
|
| 774 |
+
gap: 8px !important;
|
| 775 |
+
}
|
| 776 |
+
|
| 777 |
+
.dc-primary-stack button {
|
| 778 |
+
background: oklch(0.205 0.035 238) !important;
|
| 779 |
+
border: 1px solid oklch(0.430 0.055 235 / 0.78) !important;
|
| 780 |
+
color: var(--dc-ink-main) !important;
|
| 781 |
+
min-height: 52px !important;
|
| 782 |
+
white-space: normal !important;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
.dc-primary-stack .dc-primary,
|
| 786 |
+
.dc-primary-stack .dc-primary button {
|
| 787 |
+
background: var(--dc-primary-deep) !important;
|
| 788 |
+
border-color: var(--dc-primary) !important;
|
| 789 |
+
color: var(--dc-ink-main) !important;
|
| 790 |
+
}
|
| 791 |
+
|
| 792 |
+
.dc-primary-stack .dc-seal-button,
|
| 793 |
+
.dc-primary-stack .dc-seal-button button {
|
| 794 |
+
background: var(--dc-coral) !important;
|
| 795 |
+
border-color: var(--dc-coral) !important;
|
| 796 |
+
color: var(--dc-bg-void) !important;
|
| 797 |
+
}
|
| 798 |
+
|
| 799 |
+
.dc-evidence-grid {
|
| 800 |
+
align-items: stretch !important;
|
| 801 |
+
display: grid !important;
|
| 802 |
+
gap: 10px !important;
|
| 803 |
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(170px, 220px);
|
| 804 |
+
}
|
| 805 |
+
|
| 806 |
+
.dc-route-row,
|
| 807 |
+
.dc-followup-grid {
|
| 808 |
+
display: grid !important;
|
| 809 |
+
gap: 10px !important;
|
| 810 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 811 |
+
}
|
| 812 |
+
|
| 813 |
+
.dc-secondary-actions {
|
| 814 |
+
align-items: stretch !important;
|
| 815 |
+
display: flex !important;
|
| 816 |
+
flex-wrap: wrap !important;
|
| 817 |
+
gap: 8px !important;
|
| 818 |
+
}
|
| 819 |
+
|
| 820 |
+
.dc-secondary-actions > * {
|
| 821 |
+
flex: 1 1 140px !important;
|
| 822 |
+
min-width: 132px !important;
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
.dc-secondary-actions button {
|
| 826 |
+
background: oklch(0.205 0.035 238) !important;
|
| 827 |
+
border: 1px solid oklch(0.430 0.055 235 / 0.78) !important;
|
| 828 |
+
color: var(--dc-ink-main) !important;
|
| 829 |
+
min-height: 42px !important;
|
| 830 |
+
white-space: normal !important;
|
| 831 |
+
}
|
| 832 |
+
|
| 833 |
+
.dc-secondary-actions button:hover {
|
| 834 |
+
background: oklch(0.275 0.045 236) !important;
|
| 835 |
+
border-color: var(--dc-primary) !important;
|
| 836 |
+
}
|
| 837 |
+
|
| 838 |
+
.dc-timeline-shell,
|
| 839 |
+
.dc-inspector {
|
| 840 |
+
min-height: auto;
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
.dc-timeline-shell {
|
| 844 |
+
padding: 16px;
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
.dc-inspector {
|
| 848 |
+
background:
|
| 849 |
+
radial-gradient(circle at 100% 0%, oklch(0.825 0.105 78 / 0.07), transparent 14rem),
|
| 850 |
+
oklch(0.205 0.035 238 / 0.96);
|
| 851 |
+
padding: 16px;
|
| 852 |
+
}
|
| 853 |
+
|
| 854 |
+
.dc-inspector dl {
|
| 855 |
+
margin: 12px 0;
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
.dc-timeline-list {
|
| 859 |
+
gap: 8px;
|
| 860 |
+
}
|
| 861 |
+
|
| 862 |
+
.dc-sealed-output:empty {
|
| 863 |
+
display: none !important;
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
.dc-composer-panel .block,
|
| 867 |
+
.dc-composer-panel .container,
|
| 868 |
+
.dc-composer-panel .input-container,
|
| 869 |
+
.dc-composer-panel .wrap,
|
| 870 |
+
.dc-composer-panel .wrap.default,
|
| 871 |
+
.dc-composer-panel .wrap.svelte-1cl284s {
|
| 872 |
+
background: oklch(0.130 0.024 238) !important;
|
| 873 |
+
border-color: oklch(0.680 0.070 62 / 0.34) !important;
|
| 874 |
+
}
|
| 875 |
+
|
| 876 |
+
.dc-composer-panel textarea,
|
| 877 |
+
.dc-composer-panel input,
|
| 878 |
+
.dc-composer-panel select,
|
| 879 |
+
.dc-composer-panel [role="combobox"] {
|
| 880 |
+
background: oklch(0.105 0.018 245) !important;
|
| 881 |
+
border-color: oklch(0.430 0.055 235 / 0.82) !important;
|
| 882 |
+
color: var(--dc-ink-main) !important;
|
| 883 |
+
}
|
| 884 |
+
|
| 885 |
+
.dc-composer-panel .upload-container,
|
| 886 |
+
.dc-composer-panel .image-container,
|
| 887 |
+
.dc-composer-panel .audio-container,
|
| 888 |
+
.dc-composer-panel .upload-container button,
|
| 889 |
+
.dc-composer-panel .audio-container button {
|
| 890 |
+
background: oklch(0.105 0.018 245) !important;
|
| 891 |
+
border-color: oklch(0.680 0.070 62 / 0.28) !important;
|
| 892 |
+
color: var(--dc-ink-muted) !important;
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
.dc-composer-panel .image-container,
|
| 896 |
+
.dc-composer-panel .audio-container {
|
| 897 |
+
min-height: 112px !important;
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
.dc-composer-panel label,
|
| 901 |
+
.dc-composer-panel .label-wrap span,
|
| 902 |
+
.dc-composer-panel [data-testid="block-label"] {
|
| 903 |
+
color: oklch(0.900 0.020 235) !important;
|
| 904 |
+
}
|
| 905 |
+
|
| 906 |
+
.dc-composer-panel .label-wrap {
|
| 907 |
+
background: oklch(0.130 0.024 238) !important;
|
| 908 |
+
border: 1px solid oklch(0.680 0.070 62 / 0.30) !important;
|
| 909 |
+
border-radius: 999px !important;
|
| 910 |
+
}
|
| 911 |
+
|
| 912 |
+
.dc-composer-panel label.float {
|
| 913 |
+
background: oklch(0.130 0.024 238) !important;
|
| 914 |
+
border-color: oklch(0.680 0.070 62 / 0.34) !important;
|
| 915 |
+
color: oklch(0.900 0.020 235) !important;
|
| 916 |
+
}
|
| 917 |
+
|
| 918 |
+
.dc-composer-panel .label-wrap svg {
|
| 919 |
+
color: var(--dc-aurora) !important;
|
| 920 |
+
}
|
| 921 |
+
|
| 922 |
+
.options,
|
| 923 |
+
.option,
|
| 924 |
+
ul.options,
|
| 925 |
+
.dropdown-options {
|
| 926 |
+
background: oklch(0.130 0.024 238) !important;
|
| 927 |
+
color: var(--dc-ink-main) !important;
|
| 928 |
+
}
|
| 929 |
+
|
| 930 |
+
.options li,
|
| 931 |
+
.option {
|
| 932 |
+
color: var(--dc-ink-main) !important;
|
| 933 |
+
}
|
| 934 |
+
|
| 935 |
+
.dc-diagnostics,
|
| 936 |
+
.dc-examples {
|
| 937 |
+
margin-top: 2px;
|
| 938 |
+
}
|
| 939 |
+
|
| 940 |
+
@media (max-width: 980px) {
|
| 941 |
+
.dc-focus-grid {
|
| 942 |
+
grid-template-columns: 1fr;
|
| 943 |
+
}
|
| 944 |
+
|
| 945 |
+
.dc-stage-nav {
|
| 946 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 947 |
+
}
|
| 948 |
+
|
| 949 |
+
.dc-declaration-row {
|
| 950 |
+
grid-template-columns: 1fr;
|
| 951 |
+
}
|
| 952 |
+
|
| 953 |
+
.dc-primary-stack {
|
| 954 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
.dc-evidence-grid {
|
| 958 |
+
grid-template-columns: 1fr;
|
| 959 |
+
}
|
| 960 |
+
}
|
| 961 |
+
|
| 962 |
+
@media (max-width: 620px) {
|
| 963 |
+
*,
|
| 964 |
+
*::before,
|
| 965 |
+
*::after {
|
| 966 |
+
box-sizing: border-box !important;
|
| 967 |
+
}
|
| 968 |
+
|
| 969 |
+
html,
|
| 970 |
+
body,
|
| 971 |
+
.gradio-container,
|
| 972 |
+
.dc-app-shell {
|
| 973 |
+
max-width: 100vw !important;
|
| 974 |
+
overflow-x: hidden !important;
|
| 975 |
+
}
|
| 976 |
+
|
| 977 |
+
.gradio-container,
|
| 978 |
+
.gradio-container .main,
|
| 979 |
+
.gradio-container .wrap,
|
| 980 |
+
.gradio-container .contain {
|
| 981 |
+
margin-left: 0 !important;
|
| 982 |
+
margin-right: 0 !important;
|
| 983 |
+
padding-left: 0 !important;
|
| 984 |
+
padding-right: 0 !important;
|
| 985 |
+
}
|
| 986 |
+
|
| 987 |
+
.dc-app-shell {
|
| 988 |
+
margin: 0 !important;
|
| 989 |
+
padding: 10px !important;
|
| 990 |
+
width: 100vw !important;
|
| 991 |
+
}
|
| 992 |
+
|
| 993 |
+
.dc-statusbar,
|
| 994 |
+
.dc-stage-nav,
|
| 995 |
+
.dc-focus-grid,
|
| 996 |
+
.dc-composer-panel,
|
| 997 |
+
.dc-timeline-shell,
|
| 998 |
+
.dc-inspector {
|
| 999 |
+
max-width: 100% !important;
|
| 1000 |
+
min-width: 0 !important;
|
| 1001 |
+
width: 100% !important;
|
| 1002 |
+
}
|
| 1003 |
+
|
| 1004 |
+
.dc-statusbar {
|
| 1005 |
+
grid-template-columns: 1fr;
|
| 1006 |
+
}
|
| 1007 |
+
|
| 1008 |
+
.dc-brand-lockup,
|
| 1009 |
+
.dc-brand-lockup > div,
|
| 1010 |
+
.dc-system-status {
|
| 1011 |
+
min-width: 0 !important;
|
| 1012 |
+
}
|
| 1013 |
+
|
| 1014 |
+
.dc-brand-lockup p {
|
| 1015 |
+
max-width: 100% !important;
|
| 1016 |
+
overflow-wrap: anywhere;
|
| 1017 |
+
}
|
| 1018 |
+
|
| 1019 |
+
.dc-brand-lockup h1 {
|
| 1020 |
+
font-size: 1rem;
|
| 1021 |
+
overflow-wrap: anywhere;
|
| 1022 |
+
}
|
| 1023 |
+
|
| 1024 |
+
.dc-system-status {
|
| 1025 |
+
justify-content: flex-start;
|
| 1026 |
+
}
|
| 1027 |
+
|
| 1028 |
+
.dc-system-status span {
|
| 1029 |
+
font-size: 0.74rem;
|
| 1030 |
+
padding: 7px 8px;
|
| 1031 |
+
white-space: normal;
|
| 1032 |
+
}
|
| 1033 |
+
|
| 1034 |
+
.dc-stage-nav button {
|
| 1035 |
+
min-width: 0 !important;
|
| 1036 |
+
}
|
| 1037 |
+
|
| 1038 |
+
.dc-composer-head {
|
| 1039 |
+
align-items: flex-start;
|
| 1040 |
+
flex-direction: column;
|
| 1041 |
+
}
|
| 1042 |
+
|
| 1043 |
+
.dc-stage-nav {
|
| 1044 |
+
gap: 6px !important;
|
| 1045 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 1046 |
+
padding: 6px;
|
| 1047 |
+
}
|
| 1048 |
+
|
| 1049 |
+
.dc-stage-nav button {
|
| 1050 |
+
font-size: 0.86rem !important;
|
| 1051 |
+
min-height: 40px !important;
|
| 1052 |
+
padding-left: 6px !important;
|
| 1053 |
+
padding-right: 6px !important;
|
| 1054 |
+
}
|
| 1055 |
+
|
| 1056 |
+
.dc-composer-panel {
|
| 1057 |
+
padding: 14px;
|
| 1058 |
+
}
|
| 1059 |
+
|
| 1060 |
+
.dc-primary-stack button {
|
| 1061 |
+
min-height: 48px !important;
|
| 1062 |
+
}
|
| 1063 |
+
|
| 1064 |
+
.dc-primary-stack .dc-draft-button,
|
| 1065 |
+
.dc-primary-stack .dc-seal-button {
|
| 1066 |
+
display: none !important;
|
| 1067 |
+
}
|
| 1068 |
+
|
| 1069 |
+
.dc-composer-panel textarea {
|
| 1070 |
+
min-height: 116px !important;
|
| 1071 |
+
}
|
| 1072 |
+
|
| 1073 |
+
.dc-primary-stack,
|
| 1074 |
+
.dc-route-row,
|
| 1075 |
+
.dc-followup-grid {
|
| 1076 |
+
grid-template-columns: 1fr;
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
.dc-secondary-actions > * {
|
| 1080 |
+
flex-basis: 100% !important;
|
| 1081 |
+
}
|
| 1082 |
+
}
|
| 1083 |
+
|
| 1084 |
+
/* V4: warm, simple Codex-like multimodal composer. */
|
| 1085 |
+
:root {
|
| 1086 |
+
--dc-bg-night: oklch(0.185 0.018 55);
|
| 1087 |
+
--dc-bg-void: oklch(0.130 0.012 55);
|
| 1088 |
+
--dc-surface-ink: oklch(0.235 0.018 58);
|
| 1089 |
+
--dc-surface-raised: oklch(0.295 0.020 62);
|
| 1090 |
+
--dc-composer: oklch(0.255 0.014 52);
|
| 1091 |
+
--dc-composer-soft: oklch(0.315 0.015 58);
|
| 1092 |
+
--dc-primary: oklch(0.690 0.105 150);
|
| 1093 |
+
--dc-primary-deep: oklch(0.455 0.090 155);
|
| 1094 |
+
--dc-coral: oklch(0.700 0.140 32);
|
| 1095 |
+
--dc-aurora: oklch(0.745 0.080 185);
|
| 1096 |
+
--dc-lamp: oklch(0.830 0.120 76);
|
| 1097 |
+
--dc-plum: oklch(0.270 0.038 328);
|
| 1098 |
+
--dc-ink-main: oklch(0.960 0.010 78);
|
| 1099 |
+
--dc-ink-muted: oklch(0.760 0.018 78);
|
| 1100 |
+
--dc-border: oklch(0.465 0.024 70);
|
| 1101 |
+
--dc-radius-lg: 18px;
|
| 1102 |
+
--dc-radius-xl: 28px;
|
| 1103 |
+
}
|
| 1104 |
+
|
| 1105 |
+
html,
|
| 1106 |
+
body,
|
| 1107 |
+
.gradio-container {
|
| 1108 |
+
background:
|
| 1109 |
+
radial-gradient(circle at 18% -8%, oklch(0.830 0.120 76 / 0.16), transparent 24rem),
|
| 1110 |
+
radial-gradient(circle at 88% 10%, oklch(0.745 0.080 185 / 0.12), transparent 25rem),
|
| 1111 |
+
linear-gradient(180deg, oklch(0.150 0.012 48), var(--dc-bg-night) 48%, var(--dc-bg-void));
|
| 1112 |
+
}
|
| 1113 |
+
|
| 1114 |
+
.dc-app-shell {
|
| 1115 |
+
gap: 14px !important;
|
| 1116 |
+
max-width: 1260px;
|
| 1117 |
+
padding: 18px clamp(12px, 2.4vw, 28px) 24px;
|
| 1118 |
+
}
|
| 1119 |
+
|
| 1120 |
+
.dc-statusbar {
|
| 1121 |
+
background:
|
| 1122 |
+
linear-gradient(110deg, oklch(0.145 0.012 48 / 0.95), oklch(0.270 0.038 328 / 0.66)),
|
| 1123 |
+
url("/file=docs/design/assets/dream-customs-probe-morning-console.png");
|
| 1124 |
+
background-position: center 46%;
|
| 1125 |
+
background-size: cover;
|
| 1126 |
+
border-color: oklch(0.830 0.120 76 / 0.25);
|
| 1127 |
+
border-radius: 20px;
|
| 1128 |
+
box-shadow: none;
|
| 1129 |
+
grid-template-columns: minmax(0, 1fr) minmax(220px, auto);
|
| 1130 |
+
padding: 18px;
|
| 1131 |
+
}
|
| 1132 |
+
|
| 1133 |
+
.dc-statusbar::before {
|
| 1134 |
+
background:
|
| 1135 |
+
linear-gradient(90deg, oklch(0.145 0.012 48 / 0.92), oklch(0.235 0.018 58 / 0.76)),
|
| 1136 |
+
radial-gradient(circle at 12% 30%, oklch(0.830 0.120 76 / 0.12), transparent 18rem);
|
| 1137 |
+
}
|
| 1138 |
+
|
| 1139 |
+
.dc-brand-mark {
|
| 1140 |
+
background: oklch(0.830 0.120 76 / 0.14);
|
| 1141 |
+
border-color: oklch(0.830 0.120 76 / 0.42);
|
| 1142 |
+
border-radius: 14px;
|
| 1143 |
+
color: var(--dc-lamp);
|
| 1144 |
+
}
|
| 1145 |
+
|
| 1146 |
+
.dc-brand-lockup h1 {
|
| 1147 |
+
font-size: clamp(1.35rem, 2.4vw, 2rem);
|
| 1148 |
+
font-weight: 760;
|
| 1149 |
+
}
|
| 1150 |
+
|
| 1151 |
+
.dc-brand-lockup p {
|
| 1152 |
+
color: oklch(0.840 0.016 78);
|
| 1153 |
+
max-width: 58ch;
|
| 1154 |
+
}
|
| 1155 |
+
|
| 1156 |
+
.dc-system-status {
|
| 1157 |
+
align-content: center;
|
| 1158 |
+
max-width: 390px;
|
| 1159 |
+
}
|
| 1160 |
+
|
| 1161 |
+
.dc-system-status span {
|
| 1162 |
+
background: oklch(0.130 0.012 55 / 0.66);
|
| 1163 |
+
border-color: oklch(0.830 0.120 76 / 0.22);
|
| 1164 |
+
color: oklch(0.880 0.018 78);
|
| 1165 |
+
}
|
| 1166 |
+
|
| 1167 |
+
.dc-focus-grid {
|
| 1168 |
+
align-items: start !important;
|
| 1169 |
+
display: grid !important;
|
| 1170 |
+
gap: 16px !important;
|
| 1171 |
+
grid-template-columns: minmax(0, 1fr) minmax(330px, 390px);
|
| 1172 |
+
}
|
| 1173 |
+
|
| 1174 |
+
.dc-composer-panel {
|
| 1175 |
+
background:
|
| 1176 |
+
radial-gradient(circle at 4% 0%, oklch(0.830 0.120 76 / 0.08), transparent 18rem),
|
| 1177 |
+
linear-gradient(180deg, var(--dc-composer-soft), var(--dc-composer));
|
| 1178 |
+
border: 1px solid oklch(0.830 0.120 76 / 0.18);
|
| 1179 |
+
border-radius: var(--dc-radius-xl);
|
| 1180 |
+
box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22);
|
| 1181 |
+
padding: 18px;
|
| 1182 |
+
}
|
| 1183 |
+
|
| 1184 |
+
.dc-composer-head {
|
| 1185 |
+
align-items: flex-start;
|
| 1186 |
+
margin-bottom: 10px;
|
| 1187 |
+
}
|
| 1188 |
+
|
| 1189 |
+
.dc-composer-head h2 {
|
| 1190 |
+
color: var(--dc-ink-main);
|
| 1191 |
+
font-size: clamp(1.08rem, 1.8vw, 1.32rem);
|
| 1192 |
+
font-weight: 760;
|
| 1193 |
+
}
|
| 1194 |
+
|
| 1195 |
+
.dc-composer-head p {
|
| 1196 |
+
color: var(--dc-ink-muted);
|
| 1197 |
+
max-width: 58ch;
|
| 1198 |
+
}
|
| 1199 |
+
|
| 1200 |
+
.dc-trust-pill {
|
| 1201 |
+
background: oklch(0.830 0.120 76 / 0.10);
|
| 1202 |
+
border-color: oklch(0.830 0.120 76 / 0.28);
|
| 1203 |
+
color: oklch(0.900 0.060 76);
|
| 1204 |
+
}
|
| 1205 |
+
|
| 1206 |
+
.dc-inline-notice {
|
| 1207 |
+
background: oklch(0.185 0.018 55 / 0.58);
|
| 1208 |
+
border-color: oklch(0.830 0.120 76 / 0.18);
|
| 1209 |
+
color: oklch(0.880 0.014 78);
|
| 1210 |
+
margin-bottom: 8px;
|
| 1211 |
+
}
|
| 1212 |
+
|
| 1213 |
+
.dc-dream-input,
|
| 1214 |
+
.dc-dream-input .block,
|
| 1215 |
+
.dc-dream-input .wrap,
|
| 1216 |
+
.dc-dream-input .input-container,
|
| 1217 |
+
.dc-dream-input .container {
|
| 1218 |
+
background: transparent !important;
|
| 1219 |
+
border: 0 !important;
|
| 1220 |
+
box-shadow: none !important;
|
| 1221 |
+
}
|
| 1222 |
+
|
| 1223 |
+
.dc-dream-input textarea {
|
| 1224 |
+
background: transparent !important;
|
| 1225 |
+
border: 0 !important;
|
| 1226 |
+
box-shadow: none !important;
|
| 1227 |
+
color: var(--dc-ink-main) !important;
|
| 1228 |
+
font-size: 1.08rem !important;
|
| 1229 |
+
line-height: 1.58 !important;
|
| 1230 |
+
min-height: 138px !important;
|
| 1231 |
+
padding: 8px 2px 12px !important;
|
| 1232 |
+
}
|
| 1233 |
+
|
| 1234 |
+
.dc-dream-input textarea::placeholder {
|
| 1235 |
+
color: oklch(0.690 0.016 78) !important;
|
| 1236 |
+
}
|
| 1237 |
+
|
| 1238 |
+
.dc-composer-tools {
|
| 1239 |
+
align-items: end !important;
|
| 1240 |
+
display: grid !important;
|
| 1241 |
+
gap: 8px !important;
|
| 1242 |
+
grid-template-columns: minmax(112px, 0.8fr) minmax(112px, 0.8fr) minmax(130px, 1fr) minmax(128px, 0.9fr) minmax(160px, 1fr);
|
| 1243 |
+
}
|
| 1244 |
+
|
| 1245 |
+
.dc-composer-tools > * {
|
| 1246 |
+
min-width: 0 !important;
|
| 1247 |
+
}
|
| 1248 |
+
|
| 1249 |
+
.dc-tool-tile,
|
| 1250 |
+
.dc-tool-select,
|
| 1251 |
+
.dc-tool-button,
|
| 1252 |
+
.dc-upload-button,
|
| 1253 |
+
.dc-voice-tool,
|
| 1254 |
+
.dc-send-button {
|
| 1255 |
+
min-width: 0 !important;
|
| 1256 |
+
}
|
| 1257 |
+
|
| 1258 |
+
.dc-tool-tile .block,
|
| 1259 |
+
.dc-tool-tile .wrap,
|
| 1260 |
+
.dc-tool-tile .container,
|
| 1261 |
+
.dc-tool-tile .input-container,
|
| 1262 |
+
.dc-tool-select .block,
|
| 1263 |
+
.dc-tool-select .wrap,
|
| 1264 |
+
.dc-tool-select .container,
|
| 1265 |
+
.dc-tool-select .input-container {
|
| 1266 |
+
background: oklch(0.190 0.012 55 / 0.86) !important;
|
| 1267 |
+
border-color: oklch(0.830 0.120 76 / 0.17) !important;
|
| 1268 |
+
border-radius: 16px !important;
|
| 1269 |
+
color: var(--dc-ink-main) !important;
|
| 1270 |
+
}
|
| 1271 |
+
|
| 1272 |
+
.dc-tool-tile .image-container,
|
| 1273 |
+
.dc-tool-tile .audio-container,
|
| 1274 |
+
.dc-tool-tile .upload-container,
|
| 1275 |
+
.dc-tool-tile .upload-container button,
|
| 1276 |
+
.dc-tool-tile .audio-container button {
|
| 1277 |
+
background: oklch(0.190 0.012 55 / 0.86) !important;
|
| 1278 |
+
border-color: oklch(0.830 0.120 76 / 0.18) !important;
|
| 1279 |
+
border-radius: 16px !important;
|
| 1280 |
+
color: var(--dc-ink-muted) !important;
|
| 1281 |
+
min-height: 68px !important;
|
| 1282 |
+
}
|
| 1283 |
+
|
| 1284 |
+
.dc-tool-tile .image-container,
|
| 1285 |
+
.dc-tool-tile .audio-container {
|
| 1286 |
+
min-height: 68px !important;
|
| 1287 |
+
}
|
| 1288 |
+
|
| 1289 |
+
.dc-tool-select select,
|
| 1290 |
+
.dc-tool-select input,
|
| 1291 |
+
.dc-tool-select [role="combobox"] {
|
| 1292 |
+
background: oklch(0.190 0.012 55 / 0.86) !important;
|
| 1293 |
+
border-color: transparent !important;
|
| 1294 |
+
color: var(--dc-ink-main) !important;
|
| 1295 |
+
min-height: 42px !important;
|
| 1296 |
+
}
|
| 1297 |
+
|
| 1298 |
+
.dc-upload-button,
|
| 1299 |
+
.dc-upload-button button,
|
| 1300 |
+
.dc-voice-tool,
|
| 1301 |
+
.dc-voice-tool .block,
|
| 1302 |
+
.dc-voice-tool .wrap,
|
| 1303 |
+
.dc-voice-tool .container,
|
| 1304 |
+
.dc-voice-tool .input-container,
|
| 1305 |
+
.dc-voice-tool .audio-container {
|
| 1306 |
+
background: oklch(0.190 0.012 55 / 0.86) !important;
|
| 1307 |
+
border-color: oklch(0.830 0.120 76 / 0.18) !important;
|
| 1308 |
+
border-radius: 999px !important;
|
| 1309 |
+
color: oklch(0.895 0.030 76) !important;
|
| 1310 |
+
min-height: 44px !important;
|
| 1311 |
+
}
|
| 1312 |
+
|
| 1313 |
+
.dc-upload-button button,
|
| 1314 |
+
.dc-voice-tool button {
|
| 1315 |
+
border-radius: 999px !important;
|
| 1316 |
+
min-height: 38px !important;
|
| 1317 |
+
}
|
| 1318 |
+
|
| 1319 |
+
.dc-voice-tool {
|
| 1320 |
+
max-height: 52px !important;
|
| 1321 |
+
overflow: hidden !important;
|
| 1322 |
+
}
|
| 1323 |
+
|
| 1324 |
+
.dc-voice-tool .audio-container {
|
| 1325 |
+
height: 44px !important;
|
| 1326 |
+
min-height: 44px !important;
|
| 1327 |
+
overflow: hidden !important;
|
| 1328 |
+
}
|
| 1329 |
+
|
| 1330 |
+
.dc-composer-panel label,
|
| 1331 |
+
.dc-composer-panel .label-wrap span,
|
| 1332 |
+
.dc-composer-panel [data-testid="block-label"] {
|
| 1333 |
+
color: oklch(0.865 0.018 78) !important;
|
| 1334 |
+
font-size: 0.76rem !important;
|
| 1335 |
+
font-weight: 690 !important;
|
| 1336 |
+
}
|
| 1337 |
+
|
| 1338 |
+
.dc-composer-panel .label-wrap,
|
| 1339 |
+
.dc-composer-panel label.float {
|
| 1340 |
+
background: oklch(0.190 0.012 55 / 0.86) !important;
|
| 1341 |
+
border-color: oklch(0.830 0.120 76 / 0.16) !important;
|
| 1342 |
+
}
|
| 1343 |
+
|
| 1344 |
+
.dc-tool-button,
|
| 1345 |
+
.dc-tool-button button {
|
| 1346 |
+
background: oklch(0.190 0.012 55) !important;
|
| 1347 |
+
border: 1px solid oklch(0.830 0.120 76 / 0.20) !important;
|
| 1348 |
+
border-radius: 999px !important;
|
| 1349 |
+
color: oklch(0.895 0.030 76) !important;
|
| 1350 |
+
min-height: 44px !important;
|
| 1351 |
+
white-space: normal !important;
|
| 1352 |
+
}
|
| 1353 |
+
|
| 1354 |
+
.dc-send-button,
|
| 1355 |
+
.dc-send-button button {
|
| 1356 |
+
background: var(--dc-primary-deep) !important;
|
| 1357 |
+
border: 1px solid var(--dc-primary) !important;
|
| 1358 |
+
border-radius: 999px !important;
|
| 1359 |
+
color: var(--dc-ink-main) !important;
|
| 1360 |
+
min-height: 48px !important;
|
| 1361 |
+
white-space: normal !important;
|
| 1362 |
+
}
|
| 1363 |
+
|
| 1364 |
+
.dc-send-button:hover,
|
| 1365 |
+
.dc-send-button button:hover,
|
| 1366 |
+
.dc-tool-button:hover,
|
| 1367 |
+
.dc-tool-button button:hover {
|
| 1368 |
+
transform: translateY(-1px);
|
| 1369 |
+
}
|
| 1370 |
+
|
| 1371 |
+
.dc-pact-actions {
|
| 1372 |
+
display: grid !important;
|
| 1373 |
+
gap: 8px !important;
|
| 1374 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 1375 |
+
}
|
| 1376 |
+
|
| 1377 |
+
.dc-pact-actions button {
|
| 1378 |
+
min-height: 46px !important;
|
| 1379 |
+
white-space: normal !important;
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
+
.dc-draft-button,
|
| 1383 |
+
.dc-draft-button button {
|
| 1384 |
+
background: oklch(0.295 0.020 62) !important;
|
| 1385 |
+
border: 1px solid oklch(0.830 0.120 76 / 0.20) !important;
|
| 1386 |
+
border-radius: 999px !important;
|
| 1387 |
+
color: var(--dc-ink-main) !important;
|
| 1388 |
+
}
|
| 1389 |
+
|
| 1390 |
+
.dc-seal-button,
|
| 1391 |
+
.dc-seal-button button {
|
| 1392 |
+
background: var(--dc-coral) !important;
|
| 1393 |
+
border: 1px solid var(--dc-coral) !important;
|
| 1394 |
+
border-radius: 999px !important;
|
| 1395 |
+
color: oklch(0.130 0.012 55) !important;
|
| 1396 |
+
}
|
| 1397 |
+
|
| 1398 |
+
.dc-followup-panel,
|
| 1399 |
+
.dc-workflow-shortcuts,
|
| 1400 |
+
.dc-model-routes,
|
| 1401 |
+
.dc-diagnostics,
|
| 1402 |
+
.dc-examples {
|
| 1403 |
+
background: oklch(0.185 0.018 55 / 0.72) !important;
|
| 1404 |
+
border: 1px solid oklch(0.830 0.120 76 / 0.14) !important;
|
| 1405 |
+
border-radius: 18px !important;
|
| 1406 |
+
color: var(--dc-ink-main) !important;
|
| 1407 |
+
overflow: hidden;
|
| 1408 |
+
}
|
| 1409 |
+
|
| 1410 |
+
.dc-stage-nav {
|
| 1411 |
+
background: transparent;
|
| 1412 |
+
border: 0;
|
| 1413 |
+
border-radius: 0;
|
| 1414 |
+
padding: 0;
|
| 1415 |
+
}
|
| 1416 |
+
|
| 1417 |
+
.dc-stage-nav button,
|
| 1418 |
+
.dc-secondary-actions button {
|
| 1419 |
+
background: oklch(0.235 0.018 58) !important;
|
| 1420 |
+
border-color: oklch(0.830 0.120 76 / 0.16) !important;
|
| 1421 |
+
border-radius: 999px !important;
|
| 1422 |
+
}
|
| 1423 |
+
|
| 1424 |
+
.dc-inspector,
|
| 1425 |
+
.dc-timeline-shell {
|
| 1426 |
+
background: oklch(0.235 0.018 58 / 0.92);
|
| 1427 |
+
border-color: oklch(0.830 0.120 76 / 0.15);
|
| 1428 |
+
border-radius: 20px;
|
| 1429 |
+
}
|
| 1430 |
+
|
| 1431 |
+
.dc-inspector {
|
| 1432 |
+
box-shadow: none;
|
| 1433 |
+
}
|
| 1434 |
+
|
| 1435 |
+
.dc-timeline-shell {
|
| 1436 |
+
margin-top: 2px;
|
| 1437 |
+
}
|
| 1438 |
+
|
| 1439 |
+
.dc-timeline-event {
|
| 1440 |
+
background: oklch(0.185 0.018 55 / 0.70);
|
| 1441 |
+
border-color: oklch(0.830 0.120 76 / 0.12);
|
| 1442 |
+
}
|
| 1443 |
+
|
| 1444 |
+
.dc-event-meta span,
|
| 1445 |
+
.dc-evidence-chip,
|
| 1446 |
+
.dc-inspector dl div {
|
| 1447 |
+
background: oklch(0.185 0.018 55 / 0.68);
|
| 1448 |
+
border-color: oklch(0.830 0.120 76 / 0.13);
|
| 1449 |
+
}
|
| 1450 |
+
|
| 1451 |
+
.dc-inspector dt,
|
| 1452 |
+
.dc-inspector h3,
|
| 1453 |
+
.dc-inspector-kicker,
|
| 1454 |
+
.dc-permit-row span,
|
| 1455 |
+
.dc-timeline-head > span {
|
| 1456 |
+
color: oklch(0.830 0.120 76);
|
| 1457 |
+
}
|
| 1458 |
+
|
| 1459 |
+
@media (max-width: 980px) {
|
| 1460 |
+
.dc-focus-grid {
|
| 1461 |
+
grid-template-columns: 1fr;
|
| 1462 |
+
}
|
| 1463 |
+
|
| 1464 |
+
.dc-composer-tools {
|
| 1465 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 1466 |
+
}
|
| 1467 |
+
|
| 1468 |
+
.dc-send-button {
|
| 1469 |
+
grid-column: span 2;
|
| 1470 |
+
}
|
| 1471 |
+
}
|
| 1472 |
+
|
| 1473 |
+
@media (max-width: 620px) {
|
| 1474 |
+
.dc-app-shell {
|
| 1475 |
+
padding: 10px !important;
|
| 1476 |
+
}
|
| 1477 |
+
|
| 1478 |
+
.dc-statusbar,
|
| 1479 |
+
.dc-composer-panel,
|
| 1480 |
+
.dc-inspector,
|
| 1481 |
+
.dc-timeline-shell,
|
| 1482 |
+
.dc-followup-panel,
|
| 1483 |
+
.dc-workflow-shortcuts {
|
| 1484 |
+
border-radius: 18px;
|
| 1485 |
+
}
|
| 1486 |
+
|
| 1487 |
+
.dc-statusbar {
|
| 1488 |
+
padding: 14px;
|
| 1489 |
+
}
|
| 1490 |
+
|
| 1491 |
+
.dc-composer-panel {
|
| 1492 |
+
padding: 14px;
|
| 1493 |
+
}
|
| 1494 |
+
|
| 1495 |
+
.dc-dream-input textarea {
|
| 1496 |
+
min-height: 128px !important;
|
| 1497 |
+
}
|
| 1498 |
+
|
| 1499 |
+
.dc-composer-tools {
|
| 1500 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 1501 |
+
}
|
| 1502 |
+
|
| 1503 |
+
.dc-tool-button,
|
| 1504 |
+
.dc-send-button {
|
| 1505 |
+
grid-column: span 1;
|
| 1506 |
+
}
|
| 1507 |
+
|
| 1508 |
+
.dc-pact-actions {
|
| 1509 |
+
grid-template-columns: 1fr;
|
| 1510 |
+
}
|
| 1511 |
+
}
|
| 1512 |
"""
|
| 1513 |
|
| 1514 |
|
|
|
|
| 1530 |
with gr.Column(elem_classes=["dc-app-shell"]):
|
| 1531 |
status_html = gr.HTML()
|
| 1532 |
|
| 1533 |
+
with gr.Row(elem_classes=["dc-focus-grid"]):
|
| 1534 |
+
with gr.Column(scale=7, elem_classes=["dc-declaration-column"]):
|
| 1535 |
+
with gr.Column(elem_classes=["dc-composer-panel"]):
|
| 1536 |
+
gr.HTML(
|
| 1537 |
+
"""
|
| 1538 |
+
<div class="dc-composer-head">
|
| 1539 |
+
<div>
|
| 1540 |
+
<h2>Tell the customs desk what arrived in the night</h2>
|
| 1541 |
+
<p>One calm place for text, sketch, voice, mood, and model route.</p>
|
| 1542 |
+
</div>
|
| 1543 |
+
<span class="dc-trust-pill">Playful, not diagnostic</span>
|
| 1544 |
+
</div>
|
| 1545 |
+
""".strip()
|
| 1546 |
+
)
|
| 1547 |
+
notice_html = gr.HTML()
|
| 1548 |
+
dream_text = gr.Textbox(
|
| 1549 |
+
label="Dream material",
|
| 1550 |
+
show_label=False,
|
| 1551 |
+
lines=6,
|
| 1552 |
+
value="我梦见一部迟到的电梯,按钮都融化了,我一直到不了 14 楼。",
|
| 1553 |
+
placeholder="Describe a dream, drop in a fragment, or ask the clerk what to do with it.",
|
| 1554 |
+
elem_classes=["dc-dream-input"],
|
| 1555 |
+
)
|
| 1556 |
+
with gr.Row(elem_classes=["dc-composer-tools"]):
|
| 1557 |
+
image_input = gr.UploadButton(
|
| 1558 |
+
"Image",
|
| 1559 |
+
file_types=["image"],
|
| 1560 |
+
file_count="single",
|
| 1561 |
+
elem_classes=["dc-upload-button", "dc-image-tool"],
|
| 1562 |
+
)
|
| 1563 |
+
audio_input = gr.UploadButton(
|
| 1564 |
+
"Voice",
|
| 1565 |
+
file_types=["audio"],
|
| 1566 |
+
file_count="single",
|
| 1567 |
+
elem_classes=["dc-upload-button", "dc-audio-tool"],
|
| 1568 |
+
)
|
| 1569 |
+
mood = gr.Dropdown(
|
| 1570 |
+
label="Mood",
|
| 1571 |
+
show_label=False,
|
| 1572 |
+
choices=["foggy", "anxious", "curious", "tired", "restless", "calm"],
|
| 1573 |
+
value="foggy",
|
| 1574 |
+
elem_classes=["dc-tool-select"],
|
| 1575 |
+
)
|
| 1576 |
+
add_btn = gr.Button("+ Add", elem_classes=["dc-tool-button"])
|
| 1577 |
+
send_btn = gr.Button("Send", elem_classes=["dc-primary", "dc-send-button"])
|
| 1578 |
+
with gr.Accordion("Model routes", open=False, elem_classes=["dc-model-routes"]):
|
| 1579 |
+
with gr.Row(elem_classes=["dc-route-row"]):
|
| 1580 |
+
text_backend = gr.Dropdown(
|
| 1581 |
+
label="Text",
|
| 1582 |
+
choices=["demo", "model", "ollama"],
|
| 1583 |
+
value="demo",
|
| 1584 |
+
elem_classes=["dc-tool-select"],
|
| 1585 |
+
)
|
| 1586 |
+
vision_backend = gr.Dropdown(
|
| 1587 |
+
label="Vision",
|
| 1588 |
+
choices=["demo", "model", "ollama"],
|
| 1589 |
+
value="demo",
|
| 1590 |
+
elem_classes=["dc-tool-select"],
|
| 1591 |
+
)
|
| 1592 |
+
with gr.Accordion("Answer or refine the pact", open=False, elem_classes=["dc-followup-panel"]):
|
| 1593 |
+
with gr.Row(elem_classes=["dc-followup-grid"]):
|
| 1594 |
+
answer_text = gr.Textbox(
|
| 1595 |
+
label="Answer to the clerk",
|
| 1596 |
+
lines=2,
|
| 1597 |
+
value="我想和它结盟,但今天只想完成一件很小的事。",
|
| 1598 |
+
placeholder="Answer a customs question, or leave blank and skip.",
|
| 1599 |
+
)
|
| 1600 |
+
revision_request = gr.Textbox(
|
| 1601 |
+
label="Revision request",
|
| 1602 |
+
lines=2,
|
| 1603 |
+
value="Make it gentler and more specific for today.",
|
| 1604 |
+
placeholder="Try: make it stranger, make it gentler, or make the action smaller.",
|
| 1605 |
+
)
|
| 1606 |
+
with gr.Row(elem_classes=["dc-secondary-actions"]):
|
| 1607 |
+
ask_btn = gr.Button("Ask another question")
|
| 1608 |
+
answer_btn = gr.Button("Answer question")
|
| 1609 |
+
skip_btn = gr.Button("Skip question")
|
| 1610 |
+
revise_btn = gr.Button("Revise pact")
|
| 1611 |
+
new_btn = gr.Button("Start new")
|
| 1612 |
+
with gr.Accordion("Workflow shortcuts", open=False, elem_classes=["dc-workflow-shortcuts"]):
|
| 1613 |
+
with gr.Row(elem_classes=["dc-stage-nav"]):
|
| 1614 |
+
declare_phase_btn = gr.Button("Declare")
|
| 1615 |
+
inspect_phase_btn = gr.Button("Inspect")
|
| 1616 |
+
draft_phase_btn = gr.Button("Draft")
|
| 1617 |
+
seal_phase_btn = gr.Button("Seal", elem_classes=["dc-stage-seal"])
|
| 1618 |
+
|
| 1619 |
+
with gr.Column(scale=4, elem_classes=["dc-side-rail"]):
|
| 1620 |
inspector_html = gr.HTML()
|
| 1621 |
+
with gr.Row(elem_classes=["dc-pact-actions"]):
|
| 1622 |
+
draft_btn = gr.Button("Draft pact", elem_classes=["dc-draft-button"])
|
| 1623 |
+
seal_btn = gr.Button("Seal today's pact", elem_classes=["dc-seal-button"])
|
| 1624 |
+
sealed_html = gr.HTML(elem_classes=["dc-sealed-output"])
|
| 1625 |
|
| 1626 |
+
timeline_html = gr.HTML()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1627 |
|
| 1628 |
with gr.Accordion("Diagnostics", open=False, elem_classes=["dc-diagnostics"]):
|
| 1629 |
debug_json = gr.Code(label="Session state", language="json")
|
| 1630 |
|
| 1631 |
+
with gr.Accordion("Examples", open=False, elem_classes=["dc-examples"]):
|
| 1632 |
+
gr.Examples(
|
| 1633 |
+
examples=[
|
| 1634 |
+
[
|
| 1635 |
+
"梦见一间便利店漂在海上,收银员让我用旧日历付款。",
|
| 1636 |
+
"curious",
|
| 1637 |
+
"我想知道它到底在保护什么。",
|
| 1638 |
+
],
|
| 1639 |
+
[
|
| 1640 |
+
"I found a tiny border checkpoint inside my pillow. The officer stamped my hand with blue ink.",
|
| 1641 |
+
"restless",
|
| 1642 |
+
"I want a small action that makes tomorrow less loud.",
|
| 1643 |
+
],
|
| 1644 |
],
|
| 1645 |
+
inputs=[dream_text, mood, answer_text],
|
| 1646 |
+
)
|
|
|
|
| 1647 |
|
| 1648 |
outputs = _outputs(session_state, status_html, timeline_html, inspector_html, sealed_html, debug_json, notice_html)
|
| 1649 |
demo.load(initial_workbench_state, outputs=outputs, api_name=False)
|
| 1650 |
|
| 1651 |
+
declare_phase_btn.click(
|
| 1652 |
+
add_material_action,
|
| 1653 |
+
inputs=[session_state, dream_text, image_input, audio_input, mood, text_backend, vision_backend],
|
| 1654 |
+
outputs=outputs,
|
| 1655 |
+
api_name=False,
|
| 1656 |
+
)
|
| 1657 |
+
inspect_phase_btn.click(
|
| 1658 |
+
ask_another_question_action,
|
| 1659 |
+
inputs=[session_state, text_backend, vision_backend],
|
| 1660 |
+
outputs=outputs,
|
| 1661 |
+
api_name=False,
|
| 1662 |
+
)
|
| 1663 |
+
draft_phase_btn.click(
|
| 1664 |
+
draft_pact_action,
|
| 1665 |
+
inputs=[session_state, text_backend, vision_backend],
|
| 1666 |
+
outputs=outputs,
|
| 1667 |
+
api_name=False,
|
| 1668 |
+
)
|
| 1669 |
+
seal_phase_btn.click(
|
| 1670 |
+
seal_pact_action,
|
| 1671 |
+
inputs=[session_state, text_backend, vision_backend],
|
| 1672 |
+
outputs=outputs,
|
| 1673 |
+
api_name=False,
|
| 1674 |
+
)
|
| 1675 |
send_btn.click(
|
| 1676 |
start_declaration_action,
|
| 1677 |
inputs=[session_state, dream_text, image_input, audio_input, mood, text_backend, vision_backend],
|
design-qa.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dream Customs V4 Design QA
|
| 2 |
+
|
| 3 |
+
Date: 2026-06-05
|
| 4 |
+
|
| 5 |
+
Reference: user-provided Codex-style multimodal composer screenshot.
|
| 6 |
+
|
| 7 |
+
## Checks
|
| 8 |
+
|
| 9 |
+
- First screen uses one rounded multimodal composer instead of separate form blocks.
|
| 10 |
+
- Visible composer tools are limited to Image, Voice, Mood, Add, and Send.
|
| 11 |
+
- Technical Text/Vision routes are collapsed under Model routes.
|
| 12 |
+
- Pact inspector remains visible beside the composer on desktop.
|
| 13 |
+
- Timeline, diagnostics, examples, workflow shortcuts, and refinement controls are secondary.
|
| 14 |
+
- Text-only Chrome flow completed: Send -> Draft pact -> Seal today's pact.
|
| 15 |
+
- Sealed output renders a screenshot-friendly Today's Pact card.
|
| 16 |
+
- No desktop horizontal overflow in Chrome at the inspected viewport.
|
| 17 |
+
|
| 18 |
+
## Notes
|
| 19 |
+
|
| 20 |
+
- Image and voice use compact upload buttons to avoid large Gradio media drop zones in the first screen.
|
| 21 |
+
- Voice upload remains available as an input to the existing ASR adapter path.
|
| 22 |
+
- The UI keeps safety copy non-diagnostic.
|
| 23 |
+
|
| 24 |
+
final result: passed
|
docs/handoff.md
CHANGED
|
@@ -4,7 +4,17 @@ Last updated: 2026-06-05
|
|
| 4 |
|
| 5 |
## Current State
|
| 6 |
|
| 7 |
-
The project
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
- `docs/dream-customs-concept/index.html`
|
| 10 |
|
|
@@ -14,12 +24,14 @@ Supporting images:
|
|
| 14 |
- `docs/dream-customs-concept/assets/multimodal-intake.svg`
|
| 15 |
- `docs/dream-customs-concept/assets/alliance-card.svg`
|
| 16 |
|
| 17 |
-
|
| 18 |
|
| 19 |
- `docs/spec.md`
|
| 20 |
- `docs/prd.md`
|
| 21 |
- `docs/handoff.md`
|
| 22 |
- `docs/superpowers/plans/2026-06-05-dream-customs-mvp.md`
|
|
|
|
|
|
|
| 23 |
- `AGENTS.md`
|
| 24 |
|
| 25 |
## Product Decision
|
|
@@ -79,7 +91,7 @@ The product must never present itself as therapy, medical advice, or diagnosis.
|
|
| 79 |
|
| 80 |
## Recommended First Implementation
|
| 81 |
|
| 82 |
-
|
| 83 |
|
| 84 |
```text
|
| 85 |
app.py
|
|
@@ -100,26 +112,26 @@ tests/
|
|
| 100 |
test_pipeline.py
|
| 101 |
```
|
| 102 |
|
| 103 |
-
|
| 104 |
|
| 105 |
## Implementation Priorities
|
| 106 |
|
| 107 |
-
1.
|
| 108 |
-
2.
|
| 109 |
-
3.
|
| 110 |
-
4.
|
| 111 |
-
5.
|
| 112 |
-
6.
|
| 113 |
-
7. Space packaging.
|
| 114 |
|
| 115 |
-
##
|
| 116 |
|
| 117 |
-
|
| 118 |
|
| 119 |
-
|
|
|
|
|
|
|
| 120 |
|
| 121 |
-
|
| 122 |
-
2. move this context into the intended Build Small repository/Space repo.
|
| 123 |
|
| 124 |
## Open Questions For User
|
| 125 |
|
|
|
|
| 4 |
|
| 5 |
## Current State
|
| 6 |
|
| 7 |
+
The project has shipped a working Gradio MVP and a V4 local UI pass. The current interface centers a warm Codex-like multimodal composer: text, image upload, voice upload, mood, add-material, and send live inside one rounded input surface. Model routes, workflow shortcuts, diagnostics, and examples are collapsed by default.
|
| 8 |
+
|
| 9 |
+
Current V4 UX decisions:
|
| 10 |
+
|
| 11 |
+
- The first screen prioritizes the dream declaration composer and pact inspector.
|
| 12 |
+
- Image and voice use compact upload buttons to avoid large Gradio media drop zones in the main composer.
|
| 13 |
+
- `Draft pact` and `Seal today's pact` sit beside the live pact inspector.
|
| 14 |
+
- The timeline is a supporting "Story so far" section below the first-screen workflow.
|
| 15 |
+
- Technical model route controls are available but not first-level visual chrome.
|
| 16 |
+
|
| 17 |
+
The original visual HTML concept note remains useful background:
|
| 18 |
|
| 19 |
- `docs/dream-customs-concept/index.html`
|
| 20 |
|
|
|
|
| 24 |
- `docs/dream-customs-concept/assets/multimodal-intake.svg`
|
| 25 |
- `docs/dream-customs-concept/assets/alliance-card.svg`
|
| 26 |
|
| 27 |
+
Project context documents:
|
| 28 |
|
| 29 |
- `docs/spec.md`
|
| 30 |
- `docs/prd.md`
|
| 31 |
- `docs/handoff.md`
|
| 32 |
- `docs/superpowers/plans/2026-06-05-dream-customs-mvp.md`
|
| 33 |
+
- `docs/superpowers/plans/2026-06-05-dream-customs-uiux-v2.md`
|
| 34 |
+
- `docs/superpowers/plans/2026-06-05-dream-customs-uiux-v3.md`
|
| 35 |
- `AGENTS.md`
|
| 36 |
|
| 37 |
## Product Decision
|
|
|
|
| 91 |
|
| 92 |
## Recommended First Implementation
|
| 93 |
|
| 94 |
+
The minimal Python package already exists:
|
| 95 |
|
| 96 |
```text
|
| 97 |
app.py
|
|
|
|
| 112 |
test_pipeline.py
|
| 113 |
```
|
| 114 |
|
| 115 |
+
The current implementation keeps deterministic demo clients as the default and exposes optional model routes. For V3, do not rebuild the pipeline from scratch. Fix the app shell, control hierarchy, phase actions, and visual polish while preserving the existing `CustomsSession` state flow.
|
| 116 |
|
| 117 |
## Implementation Priorities
|
| 118 |
|
| 119 |
+
1. First-screen trust and immediate declaration controls.
|
| 120 |
+
2. Clickable phase actions.
|
| 121 |
+
3. Mobile-readable composer and inspector.
|
| 122 |
+
4. Removal of long blank page regions.
|
| 123 |
+
5. Tests and local browser verification.
|
| 124 |
+
6. Branch commit/push and Space update when credentials allow.
|
|
|
|
| 125 |
|
| 126 |
+
## Repository Status
|
| 127 |
|
| 128 |
+
This directory is now a dedicated Dream Customs repository:
|
| 129 |
|
| 130 |
+
- Local path: `/Users/junhaocheng/working-dir/ai-competitions/build-small-hackthon`
|
| 131 |
+
- GitHub remote: `https://github.com/adjcjh777/dream-customs-build-small.git`
|
| 132 |
+
- Hugging Face Space remote: `https://huggingface.co/spaces/build-small-hackathon/dream-customs`
|
| 133 |
|
| 134 |
+
Continue to confirm `git remote -v` before pushing, but the earlier VLA remote warning is no longer the active state.
|
|
|
|
| 135 |
|
| 136 |
## Open Questions For User
|
| 137 |
|
dream_customs/app_logic.py
CHANGED
|
@@ -39,6 +39,10 @@ def _file_path(value: Any) -> str:
|
|
| 39 |
return value
|
| 40 |
if isinstance(value, dict):
|
| 41 |
return str(value.get("path") or value.get("name") or "")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
if isinstance(value, (list, tuple)) and value:
|
| 43 |
return _file_path(value[0])
|
| 44 |
return ""
|
|
|
|
| 39 |
return value
|
| 40 |
if isinstance(value, dict):
|
| 41 |
return str(value.get("path") or value.get("name") or "")
|
| 42 |
+
if hasattr(value, "path"):
|
| 43 |
+
return str(getattr(value, "path") or "")
|
| 44 |
+
if hasattr(value, "name"):
|
| 45 |
+
return str(getattr(value, "name") or "")
|
| 46 |
if isinstance(value, (list, tuple)) and value:
|
| 47 |
return _file_path(value[0])
|
| 48 |
return ""
|
dream_customs/render.py
CHANGED
|
@@ -27,26 +27,20 @@ def _evidence_chip(item: EvidenceItem) -> str:
|
|
| 27 |
|
| 28 |
|
| 29 |
def render_status_bar(session: CustomsSession, text_backend: str = "demo", vision_backend: str = "demo") -> str:
|
| 30 |
-
safety = "Support note ready" if session.safety_flags else "Playful reflection, not
|
| 31 |
return f"""
|
| 32 |
<header class="dc-statusbar">
|
| 33 |
<div class="dc-brand-lockup">
|
| 34 |
<span class="dc-brand-mark">DC</span>
|
| 35 |
<div>
|
| 36 |
<h1>Dream Customs / 梦境海关</h1>
|
| 37 |
-
<p>
|
| 38 |
</div>
|
| 39 |
</div>
|
| 40 |
-
<nav class="dc-phase-rail" aria-label="Dream Customs phase">
|
| 41 |
-
<span class="{'is-active' if session.phase in ['empty', 'declaring'] else ''}">Declare</span>
|
| 42 |
-
<span class="{'is-active' if session.phase == 'negotiating' else ''}">Inspect</span>
|
| 43 |
-
<span class="{'is-active' if session.phase == 'drafting' else ''}">Draft</span>
|
| 44 |
-
<span class="{'is-active' if session.phase == 'sealed' else ''}">Seal</span>
|
| 45 |
-
</nav>
|
| 46 |
<div class="dc-system-status">
|
| 47 |
-
<span>{escape(_phase_label(session.phase))}</span>
|
| 48 |
-
<span>Text
|
| 49 |
-
<span>Vision
|
| 50 |
<span>{escape(safety)}</span>
|
| 51 |
</div>
|
| 52 |
</header>
|
|
@@ -96,8 +90,9 @@ def render_timeline(session: CustomsSession) -> str:
|
|
| 96 |
<section class="dc-timeline-shell" aria-label="Dream Customs timeline">
|
| 97 |
<div class="dc-timeline-head">
|
| 98 |
<div>
|
| 99 |
-
<
|
| 100 |
-
<
|
|
|
|
| 101 |
</div>
|
| 102 |
<span>{session.evidence_count()} filed</span>
|
| 103 |
</div>
|
|
@@ -117,7 +112,7 @@ def render_pact_inspector(session: CustomsSession) -> str:
|
|
| 117 |
<aside class="dc-inspector is-waiting" aria-label="Pact inspector">
|
| 118 |
<div class="dc-inspector-kicker">Pact inspector</div>
|
| 119 |
<h2>No pact drafted yet</h2>
|
| 120 |
-
<p>
|
| 121 |
<dl>
|
| 122 |
<div><dt>Evidence</dt><dd>{session.evidence_count()} filed</dd></div>
|
| 123 |
<div><dt>Phase</dt><dd>{escape(_phase_label(session.phase))}</dd></div>
|
|
@@ -176,14 +171,14 @@ def render_pact_card(card: PactCard) -> str:
|
|
| 176 |
return f"""
|
| 177 |
<style>
|
| 178 |
.pact-card {{
|
| 179 |
-
color: oklch(0.
|
| 180 |
background:
|
| 181 |
-
radial-gradient(circle at
|
| 182 |
-
linear-gradient(135deg, oklch(0.
|
| 183 |
-
border:
|
| 184 |
-
border-radius:
|
| 185 |
-
box-shadow: 0
|
| 186 |
-
font-family:
|
| 187 |
line-height: 1.55;
|
| 188 |
margin: 8px 0;
|
| 189 |
max-width: 860px;
|
|
@@ -191,7 +186,7 @@ def render_pact_card(card: PactCard) -> str:
|
|
| 191 |
}}
|
| 192 |
.pact-header {{
|
| 193 |
align-items: center;
|
| 194 |
-
border-bottom: 1px solid oklch(0.
|
| 195 |
display: flex;
|
| 196 |
font-weight: 720;
|
| 197 |
justify-content: space-between;
|
|
@@ -199,14 +194,14 @@ def render_pact_card(card: PactCard) -> str:
|
|
| 199 |
padding-bottom: 10px;
|
| 200 |
}}
|
| 201 |
.pact-card h2 {{
|
| 202 |
-
color: oklch(0.
|
| 203 |
font-size: 2rem;
|
| 204 |
line-height: 1.1;
|
| 205 |
margin: 0 0 4px;
|
| 206 |
text-wrap: balance;
|
| 207 |
}}
|
| 208 |
.pact-card h3 {{
|
| 209 |
-
color: oklch(0.
|
| 210 |
font-size: 1.35rem;
|
| 211 |
margin: 0 0 18px;
|
| 212 |
}}
|
|
@@ -215,18 +210,19 @@ def render_pact_card(card: PactCard) -> str:
|
|
| 215 |
.pact-card div,
|
| 216 |
.pact-card span {{
|
| 217 |
color: oklch(0.900 0.018 235) !important;
|
|
|
|
| 218 |
}}
|
| 219 |
.pact-header span {{
|
| 220 |
-
color: oklch(0.
|
| 221 |
}}
|
| 222 |
.dc-label {{
|
| 223 |
-
color: oklch(0.
|
| 224 |
font-weight: 720;
|
| 225 |
}}
|
| 226 |
.dc-seal {{
|
| 227 |
-
border: 2px solid oklch(0.
|
| 228 |
border-radius: 999px;
|
| 229 |
-
color: oklch(0.
|
| 230 |
display: inline-block;
|
| 231 |
font-weight: 820;
|
| 232 |
margin-top: 12px;
|
|
@@ -234,8 +230,8 @@ def render_pact_card(card: PactCard) -> str:
|
|
| 234 |
transform: rotate(-4deg);
|
| 235 |
}}
|
| 236 |
.dc-sealed-safety {{
|
| 237 |
-
background: oklch(0.
|
| 238 |
-
border: 1px solid oklch(0.
|
| 239 |
border-radius: 10px;
|
| 240 |
padding: 12px 14px;
|
| 241 |
}}
|
|
|
|
| 27 |
|
| 28 |
|
| 29 |
def render_status_bar(session: CustomsSession, text_backend: str = "demo", vision_backend: str = "demo") -> str:
|
| 30 |
+
safety = "Support note ready" if session.safety_flags else "Playful reflection, not diagnosis"
|
| 31 |
return f"""
|
| 32 |
<header class="dc-statusbar">
|
| 33 |
<div class="dc-brand-lockup">
|
| 34 |
<span class="dc-brand-mark">DC</span>
|
| 35 |
<div>
|
| 36 |
<h1>Dream Customs / 梦境海关</h1>
|
| 37 |
+
<p>Turn last night's strange visitor into one gentle pact for the day: a practical suggestion, a small weird task, and a bedtime release.</p>
|
| 38 |
</div>
|
| 39 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
<div class="dc-system-status">
|
| 41 |
+
<span>Current: {escape(_phase_label(session.phase))}</span>
|
| 42 |
+
<span>Text {escape(text_backend or "demo")}</span>
|
| 43 |
+
<span>Vision {escape(vision_backend or "demo")}</span>
|
| 44 |
<span>{escape(safety)}</span>
|
| 45 |
</div>
|
| 46 |
</header>
|
|
|
|
| 90 |
<section class="dc-timeline-shell" aria-label="Dream Customs timeline">
|
| 91 |
<div class="dc-timeline-head">
|
| 92 |
<div>
|
| 93 |
+
<span class="dc-section-kicker">Customs timeline</span>
|
| 94 |
+
<h2>Story so far</h2>
|
| 95 |
+
<p>Dream fragments, clerk questions, and pact drafts stay together so the ritual feels easy to follow.</p>
|
| 96 |
</div>
|
| 97 |
<span>{session.evidence_count()} filed</span>
|
| 98 |
</div>
|
|
|
|
| 112 |
<aside class="dc-inspector is-waiting" aria-label="Pact inspector">
|
| 113 |
<div class="dc-inspector-kicker">Pact inspector</div>
|
| 114 |
<h2>No pact drafted yet</h2>
|
| 115 |
+
<p>Your alliance card will appear here after the clerk has enough dream material. Text-only is enough to begin.</p>
|
| 116 |
<dl>
|
| 117 |
<div><dt>Evidence</dt><dd>{session.evidence_count()} filed</dd></div>
|
| 118 |
<div><dt>Phase</dt><dd>{escape(_phase_label(session.phase))}</dd></div>
|
|
|
|
| 171 |
return f"""
|
| 172 |
<style>
|
| 173 |
.pact-card {{
|
| 174 |
+
color: oklch(0.170 0.016 55);
|
| 175 |
background:
|
| 176 |
+
radial-gradient(circle at 88% 0%, oklch(0.830 0.120 76 / 0.20), transparent 26%),
|
| 177 |
+
linear-gradient(135deg, oklch(0.965 0.014 82), oklch(0.900 0.028 72));
|
| 178 |
+
border: 1px solid oklch(0.700 0.140 32 / 0.42);
|
| 179 |
+
border-radius: 18px;
|
| 180 |
+
box-shadow: 0 18px 38px oklch(0.130 0.012 55 / 0.34);
|
| 181 |
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
| 182 |
line-height: 1.55;
|
| 183 |
margin: 8px 0;
|
| 184 |
max-width: 860px;
|
|
|
|
| 186 |
}}
|
| 187 |
.pact-header {{
|
| 188 |
align-items: center;
|
| 189 |
+
border-bottom: 1px solid oklch(0.700 0.140 32 / 0.22);
|
| 190 |
display: flex;
|
| 191 |
font-weight: 720;
|
| 192 |
justify-content: space-between;
|
|
|
|
| 194 |
padding-bottom: 10px;
|
| 195 |
}}
|
| 196 |
.pact-card h2 {{
|
| 197 |
+
color: oklch(0.170 0.016 55) !important;
|
| 198 |
font-size: 2rem;
|
| 199 |
line-height: 1.1;
|
| 200 |
margin: 0 0 4px;
|
| 201 |
text-wrap: balance;
|
| 202 |
}}
|
| 203 |
.pact-card h3 {{
|
| 204 |
+
color: oklch(0.455 0.090 155) !important;
|
| 205 |
font-size: 1.35rem;
|
| 206 |
margin: 0 0 18px;
|
| 207 |
}}
|
|
|
|
| 210 |
.pact-card div,
|
| 211 |
.pact-card span {{
|
| 212 |
color: oklch(0.900 0.018 235) !important;
|
| 213 |
+
color: oklch(0.230 0.018 55) !important;
|
| 214 |
}}
|
| 215 |
.pact-header span {{
|
| 216 |
+
color: oklch(0.280 0.020 55) !important;
|
| 217 |
}}
|
| 218 |
.dc-label {{
|
| 219 |
+
color: oklch(0.455 0.090 155) !important;
|
| 220 |
font-weight: 720;
|
| 221 |
}}
|
| 222 |
.dc-seal {{
|
| 223 |
+
border: 2px solid oklch(0.700 0.140 32);
|
| 224 |
border-radius: 999px;
|
| 225 |
+
color: oklch(0.700 0.140 32) !important;
|
| 226 |
display: inline-block;
|
| 227 |
font-weight: 820;
|
| 228 |
margin-top: 12px;
|
|
|
|
| 230 |
transform: rotate(-4deg);
|
| 231 |
}}
|
| 232 |
.dc-sealed-safety {{
|
| 233 |
+
background: oklch(0.700 0.140 32 / 0.10);
|
| 234 |
+
border: 1px solid oklch(0.700 0.140 32 / 0.34);
|
| 235 |
border-radius: 10px;
|
| 236 |
padding: 12px 14px;
|
| 237 |
}}
|