Back to the library
Manifest scan, row stagger
Variant: Row stagger
The same scan, but each row acknowledges the line as it is crossed — a 60ms-per-row cascade of cleared checks that resolves into the single unlisted record staying flagged. Reach for this when the panel should show that every item was individually inspected, not just that the batch finished. The per-row delays are derived as `calc(index * 0.06s / var(--speed))` so the cascade keeps its spacing when the master speed knob is rolled.
auditscanstaggerstatuslist
The source
A complete HTML document. Paste it into an empty .html file and it plays — no stylesheet, script, font, or image to fetch.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Manifest scan — row stagger</title>
<style>
:root {
/* Neutrals — fixed, never remixed. */
--ivory: #faf9f5;
--paper: #ffffff;
--oat: #e3dacc;
--slate: #141413;
/* Knobs — the remix API. A knob exists iff declared here and used below. */
--hue: 38.8;
--lift: 0;
--chroma: 1;
--round: 1;
--speed: 1;
/* Accents — derived from the knobs with the family's offsets baked in,
so one hue roll moves them together. Defaults reproduce the original hex
(#d97757 / #b85c3e / #788c5d / #b04a3f). */
--clay: oklch(calc(0.6724 + var(--lift)) calc(0.1308 * var(--chroma)) var(--hue));
--clay-d: oklch(calc(0.5797 + var(--lift)) calc(0.127 * var(--chroma)) var(--hue));
--olive: oklch(calc(0.6118 + var(--lift)) calc(0.0713 * var(--chroma)) calc(var(--hue) + 88.3));
--rust: oklch(calc(0.5408 + var(--lift)) calc(0.1357 * var(--chroma)) calc(var(--hue) - 10.3));
/* Clock — every duration in the document runs off --t. */
--cycle: 4s;
--t: calc(var(--cycle) / var(--speed));
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--_step: calc(0.06s / var(--speed)); /* per-row stagger, 30-80ms band */
--_ack: calc(0.9s / var(--speed)); /* one row's acknowledge sub-cycle */
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: var(--ivory);
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
color: var(--slate);
}
.panel {
position: relative;
width: min(360px, 90vw);
padding: clamp(12px, 3.4vw, 18px);
background: var(--paper);
border: 1px solid var(--oat);
border-radius: calc(12px * var(--round));
overflow: hidden;
}
.head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
font-size: clamp(11px, 2.9vw, 12.5px);
letter-spacing: 0.06em;
text-transform: uppercase;
color: color-mix(in oklab, var(--slate) 55%, var(--paper));
margin-bottom: clamp(10px, 2.6vw, 14px);
}
.pip {
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--olive);
animation: pip var(--t) linear infinite;
}
.rows {
position: relative;
display: grid;
gap: clamp(7px, 1.9vw, 9px);
}
.row {
position: relative;
display: flex;
align-items: center;
gap: 9px;
height: clamp(20px, 5.4vw, 24px);
padding: 0 8px;
border-radius: calc(6px * var(--round));
background: color-mix(in oklab, var(--oat) 26%, var(--paper));
}
.bar {
height: 5px;
border-radius: 999px;
background: color-mix(in oklab, var(--slate) 22%, var(--paper));
}
.tick {
width: 10px;
height: 10px;
flex: 0 0 auto;
border-radius: 50%;
border: 1.5px solid color-mix(in oklab, var(--slate) 24%, var(--paper));
}
/* Each cleared row acknowledges once, offset by its index. */
.row.ok .tick {
animation: ack var(--_ack) var(--ease-out) infinite;
animation-delay: calc(var(--_i) * var(--_step));
}
.row:nth-child(1) { --_i: 0; }
.row:nth-child(2) { --_i: 1; }
.row:nth-child(3) { --_i: 2; }
.row:nth-child(4) { --_i: 3; }
.row:nth-child(5) { --_i: 4; }
/* The unlisted row: identical to its neighbours until the scan reaches it. */
.row.stow {
background: color-mix(in oklab, var(--oat) 26%, var(--paper));
animation: flag var(--t) var(--ease-out) infinite;
}
.row.stow .tick {
animation: flagtick var(--t) var(--ease-out) infinite;
}
.row.stow .bar {
animation: flagbar var(--t) var(--ease-out) infinite;
}
.scan {
position: absolute;
left: -6%;
right: -6%;
top: 0;
height: 34%;
pointer-events: none;
background: linear-gradient(
to bottom,
transparent 0%,
color-mix(in oklab, var(--clay) 12%, transparent) 62%,
var(--clay) 100%
);
animation: sweep var(--t) linear infinite;
}
.foot {
margin-top: clamp(10px, 2.6vw, 13px);
font-size: clamp(11px, 2.8vw, 12px);
color: color-mix(in oklab, var(--slate) 50%, var(--paper));
animation: foot var(--t) var(--ease-out) infinite;
}
@keyframes sweep {
0% { transform: translateY(-40%); opacity: 0; }
8% { opacity: 1; }
62% { opacity: 1; }
72% { transform: translateY(285%); opacity: 0; }
100% { transform: translateY(285%); opacity: 0; }
}
/* Short sub-cycle so the cascade repeats within the pass instead of sitting idle. */
@keyframes ack {
0% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: scale(0.97); }
22% { border-color: var(--olive); transform: scale(1); }
60% { border-color: var(--olive); transform: scale(1); }
100% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: scale(0.97); }
}
@keyframes flag {
0%, 58% { background: color-mix(in oklab, var(--oat) 26%, var(--paper)); transform: translateX(0); }
66% { background: color-mix(in oklab, var(--rust) 16%, var(--paper)); transform: translateX(2.2%); }
86% { background: color-mix(in oklab, var(--rust) 14%, var(--paper)); transform: translateX(2.2%); }
100% { background: color-mix(in oklab, var(--oat) 26%, var(--paper)); transform: translateX(0); }
}
@keyframes flagtick {
0%, 58% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: scale(0.97); }
66% { border-color: var(--rust); transform: scale(1); }
86% { border-color: var(--rust); transform: scale(1); }
100% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: scale(0.97); }
}
@keyframes flagbar {
0%, 58% { background: color-mix(in oklab, var(--slate) 22%, var(--paper)); }
66%, 86% { background: var(--rust); }
100% { background: color-mix(in oklab, var(--slate) 22%, var(--paper)); }
}
@keyframes foot {
0%, 58% { opacity: 0.45; color: color-mix(in oklab, var(--slate) 50%, var(--paper)); }
68%, 88% { opacity: 1; color: var(--rust); }
100% { opacity: 0.45; color: color-mix(in oklab, var(--slate) 50%, var(--paper)); }
}
@keyframes pip {
0%, 55% { background: var(--olive); }
68%, 86% { background: var(--rust); }
100% { background: var(--olive); }
}
@media (max-width: 380px) {
.panel { padding: 11px; }
.row { padding: 0 6px; gap: 7px; }
}
@media (prefers-reduced-motion: reduce) {
/* Keep the staggered colour cascade; drop the travelling line and the scaling. */
.scan { animation: none; opacity: 0; }
.row.ok .tick {
animation-duration: calc(var(--cycle) * 0.55 / var(--speed));
}
.row.stow,
.row.stow .tick,
.row.stow .bar,
.foot,
.pip {
animation-duration: calc(var(--cycle) * 2 / var(--speed));
}
@keyframes ack {
0% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: none; }
30%, 65% { border-color: var(--olive); transform: none; }
100% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: none; }
}
@keyframes flag {
0%, 50% { background: color-mix(in oklab, var(--oat) 26%, var(--paper)); transform: none; }
70%, 88% { background: color-mix(in oklab, var(--rust) 14%, var(--paper)); transform: none; }
100% { background: color-mix(in oklab, var(--oat) 26%, var(--paper)); transform: none; }
}
@keyframes flagtick {
0%, 50% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: none; }
70%, 88% { border-color: var(--rust); transform: none; }
100% { border-color: color-mix(in oklab, var(--slate) 24%, var(--paper)); transform: none; }
}
}
</style>
</head>
<body>
<div class="panel">
<div class="head">
<span>Manifest check</span>
<span class="pip" aria-hidden="true"></span>
</div>
<div class="rows">
<div class="row ok"><span class="tick"></span><span class="bar" style="width: 54%"></span></div>
<div class="row ok"><span class="tick"></span><span class="bar" style="width: 70%"></span></div>
<div class="row ok"><span class="tick"></span><span class="bar" style="width: 44%"></span></div>
<div class="row stow"><span class="tick"></span><span class="bar" style="width: 62%"></span></div>
<div class="row ok"><span class="tick"></span><span class="bar" style="width: 50%"></span></div>
<div class="scan" aria-hidden="true"></div>
</div>
<div class="foot">1 record not on the manifest</div>
</div>
</body>
</html>
The variant family
Same idea, one axis moved. Compare them side by side before you commit.