syntheogenesis / dee /static /trace.css
github-actions[bot]
Deploy 2565f24
7b284c7
Raw
History Blame Contribute Delete
13.7 kB
/* ═══════════════════════════════════════════════════════════════════════
LEGIBILITY (2026-08-01) — units, the run strip, and the decision trace.
All of it lives here rather than in app.css for the reason PR #14 kept the
catalog out: app.css is ~8,600 lines with a hostile cascade, and three
people are editing this tree at once. Everything below is either a NEW
class or a deliberate, commented override of an app.css rule; nothing
redefines a token.
Colours are app.css tokens only (--line, --line-strong, --ink,
--ink-strong, --ink-soft, --ink-faint, --bg-card, --bg-subtle, --bg-app,
--danger, --success, --font-mono, --r-2..--r-4, --elev-4, --topbar-h).
Inventing a var() name here would compute the whole shorthand to nothing
— see ENGINEERING.md §13.1.
═══════════════════════════════════════════════════════════════════════ */
/* ── 1. UNITS ─────────────────────────────────────────────────────────────
"Fitness 1.0" had its unit in a hover title only, so for anyone who did
not hover the right 60px it did not exist. These carry it in the page. */
/* The unit chip inside a column header. Subordinate to the header word but
not hidden — it has to survive being read at a glance. */
.th-unit {
font-family: var(--font-mono);
font-size: 9.5px;
letter-spacing: 0.02em;
font-weight: 400;
color: var(--ink-faint);
/* The header cell is .num (right-aligned) and already tight; keep the
chip on the same baseline rather than wrapping it to its own line. */
white-space: nowrap;
}
/* The always-visible legend that answers "what does 1.0 represent?" without
opening the collapsed "How to read this" block. */
.unit-legend {
margin: 0 0 10px;
padding: 8px 11px;
border-left: 2px solid var(--line-strong);
background: var(--bg-subtle);
border-radius: 0 var(--r-2) var(--r-2) 0;
font-size: 12px;
line-height: 1.55;
color: var(--ink-soft);
}
.unit-legend strong { color: var(--ink-strong); font-weight: 600; }
.unit-legend em { font-style: italic; }
.unit-legend--tight { margin: 6px 0 10px; font-size: 11.5px; }
/* Inline unit after a score, in the Radar rows and the round-2 learned rows.
Mono so it reads as a unit rather than as part of the number. */
.rs-unit,
.ls-unit {
font-family: var(--font-mono);
font-size: 9.5px;
color: var(--ink-faint);
letter-spacing: 0.02em;
}
/* ── 2. THE CHAT-LIBRARY CAP ──────────────────────────────────────────────
The reviewer typed 30 into "Variants to generate" and a Turing-run library
came back with 10 rows. The only disclosure was a banner in a different
section of the page. This one sits under the input itself. */
.setting-note {
margin: 6px 0 0;
font-size: 11px;
line-height: 1.5;
color: var(--ink-faint);
}
.setting-note strong { color: var(--ink-soft); font-weight: 600; }
/* Requested-vs-delivered, stated on the result itself. Not an error state —
a chat run capping at 20 is correct behaviour, it just has to be said. */
.count-note {
display: block;
margin-top: 4px;
font-family: var(--font-mono);
font-size: 10.5px;
letter-spacing: 0.02em;
color: var(--ink-faint);
}
.count-note b { color: var(--ink-soft); font-weight: 600; }
/* ── 3. INTERACTION RADAR PROGRESS ────────────────────────────────────────
One ESM-2 forward pass per variant, serial, with no signal at all beyond a
button reading "Analyzing…". Tool rows in the rail have had an elapsed
clock since the CRISPR index made two minutes of silence read as a hang;
this path never used it. */
.radar-elapsed {
font-family: var(--font-mono);
font-size: 10.5px;
letter-spacing: 0.03em;
color: var(--ink-faint);
font-variant-numeric: tabular-nums; /* so the seconds don't jitter */
}
.radar-progress {
display: block;
height: 2px;
margin-top: 7px;
background: var(--line);
overflow: hidden;
border-radius: 1px;
}
/* Indeterminate on purpose. The server returns one response for the whole
library, so there is no honest per-variant fraction to draw — a bar that
filled to 60% would be inventing progress. This says "working", and the
elapsed clock next to it says how long for. */
.radar-progress::after {
content: "";
display: block;
width: 34%;
height: 100%;
background: var(--ink-soft);
animation: tdRadarSlide 1.25s var(--ease-snap) infinite;
}
@keyframes tdRadarSlide {
0% { transform: translateX(-100%); }
100% { transform: translateX(320%); }
}
@media (prefers-reduced-motion: reduce) {
.radar-progress::after { animation: none; width: 100%; opacity: 0.35; }
}
/* ── 4. THE RUN STRIP (was the unlabelled "context 0% · $0.11") ───────────
Two numbers with no nouns read as noise. They are kept — cost is exactly
what someone deciding whether to keep going wants — but named, given a
denominator so a sub-1% reading isn't rendered as a flat "0%", and given
the trace as somewhere to go and read what they mean in full sentences. */
/* The bar was flex:1 and ate the row; the text now carries the meaning, so
the bar becomes a fixed-width glance indicator. Specificity (0,2,0) beats
app.css's (0,1,0) `.cp-meter-bar`, and this file loads after it — both
conditions are needed (ENGINEERING.md §13.2/§13.3). */
.cp-meter .cp-meter-bar { flex: 0 0 28px; }
/* Wraps rather than truncates. Measured at 390px (the rail's real width):
"Context 41k / 1M (4%) · $0.14 model cost" overflows by 7px, and an
ellipsis there eats "model cost" — putting the label back out of reach on
exactly the narrow screens this change set exists to serve. A second line
costs 12px; a hidden noun costs the whole fix. */
.cp-meter .cp-meter-t {
flex: 1 1 auto;
min-width: 0;
white-space: normal;
line-height: 1.35;
font-variant-numeric: tabular-nums;
}
/* The way into the trace. Text, not a glyph: the whole complaint upstream of
this file is unlabelled controls. */
.cp-trace-btn {
flex: 0 0 auto;
font-family: var(--font-mono);
font-size: 9.5px;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 3px 8px;
border: 1px solid var(--line-strong);
border-radius: 999px;
background: transparent;
color: var(--ink-soft);
cursor: pointer;
white-space: nowrap;
}
.cp-trace-btn:hover { border-color: var(--ink-soft); color: var(--ink-strong); }
.cp-trace-btn[hidden] { display: none; }
/* Matches .cp-icon's rule: the 57px collapsed rail has room for nothing. */
body[data-cockpit="min"] .cp-trace-btn { display: none; }
/* ── 5. THE DECISION TRACE ────────────────────────────────────────────────
The rail already showed every step; it showed them as a river. Ten minutes
in, "what did it actually do and why" is unanswerable because the answer
scrolled past. This is the same events, held still. */
.td-trace {
position: fixed;
inset: 0;
z-index: 60; /* above the rail (z 40s) and the canvas */
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
.td-trace[hidden] { display: none; }
.td-trace-scrim {
position: absolute;
inset: 0;
background: rgba(10, 10, 10, 0.42);
border: 0;
padding: 0;
cursor: pointer;
}
.td-trace-panel {
position: relative;
display: flex;
flex-direction: column;
width: min(760px, 100%);
max-height: min(82vh, 900px);
background: var(--bg-card);
border: 1px solid var(--line-strong);
border-radius: var(--r-4);
box-shadow: var(--elev-4);
overflow: hidden;
}
.td-trace-head {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 16px 18px 12px;
border-bottom: 1px solid var(--line);
flex: 0 0 auto;
}
.td-trace-head h2 {
margin: 0;
font-size: 15px;
letter-spacing: -0.01em;
color: var(--ink-strong);
}
.td-trace-sub {
margin: 4px 0 0;
font-size: 12px;
line-height: 1.5;
color: var(--ink-faint);
}
.td-trace-x {
margin-left: auto;
flex: 0 0 auto;
width: 26px;
height: 26px;
line-height: 1;
font-size: 15px;
border: 1px solid var(--line-strong);
border-radius: var(--r-2);
background: transparent;
color: var(--ink-soft);
cursor: pointer;
}
.td-trace-x:hover { border-color: var(--ink-soft); color: var(--ink-strong); }
/* Goal + the two meters, spelled out in words. This is where "context 3%"
is allowed the room to say what it is. */
.td-trace-meta {
flex: 0 0 auto;
padding: 12px 18px;
border-bottom: 1px solid var(--line);
background: var(--bg-subtle);
font-size: 12px;
line-height: 1.6;
color: var(--ink-soft);
}
.td-trace-goal {
margin: 0 0 8px;
color: var(--ink-strong);
font-size: 13px;
}
.td-trace-goal b {
display: block;
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--ink-faint);
font-weight: 500;
margin-bottom: 2px;
}
.td-trace-facts { margin: 0; padding: 0; list-style: none; }
.td-trace-facts li { margin: 0; }
.td-trace-facts b { color: var(--ink-strong); font-weight: 600; }
.td-trace-list {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
margin: 0;
padding: 0;
list-style: none;
-webkit-overflow-scrolling: touch;
}
.td-step { border-bottom: 1px solid var(--line); }
.td-step:last-child { border-bottom: 0; }
.td-step > details > summary {
display: flex;
align-items: baseline;
gap: 10px;
padding: 10px 18px;
cursor: pointer;
list-style: none;
}
.td-step > details > summary::-webkit-details-marker { display: none; }
.td-step > details > summary:hover { background: var(--bg-subtle); }
.td-step > details[open] > summary { background: var(--bg-subtle); }
.td-step-n {
flex: 0 0 auto;
min-width: 20px;
font-family: var(--font-mono);
font-size: 10px;
color: var(--ink-faint);
font-variant-numeric: tabular-nums;
}
.td-step-main { flex: 1 1 auto; min-width: 0; }
.td-step-obj {
display: block;
font-size: 13px;
color: var(--ink-strong);
overflow-wrap: break-word;
}
.td-step-args {
display: block;
margin-top: 1px;
font-family: var(--font-mono);
font-size: 10.5px;
color: var(--ink-faint);
overflow-wrap: break-word;
}
.td-step-status {
flex: 0 0 auto;
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 2px 7px;
border-radius: 999px;
border: 1px solid var(--line-strong);
color: var(--ink-faint);
}
.td-step--ok .td-step-status { color: var(--success); border-color: var(--success); }
.td-step--fail .td-step-status { color: var(--danger); border-color: var(--danger); }
.td-step--run .td-step-status { color: var(--ink-soft); }
.td-step-t {
flex: 0 0 auto;
font-family: var(--font-mono);
font-size: 10px;
color: var(--ink-faint);
font-variant-numeric: tabular-nums;
min-width: 34px;
text-align: right;
}
.td-step-detail {
padding: 2px 18px 14px 48px;
font-size: 12.5px;
line-height: 1.6;
color: var(--ink);
}
.td-step-lbl {
margin: 10px 0 2px;
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--ink-faint);
}
.td-step-detail p { margin: 0; overflow-wrap: break-word; }
.td-step-detail p.td-muted { color: var(--ink-faint); font-style: italic; }
.td-step-kv {
margin: 0;
display: grid;
grid-template-columns: minmax(0, auto) minmax(0, 1fr);
gap: 1px 12px;
font-family: var(--font-mono);
font-size: 11px;
}
.td-step-kv dt { color: var(--ink-faint); }
.td-step-kv dd { margin: 0; color: var(--ink-strong); overflow-wrap: anywhere; }
/* Plan steps replayed inside a "Plan" entry. */
.td-plan { margin: 0; padding: 0; list-style: none; font-size: 12.5px; }
.td-plan li { display: flex; gap: 8px; align-items: baseline; }
.td-plan-g { flex: 0 0 auto; width: 12px; color: var(--ink-faint); font-family: var(--font-mono); font-size: 11px; }
.td-plan--done > span:last-child { color: var(--ink-faint); }
.td-trace-empty {
margin: 0;
padding: 28px 18px;
text-align: center;
font-size: 12.5px;
color: var(--ink-faint);
}
.td-trace-empty[hidden] { display: none; }
.td-trace-foot {
flex: 0 0 auto;
padding: 10px 18px;
border-top: 1px solid var(--line);
font-size: 11px;
line-height: 1.5;
color: var(--ink-faint);
}
/* The rail is ~390px and phones are narrower still; a 24px inset frame there
wastes a third of the screen. Full-bleed sheet instead. */
@media (max-width: 720px) {
.td-trace { padding: 0; align-items: stretch; }
.td-trace-panel {
width: 100%;
max-height: none;
height: 100%;
border: 0;
border-radius: 0;
}
.td-step-detail { padding-left: 18px; }
}