SurveyStream · Interlocking Loop / Active Signal
One deep anchor, one live current, and a warmth reserved for money. Every ratio on this page is computed in your browser from the tokens themselves — nothing here is transcribed, so the spec cannot drift from the values it documents.
01 — Core brand colours
The aggregator side needs instrument-panel credibility; the taker side needs the reward to feel like it landed. Rather than two palettes, the registers are separated by which accent is permitted to appear. Deepwater and Stream are shared. Payout belongs to value transfer only.
A desaturated teal-navy: reads as navy at a glance, but the teal bias ties it to the cyan accent so the two never look like separate systems.
The live current, and the interactive colour in both modes. Bright enough to carry dark-mode actions, dark enough at 500 to sit on white.
Two ideas routinely collapsed into one. Pulse is flow — something is live and healthy. Payout is money landed. If Payout appears where no money moved, it stops meaning anything.
Teal-biased rather than pure grey, so the neutrals read as chosen rather than inherited. Shipped at seven steps, not the six requested — see the finding in §03.
Each feedback colour carries a light-mode step (dark enough for text on white) and a dark-mode step (bright enough for text on Deepwater). Neither works in both.
02 — Token architecture
A component that reaches past its layer is how a system rots — a button
referencing stream-500 directly cannot be re-themed, and will
silently break in the mode nobody tested.
Resolution order
primitive → semantic (per mode) → component deepwater-500 → interactive → button.primary.bg stream-500 → interactive → button.primary.bg (dark)
The same component token resolves to a different primitive per mode. That indirection is the entire point of the middle layer.
Elevation is intentionally asymmetric. In light mode
bg-elevated equals bg-surface and lift is
carried entirely by shadow. In dark mode shadow is nearly invisible, so lift
is carried by lightness. Adjacent surfaces aren't UI components and are exempt from the 3:1
rule — but a card that must read as a distinct object still takes a
border-subtle.
The rule is luminance, not semantics.
text-on-brand is white, for deep fills
(deepwater-500/600/700, error-500).
text-on-accent is ink, for bright fills
(stream-500, pulse-500,
payout-500, success-500).
text-on-interactive resolves per mode, because
light mode's action fill is dark and dark mode's is bright cyan. One shared value fails:
white on stream-500 is —.
The source guidelines had both as amber — #F2A23C
payout against #DE8A2A warning. "You earned this" and "something
is wrong" would have looked alike. Warning is pushed to a distinctly more orange-brown
step in both modes, and the two never render in the same component. Colour alone must not
carry the distinction: always pair with an icon.
success-payout was split in twoThe brief named one token; it is two.
feedback-success (mint) means the system succeeded.
feedback-payout (amber) means money moved. Merging them spends
the strongest colour in the palette on "settings saved".
Both modes rendered side by side from the same component markup — the only difference is which token set is scoped to the pane.
Tab through either pane to see the focus ring — it is a token
(focus-ring), not a browser default, and it is validated against both
the surface and the canvas below.
03 — Accessibility validation
Against WCAG 2.1 1.4.3 (text: 4.5:1 normal, 3:1 large; AAA at 7:1 / 4.5:1) and 1.4.11 (non-text: 3:1 for component boundaries and state indicators). Disabled controls and purely decorative dividers are exempt and marked as such.
neutral-400 gives exactly 3.00:1 on white but only
2.81:1 on the tinted canvas — a fail. Borders now use
neutral-500 #758D94: 3.28:1 on canvas, 3.50:1 on surface. This is why
the ramp ships at seven steps.
payout-500 is 2.10:1 against white, so an amber badge
has no discernible edge. It requires a payout-600 border at 3.37:1 —
enforced in tokens.css as .ss-badge-payout.
A conventional #2B4653 border is 1.65:1 on
bg-surface — nowhere near 1.4.11. Real borders take
#4E7687 at 3.34:1. The darker hairline survives only as a decorative
divider, which is exempt.
04 — Digital to print
CMYK below is an unmanaged mathematical conversion — a starting point, not a press spec. Real jobs convert through the output profile (GRACoL 2013 coated, SWOP web, PSO Uncoated), because naive conversion produces unusable builds for the darks: Deepwater computes to a muddy, high-ink mix no printer would accept.
ΔE2000 is measured between each hex and the published screen approximation of the Pantone solid coated colour. Under 2 is a strong match, 2–4 usable, above 5 means no good spot equivalent exists. These are candidates for specification, not final values — Pantone matching happens on a physical Bridge or Formula Guide under D50 lighting, never on a monitor.
C70 M50 Y40 K100, 260% total area coverage, inside GRACoL's 320%
limit and holds detail in reversed type.#5FE3EC — nearest spot is ΔE 7.3.#2FE3A2 — nearest spot is ΔE 5.0.Both are high-luminance saturated cyan-greens, the region neither the CMYK gamut nor the Pantone solid range reaches. That the nearest spot inks land this far away is itself the evidence. Treat both as screen-only; where print needs a light accent, tint Spot 2 at 25–40% instead of chasing the on-screen colour. And proof on the actual stock — dark teals shift green on uncoated.