Salience Sweep
A crest of heat crosses an 18×10 attention matrix: every cell flares as the wavefront reaches it, most fall back to their resting weight, and twenty are found significant and stay lit with a rust seed mark. The sweep runs on cubic-bezier(0.77,0,0.175,1) and each cell's delay is that curve inverted at its column, so the crest hesitates at the left margin, rips through the middle, and decelerates out the right — the flare envelope is kept to 130ms up / 250ms down precisely so the accelerating middle reads as a widening crest instead of the whole grid igniting at once. Reach for it when you need to show selection, scoring, or attention over a field of data — anywhere a system looks at everything and keeps only some of it.
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>Salience Sweep</title>
<style>
:root {
--ivory: #FAF9F5;
--paper: #FFFFFF;
--slate: #141413;
--clay: #D97757;
--oat: #E3DACC;
--olive: #788C5D;
--rust: #B04A3F;
--gray-300:#D1CFC5;
--gray-500:#87867F;
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
/* Declared for reference. Inside @keyframes the timing functions are
written out literally — `animation-timing-function: var(--x)` is not
reliably honoured there, and silently falls back to `ease`. */
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
/* One shared clock. Every cell runs this same 9.6s loop; only its delay
differs, so flare, hold and dissolve all propagate in the same order. */
--cycle: 9600ms;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
min-height: 100vh;
display: grid;
place-items: center;
background: var(--ivory);
font-family: var(--sans);
color: var(--slate);
-webkit-font-smoothing: antialiased;
}
/* ─────────────────────────────────────────────────────────────
KEEP FROM HERE: .card and everything inside it, the @keyframes
blocks, the :root tokens, and the prefers-reduced-motion block.
The per-cell `--d` delays are baked into the markup — they are
the inverse of the sweep's easing curve sampled at each column,
which is what keeps the wavefront and the cell flares in lockstep.
───────────────────────────────────────────────────────────── */
.card {
width: min(92vw, 560px);
background: var(--paper);
border: 1px solid var(--gray-300);
border-radius: 12px;
padding: 22px 24px 18px;
}
.head, .foot {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
font-family: var(--mono);
font-size: 10.5px;
letter-spacing: 0.11em;
text-transform: uppercase;
color: var(--gray-500);
}
.head { margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--oat); }
.head b { font-weight: 500; color: var(--slate); letter-spacing: 0.11em; }
.foot { margin-top: 14px; }
.plot { display: flex; align-items: stretch; gap: 10px; }
.ylab {
writing-mode: vertical-rl;
transform: rotate(180deg);
font-family: var(--mono);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--gray-500);
display: flex;
align-items: center;
justify-content: center;
border-left: 1px solid var(--olive);
padding-right: 2px;
}
.matrix {
position: relative;
flex: 1;
overflow: hidden;
padding: 3px;
}
.grid {
display: grid;
grid-template-columns: repeat(18, 1fr);
gap: 4px;
}
/* Each cell is three flat layers: a static baseline square whose alpha is
the resting weight, a heat layer, and a seed dot for the cells that hold.
Only opacity and transform ever animate. */
.grid i {
position: relative;
aspect-ratio: 1;
border-radius: 2px;
background: rgb(135 134 127 / var(--b));
}
.grid i::before,
.grid i::after {
content: "";
position: absolute;
border-radius: inherit;
will-change: transform, opacity;
}
/* heat layer — settled state is the base; keyframes return to it */
.grid i::before {
inset: 0;
background: var(--clay);
opacity: 0;
transform: scale(0.92);
animation: heat var(--cycle) linear var(--d) infinite both;
}
.grid i.warm::before { animation-name: heat-warm; }
.grid i.hit::before { animation-name: heat-hit; }
/* seed dot — the mark that says "this one was kept" */
.grid i::after {
inset: 50%;
width: 25%;
height: 25%;
margin: -12.5% 0 0 -12.5%;
border-radius: 50%;
background: var(--rust);
opacity: 0;
transform: scale(0.4);
}
.grid i.hit::after { animation: seed var(--cycle) linear var(--d) infinite both; }
/* ── the wavefront ──────────────────────────────────────────
A single band, 40% of the matrix wide, crossing on the strong
in-out curve: it hesitates at the left margin, rips through the
middle, and decelerates out the right. The cell delays above are
that curve inverted, so a cell flares exactly as the core reaches it. */
.sweep {
position: absolute;
inset: -4px 0;
width: 40%;
pointer-events: none;
transform: translateX(-50%);
animation: sweep-move var(--cycle) linear infinite both;
will-change: transform;
}
.band {
position: absolute;
inset: 0;
opacity: 0;
animation: sweep-fade var(--cycle) linear infinite both;
background: linear-gradient(90deg,
rgb(217 119 87 / 0) 0%,
rgb(217 119 87 / 0.05) 22%,
rgb(217 119 87 / 0.16) 42%,
rgb(217 119 87 / 0.26) 50%,
rgb(217 119 87 / 0.04) 58%,
rgb(217 119 87 / 0) 66%);
}
.band::after {
content: "";
position: absolute;
top: 0; bottom: 0; left: 50%;
width: 1px;
background: linear-gradient(180deg,
rgb(176 74 63 / 0), rgb(176 74 63 / 0.45) 26%, rgb(176 74 63 / 0.45) 74%, rgb(176 74 63 / 0));
}
.tally {
display: inline-flex;
align-items: center;
gap: 7px;
color: var(--slate);
opacity: 0;
transform: translateY(3px);
animation: tally var(--cycle) linear infinite both;
}
.tally em { width: 6px; height: 6px; border-radius: 50%; background: var(--rust); }
/* ── keyframes ─────────────────────────────────────────────
Percentages of the 9.6s cycle. The flare envelope is deliberately
short — 130ms up, 250ms down — because the sweep's easing bunches the
middle columns only ~40ms apart; a long envelope would light the whole
matrix at once instead of reading as a crest. Rise on ease-out so the
hit registers immediately, settle and dissolve on ease-in-out. */
@keyframes heat {
0% { opacity: 0; transform: scale(0.92); animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
1.35% { opacity: 1; transform: scale(1.12); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
4% { opacity: 0; transform: scale(0.92); }
100% { opacity: 0; transform: scale(0.92); }
}
@keyframes heat-warm {
0% { opacity: 0; transform: scale(0.92); animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
1.35% { opacity: 1; transform: scale(1.12); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
4% { opacity: 0.24; transform: scale(1); }
75% { opacity: 0.24; transform: scale(1); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
82% { opacity: 0; transform: scale(0.92); }
100% { opacity: 0; transform: scale(0.92); }
}
@keyframes heat-hit {
0% { opacity: 0; transform: scale(0.92); animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
1.35% { opacity: 1; transform: scale(1.12); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
4% { opacity: 1; transform: scale(1); }
75% { opacity: 1; transform: scale(1); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
82% { opacity: 0; transform: scale(0.92); }
100% { opacity: 0; transform: scale(0.92); }
}
/* The seed lands a beat after the flare peak: the cell is judged, then marked. */
@keyframes seed {
0% { opacity: 0; transform: scale(0.4); }
1.35% { opacity: 0; transform: scale(0.4); animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
5% { opacity: 1; transform: scale(1); }
75% { opacity: 1; transform: scale(1); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
81% { opacity: 0; transform: scale(0.4); }
100% { opacity: 0; transform: scale(0.4); }
}
@keyframes sweep-move {
0% { transform: translateX(-50%); }
1.25% { transform: translateX(-50%); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
36.67% { transform: translateX(200%); }
100% { transform: translateX(200%); }
}
@keyframes sweep-fade {
0% { opacity: 0; animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
4% { opacity: 1; }
31% { opacity: 1; animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
36.67% { opacity: 0; }
100% { opacity: 0; }
}
@keyframes tally {
0% { opacity: 0; transform: translateY(3px); }
38% { opacity: 0; transform: translateY(3px); animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); }
44% { opacity: 1; transform: translateY(0); }
84% { opacity: 1; transform: translateY(0); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
89% { opacity: 0; transform: translateY(3px); }
100% { opacity: 0; transform: translateY(3px); }
}
/* ── reduced motion ────────────────────────────────────────
No sweep, no flare. The base styles below are the settled
state: the cells that were found significant stay lit, the
rest stay at their resting weight. Same information, no travel. */
@media (prefers-reduced-motion: reduce) {
/* Selectors match the specificity of the rules that started the
animations, otherwise `animation: none` loses and the page still moves. */
.grid i::before,
.grid i::after,
.grid i.warm::before,
.grid i.hit::before,
.grid i.hit::after,
.sweep, .band, .tally { animation: none; }
.sweep { display: none; }
.grid i.warm::before { opacity: 0.24; transform: scale(1); }
.grid i.hit::before { opacity: 1; transform: scale(1); }
.grid i.hit::after { opacity: 1; transform: scale(1); }
.tally { opacity: 1; transform: none; }
}
</style>
</head>
<body>
<div class="card">
<div class="head">
<b>Salience sweep</b>
<span>layer 7 · head 3</span>
</div>
<div class="plot">
<div class="ylab">query</div>
<div class="matrix">
<div class="grid">
<i class="" style="--d:857ms;--b:0.318"></i>
<i class="hit" style="--d:1181ms;--b:0.305"></i>
<i class="hit" style="--d:1401ms;--b:0.396"></i>
<i class="hit" style="--d:1517ms;--b:0.285"></i>
<i class="" style="--d:1612ms;--b:0.228"></i>
<i class="" style="--d:1668ms;--b:0.261"></i>
<i class="" style="--d:1739ms;--b:0.144"></i>
<i class="" style="--d:1780ms;--b:0.213"></i>
<i class="" style="--d:1815ms;--b:0.201"></i>
<i class="" style="--d:1859ms;--b:0.259"></i>
<i class="" style="--d:1891ms;--b:0.167"></i>
<i class="" style="--d:1933ms;--b:0.200"></i>
<i class="" style="--d:1971ms;--b:0.240"></i>
<i class="" style="--d:2076ms;--b:0.178"></i>
<i class="" style="--d:2138ms;--b:0.176"></i>
<i class="" style="--d:2306ms;--b:0.156"></i>
<i class="" style="--d:2485ms;--b:0.248"></i>
<i class="" style="--d:2867ms;--b:0.293"></i>
<i class="" style="--d:835ms;--b:0.212"></i>
<i class="warm" style="--d:1157ms;--b:0.370"></i>
<i class="warm" style="--d:1370ms;--b:0.322"></i>
<i class="hit" style="--d:1466ms;--b:0.319"></i>
<i class="hit" style="--d:1567ms;--b:0.284"></i>
<i class="hit" style="--d:1653ms;--b:0.351"></i>
<i class="" style="--d:1678ms;--b:0.185"></i>
<i class="" style="--d:1735ms;--b:0.272"></i>
<i class="" style="--d:1777ms;--b:0.211"></i>
<i class="" style="--d:1811ms;--b:0.226"></i>
<i class="" style="--d:1833ms;--b:0.135"></i>
<i class="" style="--d:1880ms;--b:0.257"></i>
<i class="" style="--d:1947ms;--b:0.230"></i>
<i class="" style="--d:2035ms;--b:0.217"></i>
<i class="" style="--d:2107ms;--b:0.295"></i>
<i class="" style="--d:2258ms;--b:0.247"></i>
<i class="" style="--d:2483ms;--b:0.227"></i>
<i class="" style="--d:2838ms;--b:0.148"></i>
<i class="" style="--d:817ms;--b:0.131"></i>
<i class="warm" style="--d:1130ms;--b:0.306"></i>
<i class="" style="--d:1331ms;--b:0.197"></i>
<i class="" style="--d:1480ms;--b:0.164"></i>
<i class="warm" style="--d:1535ms;--b:0.330"></i>
<i class="hit" style="--d:1620ms;--b:0.368"></i>
<i class="hit" style="--d:1660ms;--b:0.394"></i>
<i class="" style="--d:1716ms;--b:0.184"></i>
<i class="" style="--d:1751ms;--b:0.205"></i>
<i class="" style="--d:1801ms;--b:0.225"></i>
<i class="" style="--d:1838ms;--b:0.110"></i>
<i class="" style="--d:1876ms;--b:0.245"></i>
<i class="" style="--d:1923ms;--b:0.293"></i>
<i class="" style="--d:2013ms;--b:0.219"></i>
<i class="" style="--d:2087ms;--b:0.295"></i>
<i class="" style="--d:2242ms;--b:0.236"></i>
<i class="" style="--d:2430ms;--b:0.188"></i>
<i class="" style="--d:2830ms;--b:0.152"></i>
<i class="" style="--d:802ms;--b:0.276"></i>
<i class="warm" style="--d:1123ms;--b:0.272"></i>
<i class="" style="--d:1306ms;--b:0.171"></i>
<i class="" style="--d:1447ms;--b:0.163"></i>
<i class="" style="--d:1534ms;--b:0.184"></i>
<i class="warm" style="--d:1620ms;--b:0.369"></i>
<i class="hit" style="--d:1657ms;--b:0.292"></i>
<i class="hit" style="--d:1709ms;--b:0.403"></i>
<i class="warm" style="--d:1724ms;--b:0.306"></i>
<i class="" style="--d:1791ms;--b:0.274"></i>
<i class="" style="--d:1824ms;--b:0.236"></i>
<i class="" style="--d:1874ms;--b:0.198"></i>
<i class="" style="--d:1940ms;--b:0.172"></i>
<i class="" style="--d:2002ms;--b:0.224"></i>
<i class="" style="--d:2077ms;--b:0.184"></i>
<i class="" style="--d:2230ms;--b:0.185"></i>
<i class="" style="--d:2455ms;--b:0.197"></i>
<i class="" style="--d:2834ms;--b:0.224"></i>
<i class="" style="--d:792ms;--b:0.250"></i>
<i class="warm" style="--d:1108ms;--b:0.362"></i>
<i class="" style="--d:1303ms;--b:0.230"></i>
<i class="" style="--d:1451ms;--b:0.217"></i>
<i class="" style="--d:1520ms;--b:0.178"></i>
<i class="warm" style="--d:1605ms;--b:0.346"></i>
<i class="" style="--d:1666ms;--b:0.225"></i>
<i class="warm" style="--d:1709ms;--b:0.373"></i>
<i class="hit" style="--d:1724ms;--b:0.298"></i>
<i class="hit" style="--d:1789ms;--b:0.357"></i>
<i class="" style="--d:1828ms;--b:0.369"></i>
<i class="" style="--d:1880ms;--b:0.211"></i>
<i class="" style="--d:1894ms;--b:0.180"></i>
<i class="" style="--d:1968ms;--b:0.217"></i>
<i class="" style="--d:2097ms;--b:0.194"></i>
<i class="" style="--d:2242ms;--b:0.246"></i>
<i class="" style="--d:2439ms;--b:0.184"></i>
<i class="" style="--d:2796ms;--b:0.167"></i>
<i class="" style="--d:785ms;--b:0.127"></i>
<i class="warm" style="--d:1129ms;--b:0.383"></i>
<i class="" style="--d:1308ms;--b:0.271"></i>
<i class="" style="--d:1453ms;--b:0.161"></i>
<i class="" style="--d:1550ms;--b:0.161"></i>
<i class="" style="--d:1602ms;--b:0.320"></i>
<i class="" style="--d:1635ms;--b:0.202"></i>
<i class="" style="--d:1706ms;--b:0.181"></i>
<i class="" style="--d:1733ms;--b:0.322"></i>
<i class="warm" style="--d:1758ms;--b:0.285"></i>
<i class="hit" style="--d:1829ms;--b:0.310"></i>
<i class="warm" style="--d:1841ms;--b:0.395"></i>
<i class="" style="--d:1926ms;--b:0.196"></i>
<i class="" style="--d:1970ms;--b:0.235"></i>
<i class="" style="--d:2090ms;--b:0.156"></i>
<i class="" style="--d:2218ms;--b:0.238"></i>
<i class="" style="--d:2423ms;--b:0.158"></i>
<i class="" style="--d:2809ms;--b:0.131"></i>
<i class="" style="--d:792ms;--b:0.253"></i>
<i class="warm" style="--d:1139ms;--b:0.269"></i>
<i class="" style="--d:1316ms;--b:0.280"></i>
<i class="" style="--d:1431ms;--b:0.200"></i>
<i class="" style="--d:1520ms;--b:0.262"></i>
<i class="warm" style="--d:1620ms;--b:0.343"></i>
<i class="" style="--d:1640ms;--b:0.270"></i>
<i class="" style="--d:1701ms;--b:0.202"></i>
<i class="" style="--d:1738ms;--b:0.211"></i>
<i class="" style="--d:1778ms;--b:0.220"></i>
<i class="warm" style="--d:1808ms;--b:0.305"></i>
<i class="hit" style="--d:1859ms;--b:0.328"></i>
<i class="hit" style="--d:1935ms;--b:0.276"></i>
<i class="" style="--d:1975ms;--b:0.305"></i>
<i class="" style="--d:2108ms;--b:0.156"></i>
<i class="" style="--d:2210ms;--b:0.256"></i>
<i class="" style="--d:2432ms;--b:0.267"></i>
<i class="" style="--d:2819ms;--b:0.144"></i>
<i class="" style="--d:790ms;--b:0.268"></i>
<i class="warm" style="--d:1166ms;--b:0.344"></i>
<i class="" style="--d:1353ms;--b:0.140"></i>
<i class="" style="--d:1461ms;--b:0.205"></i>
<i class="" style="--d:1565ms;--b:0.140"></i>
<i class="" style="--d:1639ms;--b:0.345"></i>
<i class="" style="--d:1668ms;--b:0.228"></i>
<i class="" style="--d:1699ms;--b:0.238"></i>
<i class="" style="--d:1766ms;--b:0.172"></i>
<i class="" style="--d:1809ms;--b:0.152"></i>
<i class="" style="--d:1823ms;--b:0.145"></i>
<i class="" style="--d:1869ms;--b:0.266"></i>
<i class="hit" style="--d:1923ms;--b:0.318"></i>
<i class="hit" style="--d:1987ms;--b:0.350"></i>
<i class="warm" style="--d:2109ms;--b:0.382"></i>
<i class="" style="--d:2256ms;--b:0.213"></i>
<i class="" style="--d:2444ms;--b:0.213"></i>
<i class="" style="--d:2839ms;--b:0.256"></i>
<i class="" style="--d:799ms;--b:0.243"></i>
<i class="warm" style="--d:1188ms;--b:0.359"></i>
<i class="" style="--d:1338ms;--b:0.168"></i>
<i class="" style="--d:1486ms;--b:0.186"></i>
<i class="" style="--d:1571ms;--b:0.197"></i>
<i class="warm" style="--d:1629ms;--b:0.380"></i>
<i class="" style="--d:1684ms;--b:0.170"></i>
<i class="" style="--d:1727ms;--b:0.144"></i>
<i class="" style="--d:1767ms;--b:0.140"></i>
<i class="" style="--d:1791ms;--b:0.150"></i>
<i class="" style="--d:1860ms;--b:0.227"></i>
<i class="" style="--d:1890ms;--b:0.274"></i>
<i class="" style="--d:1948ms;--b:0.257"></i>
<i class="warm" style="--d:2039ms;--b:0.288"></i>
<i class="hit" style="--d:2124ms;--b:0.260"></i>
<i class="hit" style="--d:2243ms;--b:0.385"></i>
<i class="warm" style="--d:2454ms;--b:0.356"></i>
<i class="" style="--d:2869ms;--b:0.216"></i>
<i class="" style="--d:832ms;--b:0.168"></i>
<i class="warm" style="--d:1204ms;--b:0.373"></i>
<i class="" style="--d:1383ms;--b:0.248"></i>
<i class="" style="--d:1495ms;--b:0.210"></i>
<i class="" style="--d:1583ms;--b:0.136"></i>
<i class="warm" style="--d:1648ms;--b:0.390"></i>
<i class="" style="--d:1728ms;--b:0.230"></i>
<i class="" style="--d:1756ms;--b:0.241"></i>
<i class="" style="--d:1810ms;--b:0.201"></i>
<i class="" style="--d:1836ms;--b:0.149"></i>
<i class="" style="--d:1870ms;--b:0.140"></i>
<i class="" style="--d:1927ms;--b:0.165"></i>
<i class="" style="--d:1995ms;--b:0.179"></i>
<i class="" style="--d:2051ms;--b:0.272"></i>
<i class="" style="--d:2137ms;--b:0.274"></i>
<i class="warm" style="--d:2310ms;--b:0.251"></i>
<i class="hit" style="--d:2493ms;--b:0.346"></i>
<i class="warm" style="--d:2902ms;--b:0.275"></i>
</div>
<div class="sweep"><div class="band"></div></div>
</div>
</div>
<div class="foot">
<span>key position</span>
<span class="tally"><em></em>20 of 180 held</span>
</div>
</div>
</body>
</html>