Spaces:
Sleeping
Sleeping
Redesign UI: courtroom palette, readable header, kill default purple
Browse files
app.py
CHANGED
|
@@ -20,16 +20,90 @@ from witnessbox.engine import WitnessBoxEngine
|
|
| 20 |
from witnessbox.witness import WITNESS_NAME, WITNESS_ROLE
|
| 21 |
|
| 22 |
CSS = """
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
.
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
.wb-bar-fill {height:100%; transition:width .4s ease;}
|
| 29 |
-
.wb-disclaimer {font-size:11px; color:
|
| 30 |
-
.wb-tier {font-variant:
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
"""
|
| 34 |
|
| 35 |
|
|
@@ -172,12 +246,21 @@ def on_ask(engine, mic, typed):
|
|
| 172 |
# layout
|
| 173 |
# --------------------------------------------------------------------------- #
|
| 174 |
def build() -> gr.Blocks:
|
| 175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
engine_state = gr.State(None)
|
| 177 |
gr.HTML(
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
)
|
| 182 |
banner = gr.HTML(_banner("info", "Call the witness to the stand."))
|
| 183 |
|
|
@@ -186,12 +269,13 @@ def build() -> gr.Blocks:
|
|
| 186 |
_portrait = "assets/marcus_reid.png"
|
| 187 |
gr.Image(
|
| 188 |
value=_portrait if os.path.exists(_portrait) else None,
|
| 189 |
-
show_label=False, height=
|
| 190 |
show_download_button=False, container=True,
|
| 191 |
)
|
| 192 |
stance_html = gr.HTML(label="Delivery")
|
| 193 |
with gr.Column(scale=4):
|
| 194 |
-
chat = gr.Chatbot(type="messages", height=
|
|
|
|
| 195 |
witness_audio = gr.Audio(label="Witness", autoplay=True, interactive=False)
|
| 196 |
with gr.Column(scale=2):
|
| 197 |
counters_html = gr.HTML()
|
|
|
|
| 20 |
from witnessbox.witness import WITNESS_NAME, WITNESS_ROLE
|
| 21 |
|
| 22 |
CSS = """
|
| 23 |
+
/* ===== WitnessBox — a courtroom palette: parchment · ink · oxblood · brass =====
|
| 24 |
+
Overrides Gradio's variables in BOTH light and dark mode so the look is
|
| 25 |
+
consistent and there's not a drop of the default indigo anywhere. */
|
| 26 |
+
.gradio-container, .gradio-container.dark {
|
| 27 |
+
--wb-ink:#2b2014; --wb-ink-soft:#6d5a3a;
|
| 28 |
+
--wb-card:#f5edd9; --wb-card-2:#efe4cb;
|
| 29 |
+
--wb-border:#c7b083; --wb-border-2:#a98c58;
|
| 30 |
+
--wb-oxblood:#7c1f25; --wb-oxblood-hi:#94333a;
|
| 31 |
+
--wb-brass:#9c7a3c; --wb-walnut:#241a10;
|
| 32 |
+
|
| 33 |
+
--body-background-fill: radial-gradient(125% 95% at 50% -12%, #f1e7cf 0%, #e3d3ab 72%);
|
| 34 |
+
--body-text-color: var(--wb-ink);
|
| 35 |
+
--body-text-color-subdued: var(--wb-ink-soft);
|
| 36 |
+
--background-fill-primary: var(--wb-card);
|
| 37 |
+
--background-fill-secondary: var(--wb-card-2);
|
| 38 |
+
--block-background-fill: var(--wb-card);
|
| 39 |
+
--block-border-color: var(--wb-border);
|
| 40 |
+
--block-label-background-fill: var(--wb-oxblood);
|
| 41 |
+
--block-label-text-color: #f4e8c9;
|
| 42 |
+
--block-title-text-color: var(--wb-ink);
|
| 43 |
+
--block-info-text-color: var(--wb-ink-soft);
|
| 44 |
+
--border-color-primary: var(--wb-border);
|
| 45 |
+
--border-color-accent: var(--wb-brass);
|
| 46 |
+
--button-primary-background-fill: linear-gradient(180deg,#8e2731,#6f1b21);
|
| 47 |
+
--button-primary-background-fill-hover: linear-gradient(180deg,#9c333b,#7c1f25);
|
| 48 |
+
--button-primary-text-color:#f6ecd2;
|
| 49 |
+
--button-primary-border-color:#591319;
|
| 50 |
+
--button-secondary-background-fill: linear-gradient(180deg,#ecdcb4,#dcc798);
|
| 51 |
+
--button-secondary-background-fill-hover: linear-gradient(180deg,#f2e4c0,#e3d0a4);
|
| 52 |
+
--button-secondary-text-color: var(--wb-ink);
|
| 53 |
+
--button-secondary-border-color: var(--wb-border-2);
|
| 54 |
+
--input-background-fill:#fbf6e8;
|
| 55 |
+
--input-border-color: var(--wb-border);
|
| 56 |
+
--input-placeholder-color:#9a8763;
|
| 57 |
+
--color-accent: var(--wb-brass);
|
| 58 |
+
--color-accent-soft:#ecdfbc;
|
| 59 |
+
--link-text-color: var(--wb-oxblood);
|
| 60 |
+
--link-text-color-hover: var(--wb-oxblood-hi);
|
| 61 |
+
--block-shadow: 0 2px 7px rgba(60,40,15,.10);
|
| 62 |
+
--block-radius:12px;
|
| 63 |
+
font-family:'Iowan Old Style','Palatino Linotype','Palatino',Georgia,'Times New Roman',serif;
|
| 64 |
+
}
|
| 65 |
+
.gradio-container { background: var(--body-background-fill); }
|
| 66 |
+
|
| 67 |
+
/* ---- header ---- */
|
| 68 |
+
#wb-title {text-align:center; padding:14px 0 2px;}
|
| 69 |
+
#wb-title .wb-crest {font-size:1.5rem; line-height:1; opacity:.85;}
|
| 70 |
+
#wb-title h1 {color:var(--wb-ink)!important; font-variant:small-caps; letter-spacing:1.5px;
|
| 71 |
+
font-weight:700; font-size:2.7rem; margin:.05em 0 .04em; line-height:1.05;}
|
| 72 |
+
#wb-title .wb-sub {color:var(--wb-ink-soft)!important; font-size:1.06rem; letter-spacing:.2px;}
|
| 73 |
+
#wb-title .wb-sub b {color:var(--wb-oxblood); font-weight:700;}
|
| 74 |
+
#wb-title .wb-rule {width:210px; height:2px; margin:11px auto 0;
|
| 75 |
+
background:linear-gradient(90deg,transparent,var(--wb-brass),transparent);}
|
| 76 |
+
|
| 77 |
+
/* ---- small-caps block labels everywhere ---- */
|
| 78 |
+
.gradio-container .block-label, .gradio-container label > span:first-child {
|
| 79 |
+
font-variant:small-caps; letter-spacing:.6px; font-weight:700;}
|
| 80 |
+
|
| 81 |
+
/* ---- chatbot = a deposition transcript on aged paper ---- */
|
| 82 |
+
#wb-chat {background:var(--wb-card)!important; border:1px solid var(--wb-border)!important;}
|
| 83 |
+
#wb-chat *, #wb-chat .message, #wb-chat .prose {color:var(--wb-ink)!important;}
|
| 84 |
+
#wb-chat .message {font-size:1.02rem!important; line-height:1.5!important; border-radius:10px!important;}
|
| 85 |
+
#wb-chat .user, #wb-chat [data-role="user"] {background:#efe3c6!important; border:1px solid var(--wb-border)!important;}
|
| 86 |
+
#wb-chat .bot, #wb-chat [data-role="assistant"] {background:#fbf6e8!important; border-left:3px solid var(--wb-oxblood)!important;}
|
| 87 |
+
#wb-chat .placeholder, #wb-chat .placeholder * {color:var(--wb-ink-soft)!important; opacity:.7;}
|
| 88 |
+
|
| 89 |
+
/* ---- banner ---- */
|
| 90 |
+
.wb-banner {text-align:center; font-size:1.15rem; font-variant:small-caps; letter-spacing:.6px;
|
| 91 |
+
padding:12px; border-radius:10px; border:1px solid var(--wb-border);}
|
| 92 |
+
|
| 93 |
+
/* ---- custom HTML panels (stance / counters) ---- */
|
| 94 |
+
.wb-card {background:var(--wb-card); border:1px solid var(--wb-border); border-radius:10px; padding:13px 15px; box-shadow:0 1px 0 #fffdf6 inset;}
|
| 95 |
+
.wb-bar-track {background:#e0d3af; border-radius:7px; height:16px; overflow:hidden; border:1px solid var(--wb-border);}
|
| 96 |
.wb-bar-fill {height:100%; transition:width .4s ease;}
|
| 97 |
+
.wb-disclaimer {font-size:11px; color:var(--wb-ink-soft); font-style:italic;}
|
| 98 |
+
.wb-tier {font-variant:small-caps; font-weight:700; color:var(--wb-oxblood); letter-spacing:.5px;}
|
| 99 |
+
|
| 100 |
+
/* ---- portrait framing ---- */
|
| 101 |
+
#wb-portrait img {border:1px solid var(--wb-border-2); border-radius:10px;}
|
| 102 |
+
|
| 103 |
+
/* ---- evidence: a walnut 'exhibit' readout ---- */
|
| 104 |
+
#wb-evidence textarea {font-family:ui-monospace,Menlo,Consolas,monospace!important;
|
| 105 |
+
background:var(--wb-walnut)!important; color:#ecdfae!important;
|
| 106 |
+
border:1px solid var(--wb-brass)!important; border-radius:8px;}
|
| 107 |
"""
|
| 108 |
|
| 109 |
|
|
|
|
| 246 |
# layout
|
| 247 |
# --------------------------------------------------------------------------- #
|
| 248 |
def build() -> gr.Blocks:
|
| 249 |
+
theme = gr.themes.Soft(
|
| 250 |
+
primary_hue=gr.themes.colors.red, # oxblood, refined to exact hues in CSS
|
| 251 |
+
secondary_hue=gr.themes.colors.amber, # brass
|
| 252 |
+
neutral_hue=gr.themes.colors.stone, # warm paper greys, never blue-greys
|
| 253 |
+
)
|
| 254 |
+
with gr.Blocks(css=CSS, title="WitnessBox", theme=theme) as demo:
|
| 255 |
engine_state = gr.State(None)
|
| 256 |
gr.HTML(
|
| 257 |
+
"<div id='wb-title'>"
|
| 258 |
+
"<div class='wb-crest'>⚖️</div>"
|
| 259 |
+
"<h1>WitnessBox</h1>"
|
| 260 |
+
f"<div class='wb-sub'>Cross-examine <b>{WITNESS_NAME}</b>, {WITNESS_ROLE}. "
|
| 261 |
+
"Your <b>voice</b> is the weapon.</div>"
|
| 262 |
+
"<div class='wb-rule'></div>"
|
| 263 |
+
"</div>"
|
| 264 |
)
|
| 265 |
banner = gr.HTML(_banner("info", "Call the witness to the stand."))
|
| 266 |
|
|
|
|
| 269 |
_portrait = "assets/marcus_reid.png"
|
| 270 |
gr.Image(
|
| 271 |
value=_portrait if os.path.exists(_portrait) else None,
|
| 272 |
+
show_label=False, height=300, elem_id="wb-portrait",
|
| 273 |
show_download_button=False, container=True,
|
| 274 |
)
|
| 275 |
stance_html = gr.HTML(label="Delivery")
|
| 276 |
with gr.Column(scale=4):
|
| 277 |
+
chat = gr.Chatbot(type="messages", height=420, label="The Stand",
|
| 278 |
+
elem_id="wb-chat")
|
| 279 |
witness_audio = gr.Audio(label="Witness", autoplay=True, interactive=False)
|
| 280 |
with gr.Column(scale=2):
|
| 281 |
counters_html = gr.HTML()
|