Back to the library
Partition panels settle
Variant: Staggered
Each panel keeps the 260ms swing of the single-beat version but starts 55ms after the one to its left, so the screen unfolds across the row instead of all at once. Use this when the bays behind the partition hold distinct items and you want the eye to travel left to right. The stagger step is derived from the master clock, so a speed roll compresses the cascade without changing its ratios.
entrancerevealpanelstaggercascade
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>Partition panels settle — staggered</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: 3.2s; /* the authored master loop */
--t: calc(var(--cycle) / var(--speed));
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--_step: calc(0.055s / var(--speed)); /* 55ms cascade offset per panel */
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
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);
}
.stage {
width: min(420px, 92vw);
padding: clamp(14px, 4vw, 22px);
background: var(--paper);
border: 1px solid var(--oat);
border-radius: calc(14px * var(--round));
}
.caption {
display: flex;
align-items: center;
gap: 8px;
font-size: clamp(11px, 3vw, 12.5px);
letter-spacing: 0.06em;
text-transform: uppercase;
color: color-mix(in oklab, var(--slate) 55%, var(--ivory));
margin-bottom: clamp(10px, 3vw, 14px);
}
.caption .dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--clay);
animation: pip var(--t) linear infinite;
}
.screen {
position: relative;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: clamp(5px, 1.6vw, 8px);
height: clamp(108px, 30vw, 140px);
perspective: 620px;
}
.bay {
position: relative;
overflow: hidden;
border-radius: calc(9px * var(--round));
background: color-mix(in oklab, var(--ivory) 78%, var(--oat));
}
.bay::after {
content: '';
position: absolute;
left: 14%;
right: 14%;
bottom: 16%;
height: 34%;
border-radius: calc(5px * var(--round));
background: color-mix(in oklab, var(--olive) 42%, var(--paper));
}
.bay::before {
content: '';
position: absolute;
left: 14%;
top: 18%;
width: 42%;
height: 12%;
border-radius: 999px;
background: color-mix(in oklab, var(--slate) 22%, var(--ivory));
}
.panel {
position: absolute;
inset: 0;
border-radius: calc(9px * var(--round));
background:
repeating-linear-gradient(
90deg,
color-mix(in oklab, var(--clay) 88%, var(--paper)) 0 3px,
color-mix(in oklab, var(--clay-d) 82%, var(--paper)) 3px 6px
);
transform-origin: left center;
will-change: transform, opacity;
animation: fold var(--t) var(--ease-out) infinite;
/* Negative delay: the cascade runs forward without an empty first cycle. */
animation-delay: calc(var(--_i) * var(--_step) - var(--t));
}
.bay:nth-child(1) .panel { --_i: 0; }
.bay:nth-child(2) .panel { --_i: 1; }
.bay:nth-child(3) .panel { --_i: 2; }
.bay:nth-child(4) .panel { --_i: 3; }
.bay:nth-child(even) .panel { transform-origin: right center; }
@keyframes fold {
0% { transform: rotateY(0deg) scale(1); opacity: 1; }
8.125%, 74% { transform: rotateY(-72deg) scale(0.97); opacity: 0; }
82% { transform: rotateY(0deg) scale(1); opacity: 1; }
100% { transform: rotateY(0deg) scale(1); opacity: 1; }
}
@keyframes pip {
0%, 6% { opacity: 1; }
40% { opacity: 0.3; }
76%, 100% { opacity: 1; }
}
@media (max-width: 380px) {
.stage { padding: 12px; }
.caption { margin-bottom: 9px; }
}
@media (prefers-reduced-motion: reduce) {
.panel {
animation: fade calc(var(--cycle) * 2 / var(--speed)) var(--ease-out) infinite;
animation-delay: calc(var(--_i) * var(--_step) * 2);
transform: none;
}
.caption .dot {
animation: pip calc(var(--cycle) * 2 / var(--speed)) linear infinite;
}
@keyframes fade {
0% { opacity: 1; }
10%, 74% { opacity: 0.12; }
84%, 100% { opacity: 1; }
}
}
</style>
</head>
<body>
<div class="stage">
<div class="caption"><span class="dot"></span>Workspace ready</div>
<div class="screen">
<div class="bay"><div class="panel"></div></div>
<div class="bay"><div class="panel"></div></div>
<div class="bay"><div class="panel"></div></div>
<div class="bay"><div class="panel"></div></div>
</div>
</div>
</body>
</html>
The variant family
Same idea, one axis moved. Compare them side by side before you commit.