The "TAP IS ON · since …" line (and its SWITCHING / NOT SWITCHED forms, and
the red error line under the destination) are gone from the tile. A tile
shows the keyword Tap is on, its destination, the groups moved, the slide
chip and the trail; status is the corner dot's job, as everywhere else in
ProdDash.
The dot now follows the retries honestly: a switch Overflow refuses is
retried three times, ten seconds apart, with the dot amber ("retrying (n of
4 attempts failed)") while the module is still fixing it itself; only when
the attempts are spent does the dot go red with the reason on hover, and the
alert fire if it is switched on. The budget counts refusals in a row across
keywords, not per keyword — a service keeps bringing new keywords, and each
one restarting a fresh budget meant a dead Overflow never turned the dot
red. The alert is raised once per outage, and a success clears the streak.
Verified against the mock with --fail-switch: amber through three refusals,
red on the fourth with one alert, later refusals stay red without
re-alerting, and green again on the first success once the mock is back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
187 lines
5.8 KiB
CSS
187 lines
5.8 KiB
CSS
/* Overflow Tap — scoped under its tile via [data-module="overflow-tap"] and
|
||
styled with the shell's variables only. Sizes hang off the tile (container
|
||
units) so the keyword reads from across a booth on a big tile and still
|
||
fits a 2×2. */
|
||
|
||
[data-module="overflow-tap"] {
|
||
container-type: size;
|
||
}
|
||
|
||
[data-module="overflow-tap"] .ot-root {
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
padding: clamp(4px, 4cqmin, 18px);
|
||
gap: clamp(2px, 1.8cqmin, 10px);
|
||
overflow: hidden;
|
||
color: var(--text);
|
||
user-select: none;
|
||
-webkit-user-select: none;
|
||
}
|
||
|
||
[data-module="overflow-tap"] .ot-offline {
|
||
flex-shrink: 0;
|
||
font-size: clamp(0.6rem, 4.6cqmin, 0.9rem);
|
||
font-weight: 700;
|
||
color: var(--danger);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.04em;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
[data-module="overflow-tap"] .ot-root.is-offline .ot-main,
|
||
[data-module="overflow-tap"] .ot-root.is-offline .ot-slide,
|
||
[data-module="overflow-tap"] .ot-root.is-offline .ot-history {
|
||
opacity: 0.45;
|
||
filter: grayscale(0.6);
|
||
}
|
||
|
||
/* ── the live keyword ───────────────────────────────────────────── */
|
||
|
||
[data-module="overflow-tap"] .ot-main {
|
||
--tone: var(--accent);
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
container-type: size;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0;
|
||
text-align: center;
|
||
overflow: hidden;
|
||
}
|
||
[data-module="overflow-tap"] .ot-main[data-tone="ok"] { --tone: var(--accent); }
|
||
[data-module="overflow-tap"] .ot-main[data-tone="warn"] { --tone: var(--warn); }
|
||
[data-module="overflow-tap"] .ot-main[data-tone="alert"] { --tone: var(--danger); }
|
||
[data-module="overflow-tap"] .ot-main[data-tone="muted"] { --tone: var(--muted); }
|
||
|
||
[data-module="overflow-tap"] .ot-keyword {
|
||
color: var(--tone);
|
||
font-size: min(clamp(1rem, 44cqh, 7rem), 18cqw);
|
||
font-weight: 750;
|
||
line-height: 1.15;
|
||
max-width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
[data-module="overflow-tap"] .ot-keyword.is-none { color: var(--muted); }
|
||
[data-module="overflow-tap"] .ot-main[data-tone="muted"] .ot-keyword {
|
||
animation: ot-pulse 1.2s ease-in-out infinite;
|
||
}
|
||
@keyframes ot-pulse {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.45; }
|
||
}
|
||
|
||
[data-module="overflow-tap"] .ot-dest {
|
||
color: var(--text);
|
||
font-size: min(clamp(0.7rem, 16cqh, 1.9rem), 8cqw);
|
||
font-weight: 600;
|
||
line-height: 1.2;
|
||
max-width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
[data-module="overflow-tap"] .ot-main[data-tone="muted"] .ot-dest { color: var(--muted); font-weight: 500; }
|
||
|
||
[data-module="overflow-tap"] .ot-groups {
|
||
color: var(--muted);
|
||
font-size: clamp(0.5rem, 9cqh, 0.95rem);
|
||
line-height: 1.3;
|
||
flex-shrink: 0;
|
||
max-width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* ── this slide ─────────────────────────────────────────────────── */
|
||
|
||
[data-module="overflow-tap"] .ot-slide {
|
||
flex-shrink: 0;
|
||
text-align: center;
|
||
font-size: clamp(0.55rem, 4.8cqmin, 0.95rem);
|
||
color: var(--text);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
padding: 0.25em 0.6em;
|
||
border-radius: 999px;
|
||
background: color-mix(in srgb, var(--text) 7%, transparent);
|
||
align-self: center;
|
||
max-width: 100%;
|
||
}
|
||
[data-module="overflow-tap"] .ot-slide.is-muted { color: var(--muted); }
|
||
[data-module="overflow-tap"] .ot-slide.is-hit {
|
||
color: var(--accent-text);
|
||
background: color-mix(in srgb, var(--accent) 80%, transparent);
|
||
font-weight: 650;
|
||
}
|
||
[data-module="overflow-tap"] .ot-slide.is-warn {
|
||
color: var(--warn);
|
||
background: color-mix(in srgb, var(--warn) 16%, transparent);
|
||
}
|
||
|
||
/* ── the trail ──────────────────────────────────────────────────── */
|
||
|
||
[data-module="overflow-tap"] .ot-history {
|
||
flex-shrink: 0;
|
||
list-style: none;
|
||
margin: 0;
|
||
padding: 0.3em 0 0;
|
||
border-top: 1px solid var(--border);
|
||
font-size: clamp(0.55rem, 4.6cqmin, 0.95rem);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.1em;
|
||
}
|
||
|
||
[data-module="overflow-tap"] .ot-h-row {
|
||
display: grid;
|
||
grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.4fr) auto;
|
||
align-items: baseline;
|
||
gap: 0 0.7em;
|
||
color: var(--text);
|
||
}
|
||
[data-module="overflow-tap"] .ot-h-row.is-failed .ot-h-kw,
|
||
[data-module="overflow-tap"] .ot-h-row.is-failed .ot-h-mark { color: var(--danger); }
|
||
[data-module="overflow-tap"] .ot-h-time {
|
||
color: var(--muted);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
[data-module="overflow-tap"] .ot-h-kw { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
[data-module="overflow-tap"] .ot-h-dest { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
[data-module="overflow-tap"] .ot-h-mark { color: var(--accent); font-weight: 700; }
|
||
[data-module="overflow-tap"] .ot-h-empty { color: var(--muted); text-align: center; }
|
||
|
||
/* On a short tile the trail would crowd the keyword out: keep the
|
||
keyword, drop the trail. Inside the keyword block the same rule: when
|
||
it is short, the small lines go before the keyword does. */
|
||
@container (max-height: 120px) {
|
||
[data-module="overflow-tap"] .ot-history { display: none; }
|
||
}
|
||
@container (max-height: 70px) {
|
||
[data-module="overflow-tap"] .ot-groups { display: none; }
|
||
}
|
||
@container (max-height: 46px) {
|
||
[data-module="overflow-tap"] .ot-dest { display: none; }
|
||
}
|
||
|
||
[data-module="overflow-tap"] .ot-empty {
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 6%;
|
||
color: var(--muted);
|
||
text-align: center;
|
||
font-size: clamp(0.65rem, 5.5cqmin, 1rem);
|
||
}
|