1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
//! The congeries palette — yog's single colour authority (DESIGN §11).
//!
//! Yog-Sothoth manifests as *a congeries of iridescent globes* — and yog's
//! visual identity is exactly that: luminous sphere-hues against the void.
//! Every colour the UI paints is named here, once; renderers import the hue,
//! never restate an RGB triple. The naming keys each hue to the platform's
//! lore so the vocabulary is stable across the tools yog drives: **lernie**
//! (the hydra) owns the liveness green, **brazen** (the brazen head) owns the
//! oracle bronze, and yog itself — the key and the gate — owns the violet.
//!
//! [`icon`] is the same congeries as the application mark — one orb table
//! rendered two ways: rasterized for the eframe window icon, emitted as the
//! checked-in `assets/yog.svg` for the desktop entry.
//!
//! [`visuals`] derives the whole egui [`egui::Visuals`] (void backgrounds,
//! gate-violet selection, moonlit text), [`fonts`] the glyph coverage both
//! families share, and [`apply`] installs both at eframe bring-up; [`pulse`]
//! is the shared in-flight animation colour; [`wordmark`] is the congeries
//! mark both wordmark seats render.
//!
//! The `badges` submodule holds the §11 badge mappings — glyph + hue +
//! **words** for one fact each ([`state_badge`], [`mark_badge`], [`op_badge`],
//! [`tool_result_badge`]) — re-exported here so a seat imports one module.
pub use ;
// The §11 badge vocabulary, split from this file at §12's cap but addressed
// through it: `theme::state_badge` and its siblings stay one import, because the
// palette and the words a badge says are one authority (§11).
pub use ;
// The §11 role stripe (bl-3acb): the one role vocabulary and its one
// hue-and-words mapping, worn by the transcript rows and the inbox-composer's
// pending queue alike — addressed through the palette for the same reason the
// badges are.
pub use ;
/// Hydra green — lernie's liveness hue: the `Live` state badge, ✔ ok tool
/// results, `Complete` framing, a settled login outcome.
pub const HYDRA: Color32 = from_rgb;
/// Spectral blue — light mid-transit through the gate: the `InFlight` badge,
/// the live streaming tail, the pulsing tool chip, hyperlinks.
pub const SPECTRE: Color32 = from_rgb;
/// Brazen bronze — the oracle head's metal: pending-mail ✉, warnings,
/// budget-exhausted marks, attention counts.
pub const BRAZEN: Color32 = from_rgb;
/// Tarnished brazen — the `Quiescent` (finished-for-now) badge: still warm,
/// no longer bright.
pub const BRAZEN_DIM: Color32 = from_rgb;
/// Ichor red — the wound hue: ✖ error results, `Failed` framing,
/// declined-transfer marks, fatal ops rows.
pub const ICHOR: Color32 = from_rgb;
/// Ash grey — `Stopped` / `Killed`: nothing behind the gate.
pub const ASH: Color32 = from_rgb;
/// Sigil magenta — the "?" uncertainty suffix (probe-degraded, DESIGN
/// §10/§11): never blends into a definite state's hue.
pub const SIGIL: Color32 = from_rgb;
/// Gate violet — yog's own hue: selection, focus, the wordmark. "It is the
/// key and the gate."
pub const GATE: Color32 = from_rgb;
/// The tagline both wordmark seats may set beneath the mark.
pub const TAGLINE: &str = "the key and the gate";
/// The modal scrim — the void laid over everything a modal has made inert
/// (§11, bl-d921). Translucent, not opaque: what the dialog is about stays
/// legible behind it, which is the whole reason a modal floats rather than
/// replaces. It is the *visible* half of a fact the hit test already enforces.
pub const SCRIM: Color32 = from_rgba_premultiplied;
// The void — background strata, darkest at the deepest inset. Private: only
// `visuals()` composes backgrounds; renderers never paint their own.
const VOID_WINDOW: Color32 = from_rgb;
const VOID_PANEL: Color32 = from_rgb;
const VOID_DEEP: Color32 = from_rgb;
const VOID_FAINT: Color32 = from_rgb;
const VOID_EDGE: Color32 = from_rgb;
// Moonlit text ramp — lavender-cast greys, brightening with interactivity.
const MOONLIT: Color32 = from_rgb;
const MOONLIT_BRIGHT: Color32 = from_rgb;
const MOONLIT_FULL: Color32 = from_rgb;
/// Repaint cadence for pulsing in-flight indicators — ~30 fps, smooth enough
/// for the eye and cheap enough for an idle UI. One cadence, so the whole UI
/// pulses in step.
pub const PULSE_REPAINT_DELAY: Duration = from_millis;
/// Pulse frequency in radians per second — ~0.6 Hz, slow enough to read as
/// "alive" rather than "blinking error".
const PULSE_RATE_RAD_PER_SEC: f64 = 4.0;
/// The in-flight pulse colour for `base` at animation-clock `time` (seconds):
/// the hue breathing between dim and full. One animation and one cadence for
/// every pulsing indicator (tool rows, transcript chips, the §11 live-activity
/// classes) so they beat as one; the *hue* is the caller's, which is how the
/// three classes read apart while sharing the beat.
/// How solid a row painted in `tone` is (bl-915e) — the palette's answer for a
/// statement that is not yet a statement. A send is shown in-memory in faded
/// colour, brightening when it is actually locked in as a statement.
///
/// One number, applied to the whole row rather than a second hue per element:
/// what is provisional about a §7.2 pending echo is not *which* colour it wears
/// — it wears exactly the colours it will wear once it lands — but how much of
/// it there is. So no seat gains a parallel palette, and brightening is the
/// same row at full strength rather than a repaint into different hues.
/// [`Tone::Weak`](crate::transcript::Tone::Weak) is the existing vocabulary's
/// word for that, and every other tone is a fact the derivation already
/// asserts, so it paints solid.
/// The whole-app [`egui::Visuals`]: egui's dark theme re-grounded in the
/// void strata, with gate-violet selection and the moonlit text ramp. Pure —
/// testable without a window; [`apply`] installs it.
/// The font families yog paints with: egui's bundled defaults, with the
/// **Monospace font list folded into Proportional** as a fallback tail.
///
/// egui ships Proportional as `[Ubuntu-Light, NotoEmoji, emoji-icon-font]` and
/// Monospace as the same plus `Hack` at the head — so Hack's box-drawing and
/// geometric coverage (`●◐◈⋯▼→⇒`) was reachable only in mono seats, and every
/// proportional seat painting one of those got a tofu box. Folding mono's list
/// in gives the two families the same font *set*, differing only in priority
/// (the proportional face still leads Proportional, Hack still leads
/// Monospace). Coverage is then identical by construction: no seat has to know
/// which family will paint its glyph, and the `tests/glyph_coverage.rs` guard
/// is one invariant over both families rather than a per-site attribution.
/// Derived from the mono list rather than naming "Hack", so an egui bump that
/// adds a mono fallback is picked up without an edit here.
/// Install the congeries fonts and visuals on an egui context — called once
/// from the eframe creation closure (main.rs, coverage-excluded), so theming
/// rides two covered pure functions plus this seam.
/// The hue of a driven integration, keyed by its CLI name: `lernie` the
/// hydra (green), `bz` the brazen head (bronze), `bl` the balls — the
/// congeries itself, so it wears the gate's violet. Anything else reads in
/// the moonlit text default. The one authoritative home for the tool → hue
/// branding (config-editor headings).
/// The hue of a conversation's start-flow ball badge, keyed by its §3.5 join
/// state (DESIGN §3.5, §11): the derived status coloured at a glance. `Bound` is
/// the healthy working ball (hydra green); `Delivered` has gone quiet (ash);
/// `Blocked`/`ClaimedElsewhere` want a look (brazen); an `OrphanedProject` ball
/// is a wound (ichor). The startable/unassigned states never head a conversation
/// ball, so they read in the neutral moonlit default. One home for the mapping;
/// a stamp the join could not resolve (`None` state) the caller paints moonlit.