The Experiment Capture panel, read against the token contract
The form layout landed correct in #105 — aligned grid, grouped sections. What's left is the half-styled read flagged on #101: the panel uses the tokens but doesn't yet speak them. Six gaps, each a small, in-system fix.
Form grid (#105) — correct6 token gaps remainreviewed vs sprout-tokens.css
Before / after
same markup, same tokens — only the gaps closed
before
Experiment Capture experiment mode
writes an isolated experiments/<id>/
idle
pill wraps mid-word when the row tightens
Start and Stop are the same neutral pill — no primary
status is lonely mono text, not a state
after
Experiment Capture experiment mode
isolated experiments/
recording
pill holds on one line — white-space:nowrap
Start fills --leaf; Stop stays the neutral secondary
status is a dot + live glow on --leaf
The six gaps
each names the token it should already be honoring
1
The “proposed” pills wrap mid-word
logging mode / experiment mode break across two lines when .panel-h tightens. A pill is an atom — it never wraps. fix → white-space:nowrap on .proposed
2
Button labels wrap too
Start logging breaks to Start / logging in a tight row. fix → white-space:nowrap on .btn
3
No action hierarchy — every button is a neutral outline
Start (constructive) and Stop read identically, so the primary action doesn't lead. The contract names --leaf as the brand action. fix → .btn.primary fills --leaf; Stop stays the secondary outline
4
Status is text, not a state
idle / running / error are core states but render as muted mono text. The system makes state a color, and the tokens note a live glow: box-shadow:0 0 8px currentColor. fix → dot + label; idle=--muted, running=--leaf (glow), error=--st-fault
5
The Monitor row sits on three baselines
In .capctl the lone — status, the floating-label port field, and the two buttons each land at a different height. fix → align-items:center; push status to its own end-slot (margin-left:auto)
6
The two modes don't read as a pair
Monitor (the always-on baseline) and Experiment (bounded, isolated) are near-identical stacked cards — nothing signals which is the safe living logger vs the throwaway test. Reuse the device already on the summary cards: a 5px left accent. fix → Monitor accent --leaf, Experiment accent --st-predicted
Also, beyond this panel —the chart series use SENSOR_COLORS = ['#1E40AF','#7C5CFF'…], generic blues/purples that aren't in the token ramp. Out of scope for #101's form, but flagging for #99: series color should derive from the band ramp or a sanctioned categorical set so the dashboard reads as one palette.
Lift this
paste into dashboard_template.html's <style> — pure token deltas, no new values
/* 1 + 2 — pills and buttons are atoms; never wrap */
.proposed, .btn { white-space: nowrap; }
/* 3 — primary action = the brand green; Stop stays the neutral outline */
.btn.primary { background: var(--leaf); border-color: var(--leaf); color: #fff; }
.btn.primary:hover { background: #2C9247; border-color: #2C9247; }
/* then give each Start: class="btn primary" *//* 4 — status is a state: a dot + label, with the live glow from the tokens */
.capstatus { display: inline-flex; align-items: center; gap: 7px; margin-left: auto; }
.capstatus::before { content: ""; width: 8px; height: 8px; border-radius: var(--r-pill);
background: currentColor; }
.capstatus.run { color: var(--leaf); font-weight: 600; }
.capstatus.run::before { box-shadow: 0 0 8px currentColor; }
.capstatus.err { color: var(--st-fault); }
/* 5 — one baseline for the control row */
.capctl { align-items: center; }
/* 6 — the two modes read as a pair (same accent device as .scard) */
#monitorCard, #captureCard { position: relative; overflow: hidden; }
#monitorCard::before, #captureCard::before { content: ""; position: absolute;
left: 0; top: 0; bottom: 0; width: 5px; }
#monitorCard::before { background: var(--leaf); } /* the living baseline */
#captureCard::before { background: var(--st-predicted); } /* the bounded test */