/* The rig: one terminal session split into tmux-style panes. Ground, ink and one accent (green = the rig is talking);
   red and amber only ever mean "the data looks bad" and "worth a look". */
:root {
  --bg: #060908; --pane: #080c0b; --line: #16201c; --line2: #22302a;
  --ink: #cfd9d4; --hi: #eef5f1; --dim: #62716b; --mute: #39453f;
  --green: #3dffa0; --green2: #1d8f5a; --amber: #ffbd52; --red: #ff4d63; --blue: #7cc8ff;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --fs: 12.5px;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body { margin: 0; background: var(--bg); color: var(--ink); font: var(--fs)/1.45 var(--mono); }
body { overflow-x: hidden; }
a { color: var(--green); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font: inherit; color: var(--ink); background: transparent; border: 1px solid var(--line2); padding: 3px 10px; cursor: pointer; }
button:hover:not(:disabled) { border-color: var(--green2); color: var(--hi); }
button:disabled { opacity: .45; cursor: default; }
button.go { border-color: var(--green2); color: var(--green); }
button.link { border: 0; padding: 0; color: var(--green); }
button:focus-visible, input:focus-visible, a:focus-visible { outline: 1px solid var(--green); outline-offset: 2px; }
input { font: inherit; color: var(--hi); background: transparent; border: 0; outline: 0; min-width: 0; }
.dim { color: var(--dim); } .red { color: var(--red); } .small { font-size: 11px; }
.skip { position: absolute; left: -999px; } .skip:focus { left: 8px; top: 8px; z-index: 9; background: var(--bg); padding: 4px 8px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
[hidden] { display: none !important; }

.app { height: 100dvh; display: flex; flex-direction: column; gap: 4px; padding: 4px; }
.app > * { flex: none; }
.app > .grid { flex: 1 1 auto; }

/* ---------- status line ---------- */
.top { display: flex; align-items: center; gap: 14px; height: 30px; padding: 0 10px; background: var(--green2); color: #03140c; font-weight: 500; white-space: nowrap; overflow: hidden; }
.top .brand { color: #021008; font-weight: 700; }
.wins { display: flex; gap: 10px; }
.wins .on { background: #021008; color: var(--green); padding: 0 5px; }
.stats { display: flex; gap: 14px; margin-left: auto; overflow: hidden; }
.stats b { color: #021008; } .stats b.red { color: #5c0010; }
.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #5c0010; margin: 0 4px 1px 2px; vertical-align: middle; }
.dot.on { background: #021008; box-shadow: 0 0 0 2px rgba(2, 16, 8, .25); }
.pill { padding: 0 7px; border: 1px solid #021008; font-weight: 700; letter-spacing: .04em; }
.pill.live { background: #021008; color: var(--green); }
.pill.demo { background: var(--amber); color: #1a1000; border-color: var(--amber); }
.icon { border: 0; padding: 2px; color: #021008; display: grid; place-items: center; }
.icon .x { display: none; } .icon.off .x { display: inline; } .icon.off .w { display: none; }

.banner { border: 1px solid var(--amber); color: var(--amber); padding: 4px 10px; }
.banner.bad { border-color: var(--red); color: var(--red); }

/* ---------- breach prompt ---------- */
.search { display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 4px 0 10px; border: 1px solid var(--line); background: var(--pane); }
.search label { color: var(--ink); white-space: nowrap; }
.search label .p { color: var(--green); }
.search input { flex: 1; height: 30px; }
.search input::placeholder { color: var(--mute); }
.search .msg { color: var(--dim); max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg.err { color: var(--red); } .msg.ok { color: var(--green); }
.search.busy input { color: var(--dim); }
.viewing { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 8px; border: 1px solid var(--green2); }
.viewing .vt { margin-right: auto; color: var(--green); }

/* ---------- panes ---------- */
.grid { display: grid; grid-template-columns: 1.25fr .8fr .8fr .95fr; grid-template-rows: minmax(0, 1.3fr) minmax(0, .7fr); gap: 4px; min-height: 0; }
.pane { position: relative; border: 1px solid var(--line); background: var(--pane); min-height: 0; min-width: 0; overflow: hidden; display: flex; flex-direction: column; }
.ph { display: flex; gap: 8px; align-items: baseline; padding: 3px 8px; border-bottom: 1px solid var(--line); color: var(--dim); white-space: nowrap; overflow: hidden; flex: none; }
.ph > span { color: var(--green); }
.ph i { font-style: normal; color: var(--mute); overflow: hidden; text-overflow: ellipsis; }
.ph em { font-style: normal; margin-left: auto; color: var(--dim); }
.stage { grid-column: 1; grid-row: 1 / span 2; }
.vis { grid-column: 2 / span 3; grid-row: 1; }
.hex { grid-column: 2; grid-row: 2; }
.jev { grid-column: 3; grid-row: 2; }
.intr { grid-column: 4; grid-row: 2; }
canvas#tty, canvas#net { flex: 1; width: 100%; min-height: 0; display: block; }

.inset { position: absolute; left: 10px; top: 32px; display: flex; gap: 10px; align-items: flex-start; pointer-events: none; }
#dither { width: 72px; height: 72px; image-rendering: pixelated; border: 1px solid var(--line2); }
.imeta { display: flex; flex-direction: column; }
.imeta b { color: var(--hi); font-size: 16px; }
.imeta span { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flags { position: absolute; left: 10px; bottom: 10px; display: flex; gap: 6px; flex-wrap: wrap; max-width: 55%; }
.flags i { font-style: normal; border: 1px solid var(--red); color: var(--red); padding: 0 6px; }
.flags i.ok { border-color: var(--green2); color: var(--green); }
.flags i.warn { border-color: var(--amber); color: var(--amber); }
.stamp { position: absolute; right: 14px; bottom: 14px; border: 3px solid var(--red); color: var(--red); padding: 6px 14px 8px; transform: rotate(-4deg); background: rgba(6, 9, 8, .82); display: flex; flex-direction: column; min-width: 200px; }
.stamp small { color: inherit; opacity: .8; letter-spacing: .1em; }
.stamp b { font-size: 26px; letter-spacing: .04em; line-height: 1.1; }
.stamp span { font-size: 11px; }
.stamp.clean { border-color: var(--green); color: var(--green); }
.stamp.warn { border-color: var(--amber); color: var(--amber); }   /* a caution: sniped */
.stamp.in { animation: stamp .32s cubic-bezier(.2, 1.6, .4, 1) both; }
@keyframes stamp { from { transform: rotate(-4deg) scale(1.6); opacity: 0; } to { transform: rotate(-4deg) scale(1); opacity: 1; } }

pre { margin: 0; font: inherit; }
.dump, .bars { padding: 6px 8px; overflow: hidden; flex: 1; font-size: 11.5px; line-height: 1.4; white-space: pre; }
.dump .l { color: var(--green); } .dump .o { color: var(--mute); } .dump .h { color: var(--ink); } .dump .a { color: var(--dim); }
.bars .m { color: var(--mute); } .bars .g { color: var(--green); } .bars .r { color: var(--red); } .bars .a { color: var(--amber); } .bars .w { color: var(--hi); } .bars .d { color: var(--dim); }

.trace { padding: 6px 8px; overflow: hidden; flex: 1; font-size: 11.5px; }
.trace .idle { color: var(--dim); margin: 0; }
.ln { white-space: pre; overflow: hidden; text-overflow: ellipsis; }
.ln .p, .ln .g { color: var(--green); } .ln .w { color: var(--hi); } .ln .a { color: var(--amber); } .ln .r { color: var(--red); } .ln .d, .ln .m { color: var(--dim); }
.intr.alert, .vis.alert { animation: alert 1.2s ease-out; }
@keyframes alert { 0%, 30% { border-color: var(--amber); } 100% { border-color: var(--line); } }
.sheet { position: absolute; left: 0; right: 0; bottom: 0; background: rgba(6, 9, 8, .94); border-top: 1px solid var(--amber); padding: 6px 8px; font-size: 11.5px; }

.botnet .nodes { display: flex; flex-wrap: wrap; gap: 2px; padding: 5px 8px; max-height: 58px; overflow: hidden; line-height: 1; }
.nodes i { font-style: normal; width: 9px; height: 9px; background: var(--line2); }
.nodes i.on { background: var(--green2); } .nodes i.on.l3 { background: #2fc47c; } .nodes i.on.l4 { background: var(--green); } .nodes i.on.l5 { background: var(--hi); }
.nodes i.new { outline: 2px solid var(--amber); }
.nodes .empty { color: var(--dim); }

.cabar { display: flex; align-items: center; gap: 10px; padding: 4px 10px; border: 1px solid var(--line); background: var(--pane); }
.calabel { color: var(--green); font-weight: 700; }
.cabar code { color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; font: inherit; }
.cabar .mc b { color: var(--hi); }
.buy { border: 1px solid var(--green2); color: var(--green); padding: 3px 14px; }
.buy.off { opacity: .45; pointer-events: none; }

/* ---------- below the fold ---------- */
.below { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; padding: 0 4px 24px; }
.big { min-height: 260px; }
.how { grid-column: 1 / -1; }
.feed, .wanted, .tally { list-style: none; margin: 0; padding: 6px 8px; overflow: auto; max-height: 340px; }
.feed li { display: flex; gap: 10px; padding: 1px 0; white-space: nowrap; overflow: hidden; }
.feed li[data-mint], .wanted li { cursor: pointer; }
.feed li[data-mint]:hover, .wanted li:hover { background: #0d1311; }
.feed time { color: var(--mute); flex: none; }
.feed span { overflow: hidden; text-overflow: ellipsis; }
.v-ok { color: var(--green); } .v-bad { color: var(--red); } .v-am { color: var(--amber); }
.feed .empty, .wanted .empty, .tally .empty { color: var(--dim); }
.wanted li { display: grid; grid-template-columns: 90px 110px 1fr; gap: 10px; padding: 2px 0; }
.wanted b { color: var(--hi); overflow: hidden; text-overflow: ellipsis; } .wanted .v { color: var(--red); }

.score { padding: 8px; display: flex; flex-direction: column; gap: 10px; overflow: auto; }
.score .hz { display: grid; grid-template-columns: 52px 1fr; gap: 4px 10px; align-items: baseline; }
.score .hz b { color: var(--green); }
.score .row { white-space: pre; overflow: hidden; text-overflow: ellipsis; }
.score .row .r { color: var(--red); } .score .row .g { color: var(--green); } .score .row .m { color: var(--mute); } .score .row .w { color: var(--hi); }
.score .recent { list-style: none; margin: 0; padding: 0; }
.score .recent li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.vote { padding: 8px; display: flex; flex-direction: column; gap: 8px; }
.vrow { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.vform { display: flex; gap: 8px; border: 1px solid var(--line); padding: 3px 3px 3px 8px; }
.vform input { flex: 1; }
.vote .msg { margin: 0; min-height: 1.4em; color: var(--dim); }
.tally { padding: 0; max-height: 160px; }
.tally li { display: grid; grid-template-columns: 24px 1fr auto auto; gap: 10px; }
.tally li b { color: var(--hi); }
.tally li.empty { display: block; }
.vote p { margin: 0; }

.how ol { margin: 0; padding: 8px 8px 0 28px; display: flex; flex-direction: column; gap: 8px; max-width: 980px; }
.how b { color: var(--hi); font-weight: 500; }
.how p { margin: 8px; max-width: 980px; }
.sched { color: var(--amber); } .fine { color: var(--dim); }

/* ---------- your coin ---------- */
.jump { white-space: nowrap; padding: 0 8px; border-left: 1px solid var(--line); }
.mine { grid-column: 1 / -1; min-height: 0; border-color: var(--green2); }
.mine .ph { color: var(--ink); }
.mineform { border: 0; border-bottom: 1px solid var(--line); }
.mine-msg { margin: 6px 10px 0; min-height: 1.4em; }
.mine-msg.working::after { content: '▌'; color: var(--green); animation: blink 1s steps(1) infinite; }
.mine-idle { padding: 0 10px 10px; max-width: 980px; }
.mine-idle p { margin: 6px 0; }
.mine-idle b { color: var(--hi); font-weight: 500; }
.mine-hot { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.mine-hot:empty { display: none; }
.mine-body { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 12px; padding: 4px 10px 10px; }
.mine .ok { color: var(--green); } .mine .bad { color: var(--red); } .mine .warn { color: var(--amber); } .mine .k { color: var(--hi); } .mine .dim { color: var(--dim); }
.mine-report { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.mr-head { display: flex; gap: 12px; align-items: center; }
.mr-head img { width: 56px; height: 56px; object-fit: cover; border: 1px solid var(--line2); background: #050706; flex: none; }
.mr-id { display: flex; flex-direction: column; min-width: 0; }
.mr-id b { color: var(--hi); font-size: 20px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mr-id span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mr-stamp { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: center; border: 3px solid var(--red); color: var(--red); padding: 4px 12px 6px; transform: rotate(-4deg); }
.mr-stamp.clean { border-color: var(--green); color: var(--green); }
.mr-stamp.warn { border-color: var(--amber); color: var(--amber); }
.mr-stamp small { letter-spacing: .1em; opacity: .8; font-size: 10px; } .mr-stamp b { font-size: 20px; line-height: 1.15; } .mr-stamp span { font-size: 11px; }
.mr-stamp.in { animation: stamp .32s cubic-bezier(.2, 1.6, .4, 1) both; }
.mr-sub { margin: 0; color: var(--dim); }
.mr-steps { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 5px 12px; margin: 0; }
.mr-steps dt { color: var(--dim); } .mr-steps dd { margin: 0; overflow-wrap: anywhere; }
.mr-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.btn { border: 1px solid var(--line2); padding: 3px 10px; color: var(--ink); }
.btn:hover { border-color: var(--green2); color: var(--hi); text-decoration: none; }
.mine-live { display: flex; flex-direction: column; min-width: 0; border-left: 1px solid var(--line); padding-left: 12px; }
.mine-stats { display: flex; flex-wrap: wrap; gap: 4px 14px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.mine-stats b { font-weight: 500; color: var(--hi); }
.mine-stats b.ok { color: var(--green); } .mine-stats b.bad { color: var(--red); }
.mine-sub { color: var(--mute); margin-top: 8px; text-transform: lowercase; }
.mine .feed { padding: 2px 0; }
.mine-alerts { max-height: 132px; } .mine-trades { max-height: 300px; }
.mine.alert { animation: alert 1.2s ease-out; }

/* ---------- a dev's dossier ---------- */
.devpage .app.dev { height: auto; min-height: 100dvh; }
.dev .back { color: #021008; font-weight: 700; }
.dev .cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; }
.dev .cols .pane { min-height: 220px; }
.dev .feed { max-height: 62vh; }
.dossier { padding: 8px; white-space: pre-wrap; word-break: break-all; }
.dev .fine { color: var(--dim); margin: 4px 8px; }

/* ---------- phones ---------- */
@media (max-width: 820px) {
  .app { height: auto; min-height: 100dvh; padding: 3px 3px 60px; gap: 3px; }
  .top { gap: 8px; font-size: 11px; }
  .top .hm, .wins { display: none; }
  .grid { display: flex; flex-direction: column; gap: 3px; }
  .vis { order: 1; height: 40vh; min-height: 270px; max-height: 380px; }
  .stage { order: 2; height: 52vh; min-height: 340px; max-height: 500px; }
  .intr { order: 3; } .intr .trace { min-height: 150px; }
  .hex, .jev { display: none; }
  #dither { width: 52px; height: 52px; }
  .flags { display: none; }
  .stamp { right: 6px; bottom: 6px; min-width: 0; padding: 3px 10px; }
  .stamp small, .stamp span { display: none; }
  .stamp b { font-size: 16px; }
  .search { height: auto; min-height: 44px; flex-wrap: wrap; }
  .search label .p { display: none; }
  .search input { font-size: 16px; height: 40px; }
  .search .msg { order: 3; flex-basis: 100%; max-width: none; padding-bottom: 6px; }
  .search .msg:empty { display: none; }
  .cabar { position: fixed; left: 3px; right: 3px; bottom: 3px; z-index: 5; }
  .below { grid-template-columns: 1fr; padding: 0 3px 70px; }
  .wanted li { grid-template-columns: 80px 1fr; } .wanted li span:last-child { grid-column: 1 / -1; color: var(--dim); }
  .dev .cols { grid-template-columns: 1fr; }
  .jump { display: none; }
  .mine-body { grid-template-columns: 1fr; }
  .mine-live { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 8px; }
  .mr-steps { grid-template-columns: 72px minmax(0, 1fr); }
}

/* ---------- stream mode (?stream): for a 24/7 broadcast, no inputs ---------- */
body.stream { --fs: 14px; }
body.stream .search, body.stream .below, body.stream .cabar, body.stream .skip, body.stream .viewing { display: none; }

/* ---------- motion: everything that moves means something arrived or changed ---------- */
/* the boot log, then the panes power on like a CRT one after another */
.boot { position: fixed; inset: 0; z-index: 60; background: var(--bg); display: flex; align-items: center; justify-content: center; padding: 24px; animation: bootFallback 0s 6s forwards; }
.boot pre { width: min(760px, 100%); color: var(--ink); font-size: 13px; line-height: 1.7; white-space: pre-wrap; text-shadow: 0 0 8px rgba(61, 255, 160, .25); }
.boot b { color: var(--green); font-weight: 500; }
.boot .ok { color: var(--green); } .boot .go { color: var(--amber); }
.boot .cur { font-style: normal; color: var(--green); animation: blink 1s steps(1) infinite; }
.boot.done { animation: bootOut .42s cubic-bezier(.6, 0, .4, 1) forwards; }
@keyframes bootOut { 0% { opacity: 1; transform: none; } 55% { opacity: 1; transform: scaleY(.006) scaleX(.9); } 100% { opacity: 0; transform: scaleY(.002) scaleX(0); } }
@keyframes bootFallback { to { opacity: 0; visibility: hidden; } }   /* if the script never runs */
/* `on` is only on <body> while the panes power on, so later effects on a pane never replay this */
body.on .top, body.on .search, body.on .grid > .pane, body.on .botnet, body.on .cabar {
  animation: power .5s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(var(--d, 0) * 70ms);
}
.banner, .viewing { animation: power .45s cubic-bezier(.2, .8, .2, 1) both; }   /* each time one appears */
@keyframes power { 0% { opacity: 0; transform: scaleY(.02); filter: brightness(3); } 55% { opacity: 1; transform: scaleY(1.015); filter: brightness(1.6); } 100% { opacity: 1; transform: none; filter: none; } }
@keyframes blink { 50% { opacity: 0; } }

/* the tube: scanlines, a slow refresh band, a faint flicker. Pointer-events off, transform/opacity only */
.crt { position: fixed; inset: 0; z-index: 70; pointer-events: none; overflow: hidden;
  background: repeating-linear-gradient(to bottom, transparent 0 2px, rgba(0, 0, 0, .16) 2px 3px); animation: flicker 7s steps(1) infinite; }
.crt::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 22vh; background: linear-gradient(to bottom, transparent, rgba(61, 255, 160, .035), transparent); animation: roll 9s linear infinite; }
.crt::after { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse at center, transparent 62%, rgba(0, 0, 0, .38) 100%); }
@keyframes flicker { 0%, 100% { opacity: .9; } 31% { opacity: .82; } 32% { opacity: .95; } 77% { opacity: .86; } 78% { opacity: .92; } }
@keyframes roll { from { transform: translateY(-22vh); } to { transform: translateY(100vh); } }
.brand, .search label .p, .ph > span, .calabel { text-shadow: 0 0 8px rgba(61, 255, 160, .45); }
.top .brand { text-shadow: none; }

/* status line: numbers roll and bump, the feed dot beats, LIVE blinks like a recording light */
.stats b { display: inline-block; }
.stats b.bump { animation: bump .55s ease-out; }
#sFlag.bump { animation-name: bumpRed; }
@keyframes bump { 30% { transform: translateY(-3px) scale(1.18); } }
@keyframes bumpRed { 30% { transform: translateY(-3px) scale(1.25); color: #b3001b; } }
.dot.on { animation: beat 1.1s ease-in-out infinite; }
@keyframes beat { 50% { transform: scale(1.6); opacity: .55; } }
.pill.live::before { content: '●'; margin-right: 5px; animation: blink 1.6s steps(1) infinite; }

/* a new breach: the pane headers flash; priority/voted/wanted breaches flash amber */
.ph.hit { animation: hit .9s ease-out; }
.ph.hit.amber { animation-name: hitAmber; }
@keyframes hit { 0% { background: rgba(61, 255, 160, .28); color: var(--hi); } 100% { background: transparent; } }
@keyframes hitAmber { 0% { background: rgba(255, 189, 82, .3); color: var(--hi); } 100% { background: transparent; } }
/* a flagged verdict lands: the graph shakes; a high threat flashes the edges red */
.vis.shake { animation: shake .36s linear; }
@keyframes shake { 20% { transform: translate(-3px, 1px); } 40% { transform: translate(3px, -1px); } 60% { transform: translate(-2px, 0); } 80% { transform: translate(2px, 1px); } }
.alarm { position: fixed; inset: 0; z-index: 45; pointer-events: none; box-shadow: inset 0 0 140px rgba(255, 77, 99, .5); opacity: 0; }
.alarm.go { animation: alarm 1.2s ease-out; }
@keyframes alarm { 0% { opacity: 0; } 10% { opacity: 1; } 100% { opacity: 0; } }

/* scanners: one bar sweeping the hexdump, the botnet, and the trace window while a trace runs */
.hex::after, .botnet .nodes::after, .intr.scanning::after { content: ''; position: absolute; pointer-events: none; }
.hex::after { left: 0; right: 0; top: 0; height: 48px; background: linear-gradient(to bottom, transparent, rgba(61, 255, 160, .07), transparent); animation: scanY 3.4s linear infinite; }
.intr.scanning::after { left: 0; right: 0; top: 0; height: 60px; background: linear-gradient(to bottom, transparent, rgba(255, 189, 82, .1), transparent); animation: scanY 1.6s linear infinite; }
@keyframes scanY { from { transform: translateY(-60px); } to { transform: translateY(60vh); } }
.botnet .nodes { position: relative; }
.botnet .nodes::after { top: 0; bottom: 0; left: 0; width: 90px; background: linear-gradient(90deg, transparent, rgba(61, 255, 160, .12), transparent); animation: scanX 5s linear infinite; }
@keyframes scanX { from { transform: translateX(-90px); } to { transform: translateX(100vw); } }
.nodes i { transition: background-color .4s; }
.nodes i.new { animation: pop .7s cubic-bezier(.2, 1.6, .4, 1) both; }
.nodes i.drop { animation: drop 1s steps(2) both; }
.nodes.wave i.on { animation: wave .6s ease-out both; animation-delay: calc(var(--i, 0) * 5ms); }
@keyframes pop { 0% { transform: scale(0); } 60% { transform: scale(1.8); } 100% { transform: none; } }
@keyframes drop { 0%, 50% { background: var(--red); } 100% { background: var(--line2); } }
@keyframes wave { 50% { transform: scale(1.5); background: var(--hi); } }

/* rows that just arrived slide in with a flash: green for good news, red for bad */
.feed li.new, .wanted li.new, .tally li.new, .score .recent li.new { animation: rowIn .7s ease-out both; animation-delay: calc(var(--i, 0) * 45ms); }
.feed li.new.bad, .wanted li.new, .score .recent li.new.bad { animation-name: rowInBad; }
@keyframes rowIn { 0% { opacity: 0; transform: translateX(-12px); background: rgba(61, 255, 160, .2); } 40% { opacity: 1; transform: none; } 100% { background: transparent; } }
@keyframes rowInBad { 0% { opacity: 0; transform: translateX(-12px); background: rgba(255, 77, 99, .24); } 40% { opacity: 1; transform: none; } 100% { background: transparent; } }
.feed li:first-child time::before { content: '▸ '; color: var(--green); animation: blink 1s steps(1) infinite; }

/* scorecard bars grow from zero */
.sbar { display: inline-block; position: relative; width: 14ch; height: .78em; background: var(--line); vertical-align: -1px; overflow: hidden; }
.sbar i { position: absolute; inset: 0; background: currentColor; transform-origin: left; transform: scaleX(var(--p, 0)); animation: grow 1s cubic-bezier(.2, .8, .2, 1) both; }
.sbar.r { color: var(--red); } .sbar.a { color: var(--amber); } .sbar.g { color: var(--green); }
@keyframes grow { from { transform: scaleX(0); } }

/* below the fold: panes slide up the first time they scroll into view */
.js .below > .pane { opacity: 0; transform: translateY(18px); transition: opacity .6s ease-out, transform .6s cubic-bezier(.2, .8, .2, 1); }
.js .below > .pane.seen { opacity: 1; transform: none; }

/* motion levels, set on <html> by util.mjs and switched with the fx button. calm (the default when the system asks
   for less motion) keeps typing, decoding, growing and fading, and drops shaking, tearing, flicker, flashes and sweeps */
[data-motion="calm"] .crt, [data-motion="calm"] .vis.shake, [data-motion="calm"] .alarm.go, [data-motion="calm"] .dot.on,
[data-motion="calm"] .pill.live::before, [data-motion="calm"] .feed li:first-child time::before, [data-motion="calm"] .nodes.wave i.on,
[data-motion="calm"] .mine-msg.working::after { animation: none; }
[data-motion="calm"] .crt::before, [data-motion="calm"] .hex::after, [data-motion="calm"] .botnet .nodes::after, [data-motion="calm"] .intr.scanning::after { display: none; }
[data-motion="calm"] body.on .top, [data-motion="calm"] body.on .search, [data-motion="calm"] body.on .grid > .pane, [data-motion="calm"] body.on .botnet,
[data-motion="calm"] body.on .cabar, [data-motion="calm"] .banner, [data-motion="calm"] .viewing { animation-name: fadeIn; }
[data-motion="calm"] .boot.done { animation-name: fadeOut; }
@keyframes fadeIn { from { opacity: 0; } }
@keyframes fadeOut { to { opacity: 0; } }
[data-motion="off"] *, [data-motion="off"] *::before, [data-motion="off"] *::after { animation: none !important; transition: none !important; }
[data-motion="off"] .boot, [data-motion="off"] .crt::before { display: none; }
[data-motion="off"].js .below > .pane { opacity: 1; transform: none; }
.icon.fx { border: 1px solid #021008; padding: 0 5px; font-weight: 700; font-size: 11px; }
