Hand the style off
Ship the same tokens to designers and engineers: JSON for the app, CSS custom properties for the site, PDF for the deck.
Signal Red · tokens
17 tokens--bg#ee2f27--ink#0d0b0a--accent#ffffff--muted#3a211d--headingHelvetica--bodyHelvetica--headingSize54px--tracking1.5%--lineHeight1.02--easingcubic-bezier(0.87, 0, 0.13, 1)--duration480ms--distance14px--stagger70ms--blur6px--overshoot0.86--logoPatternmask--loop2400ms cycleEasing signature
Snap — Slow-fast-slow symmetric cross-over. Counters and tickers.
CSS custom properties
:root {
--bg: #ee2f27;
--ink: #0d0b0a;
--accent: #ffffff;
--muted: #3a211d;
--font-heading: Helvetica, system-ui, sans-serif;
--font-body: Helvetica, system-ui, sans-serif;
--heading-size: 54px;
--heading-tracking: 1.5%;
--heading-leading: 1.02;
--ease: cubic-bezier(0.87, 0, 0.13, 1);
--duration: 480ms;
--rise: 14px;
--stagger: 70ms;
--blur: 6px;
--overshoot: 0.86;
--loop: 2400ms;
}
.rise { animation: riseIn var(--duration) var(--ease) both; }
@keyframes riseIn {
from { opacity: 0; transform: translateY(var(--rise)); }
to { opacity: 1; transform: none; }
}
:root {
--bg: #f5f1e8;
--ink: #141414;
--accent: #ff4d2d;
--muted: #6b6b6b;
--font-heading: Georgia, system-ui, sans-serif;
--font-body: Georgia, system-ui, sans-serif;
--heading-size: 52px;
--heading-tracking: -2.4%;
--heading-leading: 1.02;
--ease: cubic-bezier(0.68, -0.4, 0.32, 1.4);
--duration: 420ms;
--rise: 26px;
--stagger: 40ms;
--blur: 0px;
--overshoot: 0.72;
--loop: 2100ms;
}
.rise { animation: riseIn var(--duration) var(--ease) both; }
@keyframes riseIn {
from { opacity: 0; transform: translateY(var(--rise)); }
to { opacity: 1; transform: none; }
}
:root {
--bg: #ffffff;
--ink: #1c2530;
--accent: #2f6df6;
--muted: #7b8798;
--font-heading: Helvetica, system-ui, sans-serif;
--font-body: Helvetica, system-ui, sans-serif;
--heading-size: 38px;
--heading-tracking: -0.6%;
--heading-leading: 1.2;
--ease: cubic-bezier(0.4, 0, 0.2, 1);
--duration: 780ms;
--rise: 10px;
--stagger: 90ms;
--blur: 4px;
--overshoot: 0.94;
--loop: 3900ms;
}
.rise { animation: riseIn var(--duration) var(--ease) both; }
@keyframes riseIn {
from { opacity: 0; transform: translateY(var(--rise)); }
to { opacity: 1; transform: none; }
}