/* Illustrations for the home page and /use-cases/ (see graphics.js for the motion). All inline SVG, drawn in the same
   dark palette as the page. The finished state is the default, so everything reads with no JS and with reduced motion.
   Gradients only mark the live moments (a wire carrying a key, a seat in use); borders are always full, never one side. */

:root {
  --g-bad: #f08a8a;
  --g-ok-bg: rgba(52, 211, 153, 0.12);
  --g-ok-line: rgba(52, 211, 153, 0.5);
  --g-bad-bg: rgba(240, 138, 138, 0.12);
  --g-bad-line: rgba(240, 138, 138, 0.5);
  --g-panel: #0a0c11;
  --g-card: #12151c;
}

.gfx-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* a framed illustration at the top of a card */
.gfx-frame { margin: 0 0 1.35rem; aspect-ratio: 320 / 160; border: 1px solid var(--hair); border-radius: 12px; overflow: hidden;
  background: radial-gradient(110% 80% at 50% -10%, rgba(123, 108, 255, 0.13), transparent 62%), var(--g-panel); }
.card:hover .gfx-frame { border-color: var(--hair-strong); }
.gfx-frame svg, .gfx-banner svg { display: block; width: 100%; height: 100%; }
.gfx-wide svg { display: block; width: 100%; height: auto; }
.gfx-wide .gfx-mob { display: none; }

/* every animated element rotates and scales about its own centre */
.gfx [data-fx] { transform-box: fill-box; transform-origin: center; }
.gfx [data-ghost], .gfx [data-out] { opacity: 0; }

/* shared drawing language */
.gfx .gc { fill: var(--g-card); stroke: rgba(255, 255, 255, 0.14); stroke-width: 1; }
.gfx .gc-hi { fill: none; stroke: url(#gfx-brand); stroke-width: 1.4; }
.gfx .gc-dash { fill: none; stroke: rgba(255, 255, 255, 0.22); stroke-dasharray: 3 3; }
.gfx .gl { fill: none; stroke: rgba(255, 255, 255, 0.14); stroke-width: 1; stroke-linecap: round; }
.gfx .gw { fill: none; stroke: url(#gfx-brand); stroke-width: 1.6; stroke-linecap: round; }
.gfx .gk { font: 600 8px/1 var(--font); letter-spacing: 0.12em; fill: var(--text-3); }
.gfx .gm { font: 600 11.5px/1 var(--mono); letter-spacing: 0.01em; fill: var(--text); }
.gfx .gs { font: 500 9.5px/1 var(--font); fill: var(--text-3); }
.gfx .gsm { font: 500 8.5px/1 var(--mono); fill: var(--text-3); }
.gfx .gt { font: 560 10.5px/1 var(--font); fill: var(--text-2); }
.gfx .gb { font: 650 10.5px/1 var(--font); fill: var(--text); }
.gfx .gok { font: 650 9.5px/1 var(--font); fill: var(--ok); }
.gfx .gbad { font: 650 9.5px/1 var(--font); fill: var(--g-bad); }
.gfx .pill-ok { fill: var(--g-ok-bg); stroke: var(--g-ok-line); }
.gfx .pill-bad { fill: var(--g-bad-bg); stroke: var(--g-bad-line); }
.gfx .pill-n { fill: rgba(255, 255, 255, 0.04); stroke: rgba(255, 255, 255, 0.16); }
.gfx .ico { fill: none; stroke: var(--text-3); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.gfx .ico-ok { fill: none; stroke: var(--ok); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.gfx .ico-bad { fill: none; stroke: var(--g-bad); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.gfx .dot-ok { fill: var(--ok); }
.gfx .dot-w { fill: #fff; filter: none; }
.gfx .seg { fill: rgba(255, 255, 255, 0.09); }
.gfx .seg-on { fill: url(#gfx-brand); }
.gfx .cursor { fill: #f8f9fc; stroke: #08090c; stroke-width: 1; stroke-linejoin: round; }
.gfx .btn-o { fill: rgba(255, 255, 255, 0.03); stroke: rgba(255, 255, 255, 0.18); }
.gfx .btn-hi { fill: rgba(123, 108, 255, 0.28); stroke: url(#gfx-brand); }
.gfx .scan { fill: url(#gfx-scan); }

/* wide figures: stores to product, the use-case hub */
.gfx-wide { margin: 0 0 1.1rem; border: 1px solid var(--hair); border-radius: var(--radius); overflow: hidden;
  background: radial-gradient(90% 90% at 50% 0%, rgba(123, 108, 255, 0.12), transparent 65%), var(--g-panel); }

/* banner beside a use-case group heading */
.uc-head { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 25rem); gap: 1.6rem 3.5rem; align-items: center; }
.uc-head .lead { max-width: 34rem; }
.gfx-banner { aspect-ratio: 360 / 150; border: 1px solid var(--hair); border-radius: 14px; overflow: hidden;
  background: radial-gradient(100% 90% at 50% -10%, rgba(123, 108, 255, 0.12), transparent 62%), var(--g-panel); }

/* use-cases page head: copy left, hub right */
.page-head-grid { display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr); gap: 3rem 3.5rem; align-items: center; }
.page-head-grid .page-head-copy h1 { max-width: none; text-wrap: balance; }

/* a small line icon at the head of each use-case card */
.uc-top { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; margin-bottom: 1rem; }
.uc-top .uc-tags { margin-bottom: 0; }
.uc-ico { flex: none; display: grid; place-items: center; width: 2.6rem; height: 2.6rem; border: 1px solid var(--hair-strong); border-radius: 12px;
  background: linear-gradient(160deg, rgba(165, 152, 255, 0.12), rgba(79, 227, 200, 0.04) 70%), var(--surface-2);
  color: var(--accent-hi); transition: border-color 0.25s ease, color 0.25s ease, transform 0.25s ease; }
.uc-ico svg { width: 1.5rem; height: 1.5rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.card:hover .uc-ico { border-color: color-mix(in srgb, var(--accent) 55%, transparent); color: #fff; transform: translateY(-1px); }
/* the icon draws itself when its card arrives (only when reveals are on, so nothing is hidden without JS) */
.js-reveal .uc-ico svg * { stroke-dasharray: 1; stroke-dashoffset: 1; }
.js-reveal .reveal.in .uc-ico svg * { stroke-dashoffset: 0; transition: stroke-dashoffset 1.1s cubic-bezier(0.2, 0.7, 0.2, 1) 0.25s; }

/* the update notice slides in when it arrives */
.js-reveal .notice.reveal.in .notice-dot { animation: notice-pulse 2.6s ease-in-out 0.6s 3; }
@keyframes notice-pulse { 0%, 100% { box-shadow: 0 0 12px rgba(111, 168, 255, 0.9); } 50% { box-shadow: 0 0 22px 3px rgba(111, 168, 255, 0.9); } }

@media (max-width: 62rem) {
  .uc-head { grid-template-columns: 1fr; }
  .gfx-banner { max-width: 28rem; }
  .page-head-grid { grid-template-columns: 1fr; }
}
@media (max-width: 48rem) {

  .gfx-wide .gfx-desk { display: none; }
  .gfx-wide .gfx-mob { display: block; }
}
@media print { .gfx-wide, .gfx-banner { break-inside: avoid; } }

/* ---- scenes driven by CSS (hero lifecycle, feature tiles, use-case hub) ----
   Same rule as the rest of this file: the finished state is the default, so a scene reads with no JS, in print and with
   reduced motion. graphics.js adds .fx-on the first time a scene scrolls into view and .fx-paused while it is off screen. */
.fxs text { font-family: var(--font); }
.fxs .x-m { font-family: var(--mono); }
.fx-svg { display: block; width: 100%; height: auto; }

.fxs .x-revA { opacity: 1; }
.fxs .x-actA, .fxs .x-u, .fxs .x-sweep, .fxs .x-cursor, .fxs .x-pl, .fxs .x-ar { opacity: 0; }
.fxs .x-strikeA { stroke-dasharray: 1; stroke-dashoffset: 0; }
.fxs .x-d { stroke-dasharray: 1; stroke-dashoffset: 0; }
.fxs .x-halo { opacity: 0.8; }
.fxs [style*="x-pulse"], .fxs [style*="x-click"] { opacity: 0; }
.fxs [style*="x-dimk"] { opacity: 0.4; }
.fxs [style*="x-shiftup"] { transform: translateY(-44px); }
.fxs .x-pl { stroke-dasharray: 0.14 1; stroke-dashoffset: 0.14; }
.fxs .x-core { transform-box: fill-box; transform-origin: center; opacity: 0.85; }
.fxs .x-hl { transform-box: fill-box; transform-origin: center; }
.fxs .x-orbit { transform-origin: 390px 390px; }

.fxs.fx-on .x-progA { animation: x-prog 12s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.fxs.fx-on .x-st { opacity: 0.58; animation: x-lit 12s ease-in-out infinite; }
.fxs.fx-on .x-s1 { animation-delay: 2.4s; }
.fxs.fx-on .x-s2 { animation-delay: 4.8s; }
.fxs.fx-on .x-s3 { animation-delay: 7.2s; }
.fxs.fx-on .x-s4 { animation-delay: 9.6s; }
.fxs.fx-on .x-actA { opacity: 1; animation: x-kAct 12s linear infinite; }
.fxs.fx-on .x-revA { opacity: 0; animation: x-kRev 12s linear infinite; }
.fxs.fx-on .x-strikeA { stroke-dashoffset: 1; animation: x-kStrike 12s ease-in-out infinite; }
.fxs.fx-on .x-halo { animation: x-breathe 4.5s ease-in-out infinite; }

.fxs.fx-on .x-fade { animation: x-fade 8s linear infinite; }
.fxs.fx-on .x-r, .fxs.fx-on .x-d, .fxs.fx-on .x-u, .fxs.fx-on .x-k { animation-duration: 8s; animation-iteration-count: infinite; animation-fill-mode: both; animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }

.fxs.fx-on .x-radar { animation: x-spin 26s linear infinite; }
.fxs.fx-on .x-orbit { animation: x-spin 90s linear infinite; }
.fxs.fx-on .x-core { animation: x-corepulse 5s ease-in-out infinite; }
.fxs.fx-on .x-pl { animation: x-pulse 10s cubic-bezier(0.5, 0, 0.5, 1) infinite; }
.fxs.fx-on .x-ar { animation: x-arrive 10s ease-out infinite; }

.fxs.fx-paused, .fxs.fx-paused * { animation-play-state: paused !important; }
@media (prefers-reduced-motion: reduce) { .fxs, .fxs * { animation: none !important; } }

@keyframes x-prog{0%{stroke-dashoffset:1000;opacity:1}15%{stroke-dashoffset:1000}20%{stroke-dashoffset:750}35%{stroke-dashoffset:750}40%{stroke-dashoffset:500}55%{stroke-dashoffset:500}60%{stroke-dashoffset:250}75%{stroke-dashoffset:250}80%{stroke-dashoffset:0}94%{stroke-dashoffset:0;opacity:1}98%{stroke-dashoffset:0;opacity:0}100%{stroke-dashoffset:1000;opacity:0}}
@keyframes x-lit{0%{opacity:.58}2%{opacity:1}17%{opacity:1}22%{opacity:.58}100%{opacity:.58}}
@keyframes x-kAct{0%,83%{opacity:1}86%,100%{opacity:0}}
@keyframes x-kRev{0%,83%{opacity:0}86%,100%{opacity:1}}
@keyframes x-kStrike{0%,84%{stroke-dashoffset:1}92%,100%{stroke-dashoffset:0}}
@keyframes x-breathe{0%,100%{opacity:.55}50%{opacity:1}}
@keyframes x-fade{0%{opacity:0}3%{opacity:1}92%{opacity:1}98%,100%{opacity:0}}
@keyframes x-ra{0%,4%{opacity:0;transform:translateY(10px)}12%,100%{opacity:1;transform:none}}
@keyframes x-rb{0%,12%{opacity:0;transform:translateY(10px)}20%,100%{opacity:1;transform:none}}
@keyframes x-rc{0%,20%{opacity:0;transform:translateY(10px)}28%,100%{opacity:1;transform:none}}
@keyframes x-rd{0%,28%{opacity:0;transform:translateY(10px)}36%,100%{opacity:1;transform:none}}
@keyframes x-re{0%,36%{opacity:0;transform:translateY(10px)}44%,100%{opacity:1;transform:none}}
@keyframes x-rf{0%,44%{opacity:0;transform:translateY(10px)}52%,100%{opacity:1;transform:none}}
@keyframes x-rg{0%,52%{opacity:0;transform:translateY(10px)}60%,100%{opacity:1;transform:none}}
@keyframes x-rh{0%,60%{opacity:0;transform:translateY(10px)}68%,100%{opacity:1;transform:none}}
@keyframes x-da{0%,4%{stroke-dashoffset:1}16%,100%{stroke-dashoffset:0}}
@keyframes x-db{0%,12%{stroke-dashoffset:1}24%,100%{stroke-dashoffset:0}}
@keyframes x-dc{0%,20%{stroke-dashoffset:1}32%,100%{stroke-dashoffset:0}}
@keyframes x-dd{0%,28%{stroke-dashoffset:1}40%,100%{stroke-dashoffset:0}}
@keyframes x-de{0%,36%{stroke-dashoffset:1}48%,100%{stroke-dashoffset:0}}
@keyframes x-df{0%,44%{stroke-dashoffset:1}56%,100%{stroke-dashoffset:0}}
@keyframes x-dg{0%,52%{stroke-dashoffset:1}64%,100%{stroke-dashoffset:0}}
@keyframes x-ua{0%,4%{opacity:1}9%,100%{opacity:0}}
@keyframes x-ud{0%,28%{opacity:1}33%,100%{opacity:0}}
@keyframes x-ue{0%,36%{opacity:1}41%,100%{opacity:0}}
@keyframes x-uf{0%,44%{opacity:1}49%,100%{opacity:0}}
@keyframes x-ug{0%,52%{opacity:1}57%,100%{opacity:0}}
@keyframes x-uh{0%,60%{opacity:1}65%,100%{opacity:0}}
@keyframes x-pulse1{0%,20%{transform:translateX(0);opacity:0}22%{opacity:1}34%{transform:translateX(120px);opacity:1}36%,100%{transform:translateX(120px);opacity:0}}
@keyframes x-pulse2{0%,52%{transform:translateX(0);opacity:0}54%{opacity:1}64%{transform:translateX(50px);opacity:1}66%,100%{transform:translateX(50px);opacity:0}}
@keyframes x-dimk{0%,44%{opacity:1}52%,100%{opacity:.4}}
@keyframes x-scan{0%,18%{transform:translateX(0);opacity:0}22%{opacity:1}40%{transform:translateX(210px);opacity:1}44%,100%{transform:translateX(210px);opacity:0}}
@keyframes x-shake{0%,62%{transform:translateX(0)}65%{transform:translateX(-6px)}68%{transform:translateX(6px)}71%{transform:translateX(-4px)}74%,100%{transform:translateX(0)}}
@keyframes x-shiftup{0%,50%{transform:translateY(0)}60%,100%{transform:translateY(-44px)}}
@keyframes x-cur{0%,6%{transform:translate(380px,190px);opacity:0}10%{opacity:1}30%{transform:translate(206px,128px);opacity:1}38%{transform:translate(206px,128px)}58%{transform:translate(430px,128px);opacity:1}66%{transform:translate(430px,128px)}80%{transform:translate(500px,180px);opacity:1}86%,100%{transform:translate(500px,180px);opacity:0}}
@keyframes x-click1{0%,30%{opacity:0}34%{opacity:1}44%,100%{opacity:0}}
@keyframes x-click2{0%,58%{opacity:0}62%{opacity:1}72%,100%{opacity:0}}
@keyframes x-ring{0%,44%{stroke-dashoffset:1}58%,100%{stroke-dashoffset:0}}
@keyframes x-halo{0%,100%{opacity:.5}50%{opacity:1}}
@keyframes x-spin{to{transform:rotate(360deg)}}
@keyframes x-corepulse{0%,100%{transform:scale(1);opacity:.65}50%{transform:scale(1.14);opacity:1}}
@keyframes x-pulse{0%{stroke-dashoffset:.14;opacity:0}1.5%{opacity:1}11%{stroke-dashoffset:-1;opacity:1}12%,100%{stroke-dashoffset:-1;opacity:0}}
@keyframes x-arrive{0%,10%{opacity:0;transform:scale(.92)}13%{opacity:1;transform:scale(1)}28%{opacity:.0;transform:scale(1.06)}100%{opacity:0}}

/* hero: one centered column, the lifecycle underneath */
.hero::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; background-image: radial-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1.2px); background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 38%, #000, transparent); mask-image: radial-gradient(ellipse 70% 60% at 50% 38%, #000, transparent); }
.hero > .wrap { position: relative; z-index: 1; }
.hero-center { display: flex; flex-direction: column; align-items: center; text-align: center; }
.hero-center h1 { margin-top: 1.25rem; font-size: clamp(2.3rem, 5vw, 3.6rem); line-height: 1.05; letter-spacing: -0.04em; text-wrap: balance; }
.hero-center .lede { max-width: 42rem; margin-top: 1.15rem; font-size: clamp(1rem, 1.5vw, 1.1rem); }
.hero-center .actions { justify-content: center; margin-top: 1.7rem; }
.hero-center .fine { max-width: 38rem; }
@media (min-width: 48.01rem) { .hero { padding-top: 8rem; } }
/* the glow under the lifecycle panel lives in the hero background, so it fades out well inside the section and never meets a clipped edge */
.hero { background-image: radial-gradient(60% 30% at 50% 74%, rgba(123, 108, 255, 0.2), transparent 74%); }
.lifecycle { position: relative; max-width: 75rem; margin: 3.4rem auto 0; border: 1px solid transparent; border-radius: 28px; overflow: hidden;
  background: linear-gradient(180deg, rgba(20, 23, 31, 0.92), rgba(11, 13, 18, 0.92)) padding-box, linear-gradient(150deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.05) 38%, rgba(165, 152, 255, 0.32) 78%, rgba(79, 227, 200, 0.28)) border-box;
  box-shadow: 0 30px 60px -44px rgba(0, 0, 0, 0.7); }
.lifecycle::before { content: ""; position: absolute; inset: 0; background: radial-gradient(60% 80% at 50% 0%, rgba(123, 108, 255, 0.16), transparent 70%); pointer-events: none; }
.lifecycle svg { position: relative; }
.lifecycle .lc-mob { display: none; max-width: 21rem; margin-inline: auto; padding: 1.25rem 0.5rem 1.4rem; }

/* features: a bento of six tiles */
.bento { position: relative; isolation: isolate; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 1.25rem; }
/* one shared ambient glow behind the whole grid, so the tiles read as a set instead of six separate blooms */
.bento::before { content: ""; position: absolute; inset: -2.5rem 0; z-index: -1; pointer-events: none;
  background: radial-gradient(48% 55% at 22% 38%, rgba(123, 108, 255, 0.13), transparent 72%), radial-gradient(44% 50% at 80% 70%, rgba(79, 140, 255, 0.09), transparent 72%); }
.tile { position: relative; display: flex; flex-direction: column; overflow: hidden; border: 1px solid transparent; border-radius: 24px;
  background: linear-gradient(180deg, rgba(20, 23, 31, 0.95), rgba(11, 13, 18, 0.95)) padding-box, linear-gradient(150deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.05) 40%, rgba(165, 152, 255, 0.28) 80%, rgba(79, 227, 200, 0.22)) border-box;
  box-shadow: 0 30px 60px -44px rgba(0, 0, 0, 0.7); }
.tile::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 38%); pointer-events: none; }
.t-4 { grid-column: span 4; } .t-2 { grid-column: span 2; } .t-3 { grid-column: span 3; }
.tile-hd { position: relative; max-width: 32.5rem; padding: 1.75rem 1.9rem 0; }
.tile-lb { font: 600 0.7rem/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: #a598ff; }
.tile h3 { margin-top: 0.7rem; font: 650 1.5rem/1.2 var(--font); letter-spacing: -0.02em; text-wrap: balance; color: var(--text); }
.tile .tile-p { margin-top: 0.65rem; font-size: 0.92rem; line-height: 1.6; color: var(--text-3); }
.tile-scene { position: relative; margin-top: auto; padding: 1.7rem 1.9rem 1.8rem; }
.tile .tile-compact { display: none; position: relative; margin: 1.5rem 1.25rem 1.4rem; }

/* use cases: the hub */
.hub { position: relative; width: 100%; max-width: 40rem; aspect-ratio: 1; justify-self: center; }
.hub::before { content: ""; position: absolute; inset: -12%; background: radial-gradient(closest-side, rgba(123, 108, 255, 0.2), transparent), radial-gradient(closest-side at 70% 60%, rgba(79, 227, 200, 0.08), transparent); pointer-events: none; }
.hub .fx-svg { position: absolute; inset: 0; height: 100%; }
.hub-radar { position: absolute; inset: 5.13%; border-radius: 50%;
  background: conic-gradient(from 0deg, rgba(165, 152, 255, 0) 0deg, rgba(165, 152, 255, 0) 250deg, rgba(111, 168, 255, 0.07) 320deg, rgba(79, 227, 200, 0.16) 360deg);
  -webkit-mask-image: radial-gradient(circle, transparent 20%, #000 34%, #000 52%, transparent 66%); mask-image: radial-gradient(circle, transparent 20%, #000 34%, #000 52%, transparent 66%); }
.hub .x-nl { paint-order: stroke; stroke: var(--bg); stroke-width: 7px; stroke-linejoin: round; font-size: 18px; }
.uc-note { display: flex; align-items: center; gap: 0.8rem; margin-top: 1.6rem; font-size: 0.85rem; color: var(--text-3); }
.uc-note i { flex: none; width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--ok); box-shadow: 0 0 10px rgba(52, 211, 153, 0.8); }

@media (max-width: 75rem) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .t-4, .t-3 { grid-column: span 2; }
  .t-2 { grid-column: span 1; }
}
@media (max-width: 62rem) {
  .lifecycle .lc-desk { display: none; }
  .lifecycle .lc-mob { display: block; }
  .lifecycle { margin-top: 3rem; }
}
@media (max-width: 56rem) {
  .bento { grid-template-columns: 1fr; }
  .t-4, .t-3, .t-2 { grid-column: auto; }
  .t-2 .tile-scene .fx-svg { max-width: 26rem; margin-inline: auto; }
}
@media (max-width: 48rem) { .br-d { display: none; } }
@media (max-width: 40rem) {
  .t-4 .tile-scene, .t-3 .tile-scene { display: none; }
  .t-4 .tile-compact, .t-3 .tile-compact { display: block; }
  .tile-hd { padding: 1.5rem 1.4rem 0; }
  .tile-scene { padding: 1.4rem 1.4rem 1.5rem; }
  .tile h3 { font-size: 1.3rem; }
  .hub .x-nl { font-size: 26px; stroke-width: 8px; }
}
@media print { .lifecycle, .tile, .hub { break-inside: avoid; } }
.page-head { overflow-x: clip; }

/* ---- /compare/: the studio goes offline, the Waveform column, the cost bar, keys moving across ----
   Finished state (no JS, print, reduced motion) is the offline moment: Waveform still licensed, the dongle licensed while
   it is present, the cloud check and the store lookup unable to verify. graphics.js adds .fx-on to run the 10 s loop. */
.fxs .x-on, .fxs .x-oa, .fxs .x-oz, .fxs .x-oglow, .fxs .x-ora { opacity: 0; }
.fxs .x-oa, .fxs .x-oz { stroke-dasharray: 0.12 1; stroke-dashoffset: 0.12; }
.fxs .x-odim { opacity: 0.22; }
.fxs .x-ohalo { opacity: 0.6; }
.fxs .x-ox { transform-box: fill-box; transform-origin: center; }
.fxs.fx-on .x-oa { animation: x-oa 10s linear infinite; }
.fxs.fx-on .x-oz { animation: x-oz 10s linear infinite; }
.fxs.fx-on .x-on { animation: x-on 10s ease-in-out infinite; }
.fxs.fx-on .x-off { animation: x-off 10s ease-in-out infinite; }
.fxs.fx-on .x-odim { animation: x-odim 10s ease-in-out infinite; }
.fxs.fx-on .x-ox { animation: x-ox 10s cubic-bezier(0.2, 0.7, 0.2, 1) infinite; }
.fxs.fx-on .x-oglow { animation: x-oglow 10s ease-in-out infinite; }
.fxs.fx-on .x-ora { animation: x-ora 10s ease-in-out infinite; }
.fxs.fx-on .x-orb { animation: x-orb 10s ease-in-out infinite; }
.fxs.fx-on .x-oshk { animation: x-oshk 10s ease-in-out infinite; }
.fxs.fx-on .x-ohalo { animation: x-breathe 4.5s ease-in-out infinite; }
@keyframes x-oa{0%,5%{stroke-dashoffset:.12;opacity:0}6%{opacity:1}19%{stroke-dashoffset:-1;opacity:1}20%,100%{stroke-dashoffset:-1;opacity:0}}
@keyframes x-oz{0%,34%{stroke-dashoffset:.12;opacity:0}35%{opacity:1}46%{stroke-dashoffset:-1;opacity:1}47%,100%{stroke-dashoffset:-1;opacity:0}}
@keyframes x-on{0%,26%{opacity:1}29%,86%{opacity:0}89%,100%{opacity:1}}
@keyframes x-off{0%,26%{opacity:0}29%,86%{opacity:1}89%,100%{opacity:0}}
@keyframes x-odim{0%,27%{opacity:1}31%,86%{opacity:.22}90%,100%{opacity:1}}
@keyframes x-ox{0%,29%{opacity:0;transform:scale(.5)}33%,86%{opacity:1;transform:scale(1)}89%,100%{opacity:0;transform:scale(1)}}
@keyframes x-oglow{0%,17%{opacity:0}20%{opacity:1}28%{opacity:0}44%{opacity:0}47%{opacity:1}58%,100%{opacity:0}}
@keyframes x-ora{0%,47%{opacity:1}50%,88%{opacity:0}91%,100%{opacity:1}}
@keyframes x-orb{0%,47%{opacity:0}50%,88%{opacity:1}91%,100%{opacity:0}}
@keyframes x-oshk{0%,49%{transform:translateX(0)}51%{transform:translateX(-5px)}53%{transform:translateX(5px)}55%{transform:translateX(-3px)}57%,100%{transform:translateX(0)}}

/* a slow band of light down the Waveform column, and a glint along the Waveform cost bar */
.cmp-col::after, .bar-wf::after { content: ""; position: absolute; opacity: 0; pointer-events: none; }
.cmp-col::after { left: 0; right: 0; top: -9rem; height: 9rem; background: linear-gradient(180deg, transparent, rgba(165, 152, 255, 0.14), transparent); }
.bar-wf::after { top: 0; bottom: 0; left: 0; width: 30%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent); }
.fxs.fx-on .cmp-col::after { animation: x-csweep 7s cubic-bezier(0.45, 0, 0.55, 1) infinite; }
.fxs.fx-on .bar-wf::after { animation: x-shine 3.6s ease-in-out infinite; }
.fxs.fx-paused .cmp-col::after, .fxs.fx-paused .bar-wf::after { animation-play-state: paused; }
@keyframes x-csweep{0%{top:-9rem;opacity:0}10%{opacity:1}85%{opacity:1}100%{top:100%;opacity:0}}
@keyframes x-shine{0%{transform:translateX(-120%);opacity:1}60%,100%{transform:translateX(420%);opacity:1}}

/* keys from the previous system arrive in Waveform and stay valid */
.fxs .x-mk { transform: translateX(358px); }
.fxs.fx-on .x-mk { animation: x-mk 9s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.fxs.fx-on .x-mok { animation: x-mok 9s ease-in-out infinite; }
.fxs.fx-on .x-mring { animation: x-breathe 3s ease-in-out infinite; }
.fxs.fx-on .x-mk2 { animation-delay: 0.9s; }
.fxs.fx-on .x-mk3 { animation-delay: 1.8s; }
@keyframes x-mk{0%,6%{transform:translateX(0);opacity:0}10%{opacity:1}34%{transform:translateX(0)}52%{transform:translateX(358px);opacity:1}86%{transform:translateX(358px);opacity:1}92%,100%{transform:translateX(358px);opacity:0}}
@keyframes x-mok{0%,52%{opacity:0}58%,86%{opacity:1}92%,100%{opacity:0}}
@media print { .offline, .cmp, .calc-out, .move { break-inside: avoid; } }
