An agent inbox: the bell rings and its badge counts up as three agents stop to ask for you, each ask dropping onto a stacked deck while the summary updates to 3 agents need you. A @property clock.
Also known as: agents need you notification, notification bell badge animation, agent questions inbox.
<div class="aia-agent-inbox-badge" role="status" aria-label="3 agents need your input">
<div class="aia-agent-inbox-badge-head">
<span class="aia-agent-inbox-badge-bell" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8.5a6 6 0 0 1 12 0c0 6.5 2.8 8.5 2.8 8.5H3.2S6 15 6 8.5"/><path d="M10.2 20.5a2 2 0 0 0 3.6 0"/></svg><b class="aia-agent-inbox-badge-count"></b></span>
<span class="aia-agent-inbox-badge-title">
<b>Inbox</b>
<span class="aia-agent-inbox-badge-sum" aria-hidden="true"><span>All caught up</span><span>1 agent needs you</span><span class="aia-agent-inbox-badge-many"></span></span>
</span>
</div>
<ul class="aia-agent-inbox-badge-stack">
<li><span class="aia-agent-inbox-badge-av" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 7 4.5 5L5 17M12 17.5h7"/></svg></span><span class="aia-agent-inbox-badge-ask"><b>deploy-bot</b><span>Ship v2.4.0 to production?</span></span><i>2m</i></li>
<li><span class="aia-agent-inbox-badge-av" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="12" cy="5.5" rx="7.5" ry="2.8"/><path d="M4.5 5.5v13c0 1.5 3.4 2.8 7.5 2.8s7.5-1.3 7.5-2.8v-13"/><path d="M4.5 12c0 1.5 3.4 2.8 7.5 2.8s7.5-1.3 7.5-2.8"/></svg></span><span class="aia-agent-inbox-badge-ask"><b>migrate-db</b><span>Drop the legacy_email column?</span></span><i>1m</i></li>
<li><span class="aia-agent-inbox-badge-av" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg></span><span class="aia-agent-inbox-badge-ask"><b>docs-sync</b><span>Overwrite README.md?</span></span><i>now</i></li>
</ul>
</div>@property --aia-agent-inbox-badge-t {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --aia-agent-inbox-badge-n {
syntax: "<integer>";
inherits: false;
initial-value: 0;
}
.aia-agent-inbox-badge {
--c: var(--aia-color, #7c5cff);
font-size: var(--aia-size, 16px);
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.4;
position: relative;
box-sizing: border-box;
padding: 0.9em 1em;
border-radius: 0.9em;
background: color-mix(in srgb, currentColor 3%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 11%, transparent), 0 0.1em 0.2em color-mix(in srgb, currentColor 4%, transparent), 0 0.9em 2em -1.1em rgb(0 0 0 / 0.3);
--d: 9s;
--t: var(--aia-agent-inbox-badge-t);
--red: color-mix(in srgb, #dc2626 92%, #fff);
width: 20em;
padding: 0.8em 0.85em 0.75em;
animation: aia-agent-inbox-badge-clock var(--d) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.aia-agent-inbox-badge-head {
display: flex;
align-items: center;
gap: 0.65em;
margin-bottom: 0.7em;
}
.aia-agent-inbox-badge-bell {
position: relative;
display: grid;
place-items: center;
width: 2.2em;
height: 2.2em;
border-radius: 50%;
background: color-mix(in srgb, currentColor 6%, transparent);
}
.aia-agent-inbox-badge-bell svg {
width: 1.15em;
height: 1.15em;
transform-origin: 50% 10%;
animation: aia-agent-inbox-badge-ring var(--d) ease-in-out infinite;
}
.aia-agent-inbox-badge-count {
position: absolute;
top: -0.35em;
right: -0.45em;
box-sizing: border-box;
min-width: 1.75em;
height: 1.75em;
padding: 0 0.4em;
border-radius: 999em;
background: var(--red);
color: #fff;
font: 700 0.64em / 1.75em system-ui, sans-serif;
text-align: center;
--aia-agent-inbox-badge-n: calc(var(--t));
counter-reset: n var(--aia-agent-inbox-badge-n);
animation: aia-agent-inbox-badge-pop var(--d) cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}
.aia-agent-inbox-badge-count::before { content: counter(n); }
.aia-agent-inbox-badge-title {
display: grid;
line-height: 1.3;
}
.aia-agent-inbox-badge-title b { font-size: 0.9em; }
.aia-agent-inbox-badge-sum {
display: grid;
color: color-mix(in srgb, currentColor 55%, transparent);
font-size: 0.74em;
animation: aia-agent-inbox-badge-fade var(--d) linear infinite;
}
.aia-agent-inbox-badge-sum > * {
grid-area: 1 / 1;
white-space: nowrap;
}
.aia-agent-inbox-badge-sum > :nth-child(1) { opacity: clamp(0, 1 - var(--t) * 3, 1); }
.aia-agent-inbox-badge-sum > :nth-child(2) { opacity: min(clamp(0, (var(--t) - 0.5) * 3, 1), clamp(0, (1.5 - var(--t)) * 3, 1)); }
.aia-agent-inbox-badge-many {
--aia-agent-inbox-badge-n: calc(var(--t));
counter-reset: n var(--aia-agent-inbox-badge-n);
opacity: clamp(0, (var(--t) - 1.5) * 3, 1);
}
.aia-agent-inbox-badge-many::before { content: counter(n) " agents need you"; }
.aia-agent-inbox-badge-stack {
position: relative;
height: 4.1em;
margin: 0;
padding: 0;
list-style: none;
animation: aia-agent-inbox-badge-fade var(--d) linear infinite;
}
.aia-agent-inbox-badge-stack::before {
content: "No agents waiting on you";
position: absolute;
left: 0;
right: 0;
top: 0;
display: grid;
place-items: center;
box-sizing: border-box;
border-radius: 0.9em;
border: 1px dashed color-mix(in srgb, currentColor 18%, transparent);
color: color-mix(in srgb, currentColor 40%, transparent);
font-size: 0.78em;
height: calc(3.1em / 0.78);
opacity: clamp(0, 1 - var(--t) * 2.5, 1);
}
.aia-agent-inbox-badge-stack li {
--k: 0;
--p: clamp(0, var(--t) - var(--k), 1);
--dp: clamp(0, var(--t) - var(--k) - 1, 2);
position: absolute;
left: 0;
right: 0;
top: 0;
display: grid;
grid-template-columns: 1.6em 1fr auto;
align-items: center;
gap: 0.6em;
box-sizing: border-box;
height: 3.1em;
padding: 0 0.7em;
border-radius: 0.7em;
background: color-mix(in srgb, currentColor 4%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 12%, transparent), 0 0.5em 1em -0.7em rgb(0 0 0 / 0.35);
transform-origin: 50% 100%;
transform: translateY(calc((1 - var(--p)) * -0.9em + var(--dp) * 0.5em)) scale(calc(1 - var(--dp) * 0.05));
opacity: calc(var(--p) * (1 - var(--dp) * 0.25));
clip-path: inset(calc(min(var(--dp), 1) * (100% - 0.62em)) 0 0 0 round 0.7em);
}
.aia-agent-inbox-badge-stack li:nth-child(2) { --k: 1; z-index: 1; }
.aia-agent-inbox-badge-stack li:nth-child(3) { --k: 2; z-index: 2; }
.aia-agent-inbox-badge-stack li > * {
opacity: calc(1 - clamp(0, var(--dp) * 4, 1));
}
.aia-agent-inbox-badge-av {
display: grid;
place-items: center;
width: 1.6em;
height: 1.6em;
border-radius: 0.45em;
background: color-mix(in srgb, var(--c) 15%, transparent);
color: var(--c);
}
.aia-agent-inbox-badge-av svg {
width: 0.95em;
height: 0.95em;
}
.aia-agent-inbox-badge-ask {
display: grid;
min-width: 0;
line-height: 1.3;
}
.aia-agent-inbox-badge-ask b {
font: 600 0.68em ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
color: color-mix(in srgb, currentColor 60%, transparent);
}
.aia-agent-inbox-badge-ask span {
overflow: hidden;
font-size: 0.8em;
font-weight: 500;
white-space: nowrap;
text-overflow: ellipsis;
}
.aia-agent-inbox-badge-stack i {
align-self: start;
margin-top: 0.75em;
color: color-mix(in srgb, currentColor 45%, transparent);
font: normal 0.64em ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
}
@keyframes aia-agent-inbox-badge-clock {
0%, 8% { --aia-agent-inbox-badge-t: 0; }
14%, 36% { --aia-agent-inbox-badge-t: 1; }
42%, 62% { --aia-agent-inbox-badge-t: 2; }
68%, 96% { --aia-agent-inbox-badge-t: 3; }
97%, 100% { --aia-agent-inbox-badge-t: 0; }
}
@keyframes aia-agent-inbox-badge-ring {
0%, 9%, 17%, 37%, 45%, 63%, 71%, 100% { transform: none; }
10%, 38%, 64% { transform: rotate(16deg); }
11.5%, 39.5%, 65.5% { transform: rotate(-14deg); }
13%, 41%, 67% { transform: rotate(9deg); }
14.5%, 42.5%, 68.5% { transform: rotate(-5deg); }
}
@keyframes aia-agent-inbox-badge-pop {
0%, 9% { opacity: 0; transform: scale(0); }
12% { opacity: 1; transform: scale(1.3); }
15%, 38% { transform: scale(1); }
40% { transform: scale(1.3); }
43%, 64% { transform: scale(1); }
66% { transform: scale(1.3); }
69%, 92% { opacity: 1; transform: scale(1); }
95%, 100% { opacity: 0; transform: scale(0); }
}
@keyframes aia-agent-inbox-badge-fade {
0%, 92% { opacity: 1; }
95%, 97.5% { opacity: 0; }
100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
.aia-agent-inbox-badge,
.aia-agent-inbox-badge-sum,
.aia-agent-inbox-badge-stack,
.aia-agent-inbox-badge-bell svg {
animation: none;
--aia-agent-inbox-badge-t: 3;
}
.aia-agent-inbox-badge-count {
animation-play-state: paused;
animation-delay: calc(var(--d) * -0.8);
}
}
@media (prefers-reduced-motion: reduce) {
.aia-agent-inbox-badge, .aia-agent-inbox-badge *, .aia-agent-inbox-badge::before, .aia-agent-inbox-badge::after, .aia-agent-inbox-badge *::before, .aia-agent-inbox-badge *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--aia-color on the element or a parent.
Currently previewing #3b82f6.--aia-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.