/* Quinine Cybersecurity: procedural cybersecurity backgrounds (cyber-bg.js) and the packet-flow
   diagram. Decorative layers sit behind content (z-index -1 inside an isolated host), never take
   pointer events and are aria-hidden. Colours come only from tokens.css. Animations run only on
   .cyber-bg.is-live (on screen, within the animation budget) and pause while the tab is hidden;
   prefers-reduced-motion shows the final, static composition. Docs: docs/cyber-visuals.md. */

:where([data-cyber]) { position: relative; isolation: isolate; }

.cyber-bg {
  --cb-wire: color-mix(in srgb, var(--color-accent) 17%, transparent);
  --cb-wire-lit: color-mix(in srgb, var(--color-accent) 62%, transparent);
  --cb-fine: color-mix(in srgb, var(--color-line-fine) 42%, transparent);
  --cb-node: color-mix(in srgb, var(--color-accent) 30%, transparent);
  --cb-plate: var(--color-bg);
  --cb-packet: color-mix(in srgb, var(--color-accent) 80%, transparent);
  --cb-signal: var(--color-signal);
  --cb-text: color-mix(in srgb, var(--color-text-muted) 62%, transparent);
  --cb-q-line: color-mix(in srgb, var(--color-ink) 9%, transparent);
  --cb-q-trace: color-mix(in srgb, var(--color-accent) 55%, transparent);
  --cb-q-fill: color-mix(in srgb, var(--color-ink) 3%, transparent);
  --cb-grid: color-mix(in srgb, var(--color-accent) 7%, transparent);
  position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  contain: strict;
}
:root[data-theme="dark"] .cyber-bg {
  --cb-wire: color-mix(in srgb, var(--color-accent) 14%, transparent);
  --cb-packet: color-mix(in srgb, var(--citron) 85%, transparent);
  --cb-q-line: color-mix(in srgb, var(--color-ink) 7%, transparent);
  --cb-q-trace: color-mix(in srgb, var(--citron) 50%, transparent);
  --cb-grid: color-mix(in srgb, var(--color-ink) 4%, transparent);
}
/* Dark band surfaces (footer, feature panels): on-band tokens in both themes. */
.cyber-bg.cb--band {
  --cb-wire: color-mix(in srgb, var(--color-on-band) 10%, transparent);
  --cb-wire-lit: color-mix(in srgb, var(--color-on-band) 34%, transparent);
  --cb-node: color-mix(in srgb, var(--color-on-band) 18%, transparent);
  --cb-plate: var(--color-band);
  --cb-packet: color-mix(in srgb, var(--citron) 80%, transparent);
  --cb-text: color-mix(in srgb, var(--color-on-band-muted) 45%, transparent);
  --cb-q-line: color-mix(in srgb, var(--color-on-band) 7%, transparent);
  --cb-q-trace: color-mix(in srgb, var(--citron) 40%, transparent);
  --cb-q-fill: color-mix(in srgb, var(--color-on-band) 2.5%, transparent);
  --cb-grid: color-mix(in srgb, var(--color-on-band) 4%, transparent);
}

/* Security grid: its own layer; scroll position nudges its opacity (--cb-scroll, 0..1). */
.cb-grid {
  position: absolute; inset: 0; will-change: opacity;
  background-image: linear-gradient(var(--cb-grid) 1px, transparent 1px), linear-gradient(90deg, var(--cb-grid) 1px, transparent 1px);
  background-size: 40px 40px; background-position: -1px -1px;
  opacity: calc(0.55 + 0.45 * var(--cb-scroll, 0.6));
  -webkit-mask-image: radial-gradient(ellipse 80% 75% at 50% 45%, #000 30%, transparent 85%);
  mask-image: radial-gradient(ellipse 80% 75% at 50% 45%, #000 30%, transparent 85%);
}
.cb--small .cb-grid { background-size: 32px 32px; }

.cb-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: hidden; }
.cyber-bg[data-focus="right"] .cb-svg { -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.25) 10%, #000 65%); mask-image: linear-gradient(90deg, rgba(0,0,0,0.25) 10%, #000 65%); }
.cyber-bg[data-focus="left"] .cb-svg { -webkit-mask-image: linear-gradient(270deg, rgba(0,0,0,0.25) 10%, #000 65%); mask-image: linear-gradient(270deg, rgba(0,0,0,0.25) 10%, #000 65%); }
.cyber-bg[data-focus="edges"] .cb-svg { -webkit-mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, rgba(0,0,0,0.3) 35%, #000 90%); mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, rgba(0,0,0,0.3) 35%, #000 90%); }

.cb-grain-dot { fill: var(--cb-wire); }
.cb-grain { opacity: 0.8; }
.cb-arch path, .cb-arch circle { fill: none; stroke: var(--cb-fine); stroke-width: 1; stroke-dasharray: 1 0; opacity: 0.55; }
.cb-arch circle { stroke-dasharray: 2 7; }

.cb-trace { fill: none; stroke: var(--cb-wire); stroke-width: 1.25; stroke-linejoin: round; stroke-linecap: round; transition: stroke 400ms ease; }
.cb-trace.is-lit { stroke: var(--cb-wire-lit); }
.cb-trace--stub { stroke-dasharray: 2 4; }
.cb-pad { fill: var(--cb-plate); stroke: var(--cb-wire); stroke-width: 1.2; }
.cb-link { fill: none; stroke: var(--cb-wire); stroke-width: 1; stroke-dasharray: 3 5; transition: stroke 300ms ease; }
.cb-link.is-active { stroke: var(--cb-wire-lit); stroke-dasharray: none; }
.cb-node-ring { fill: var(--cb-plate); stroke: var(--cb-node); stroke-width: 1.2; transition: stroke 300ms ease; }
.cb-node-core { fill: var(--cb-node); transition: fill 300ms ease; }
.cb-node.is-active .cb-node-ring { stroke: var(--cb-packet); }
.cb-node.is-active .cb-node-core, .cb-node.is-active .cb-qnode { fill: var(--cb-signal); }
.cb-qnode { fill: var(--cb-node); stroke: none; transition: fill 300ms ease; }

.cb-boundary-line { fill: none; stroke: var(--cb-fine); stroke-width: 1; stroke-dasharray: 10 4 2 4; }
.cb-gate { fill: var(--cb-plate); stroke: var(--cb-fine); stroke-width: 1.2; }
.cb-subnet-box { fill: none; stroke: var(--cb-fine); stroke-width: 1; stroke-dasharray: 4 4; }
.cb-term, .cb-hex text { font-family: var(--font-mono-stack); font-size: 10px; letter-spacing: 0.14em; fill: var(--cb-text); }
.cb-hex text { font-size: 9px; fill: var(--cb-fine); }

.cb-packet { fill: none; stroke: var(--cb-packet); stroke-width: 2.2; stroke-linecap: round; stroke-dasharray: 3 200; stroke-dashoffset: -55; }

.cb-q-outline { fill: none; stroke: var(--cb-q-line); stroke-width: 1.4; stroke-linejoin: round; }
.cb-q-trace { fill: none; stroke: var(--cb-q-trace); stroke-width: 1.6; stroke-linecap: round; stroke-dasharray: 5 95; stroke-dashoffset: 30; }
.cb-q-fill { fill: var(--cb-q-fill); stroke: none; }
.cb-q--footer .cb-q-outline { stroke-width: 1.2; }
.cb-q--once .cb-q-outline { stroke: color-mix(in srgb, var(--cb-q-trace) 55%, transparent); }
.cb-q--converge .cb-q-outline { stroke: color-mix(in srgb, var(--cb-fine) 80%, transparent); }
.cb-converge-line { fill: none; stroke: var(--cb-fine); stroke-width: 1; opacity: 0.6; }
.cb-q--mini { stroke: var(--cb-node); }
.cb-step-wire { fill: none; stroke: var(--cb-wire-lit); stroke-width: 1.2; stroke-dasharray: 2 4; opacity: 0.7; }

.cb-scan {
  position: absolute; inset: 0; opacity: 0; will-change: transform, opacity;
  background: linear-gradient(180deg, transparent 0%, transparent 94%, color-mix(in srgb, var(--cb-packet) 10%, transparent) 99.4%, color-mix(in srgb, var(--cb-packet) 30%, transparent) 100%);
}

/* ------------------------------------------------------------------ motion (only while live) */
@media (prefers-reduced-motion: no-preference) {
  .cyber-bg:not(.is-live) :is(.cb-packet, .cb-q-trace, .cb-scan, .cb-q-conv, .cb-converge-line, .cb-node--pulse, .cb-node--blink, .cb-q--footer) { animation-play-state: paused !important; }
  :root.cyber-hidden .cyber-bg * { animation-play-state: paused !important; }

  .cb-packet { animation: cb-packet var(--cb-dur, 9s) linear var(--cb-delay, 0s) infinite both; }
  .cb-packet--step { animation: cb-packet-step 4.8s var(--ease-in-out) var(--cb-delay, 0s) infinite both; }
  .cb-packet--q { animation: cb-packet-q 18s var(--ease-in-out) 3s infinite both; stroke-dasharray: 4 200; }
  .cb-q-trace { animation: cb-q-trace 48s linear infinite; }
  .cb-scan { animation: cb-scan 22s var(--ease-in-out) 5s infinite; }
  .cb-node--pulse { animation: cb-node-pulse 7s ease-in-out var(--cb-delay, 0s) infinite; }
  .cb-node--blink { animation: cb-blink 6s ease-in-out var(--cb-delay, 0s) infinite; }
  .cb-q--footer { animation: cb-ambient 12s ease-in-out infinite; }

  .cyber-bg .cb-entry { stroke-dasharray: 100 100; stroke-dashoffset: 100; }
  .cyber-bg.is-entered .cb-entry { animation: cb-draw 1.6s var(--ease-trace) var(--cb-delay, 0s) both; }
  .cb-q--once .cb-q-draw { stroke-dasharray: 100 100; stroke-dashoffset: 100; }
  .cyber-bg.is-entered .cb-q--once .cb-q-draw { animation: cb-draw 2.6s var(--ease-trace) 300ms both; }
  .cb-q-conv, .cb-converge-line { stroke-dasharray: 100 100; }
  .cb-q-conv { animation: cb-converge-q 26s var(--ease-in-out) 2s infinite both; }
  .cb-converge-line { animation: cb-converge-line 26s var(--ease-in-out) 2s infinite both; }

  .cb-flow__packet { animation: cb-packet 4.8s linear var(--cb-delay, 0s) infinite both; animation-play-state: paused; }
  .cb-flow__packet--return { animation-duration: 6.4s; }
  [data-cyber-diagram].is-live .cb-flow__packet { animation-play-state: running; }
  :root.cyber-hidden .cb-flow__packet { animation-play-state: paused; }
}
@media (prefers-reduced-motion: reduce) {
  .cb-converge-line { opacity: 0.35; }
  .cb-packet--q { display: none; }
}

@keyframes cb-packet { from { stroke-dashoffset: 3; } to { stroke-dashoffset: -100; } }
@keyframes cb-packet-step { 0% { stroke-dashoffset: 3; opacity: 1; } 40% { stroke-dashoffset: -100; opacity: 1; } 41%, 100% { stroke-dashoffset: -100; opacity: 0; } }
@keyframes cb-packet-q { 0% { stroke-dashoffset: 4; opacity: 1; } 34% { stroke-dashoffset: -100; opacity: 1; } 35%, 100% { stroke-dashoffset: -100; opacity: 0; } }
@keyframes cb-q-trace { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes cb-scan { 0% { opacity: 0; transform: translateY(-100%); } 5% { opacity: 1; } 28% { opacity: 1; transform: translateY(0); } 32%, 100% { opacity: 0; transform: translateY(0); } }
@keyframes cb-node-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@keyframes cb-blink { 0%, 70%, 100% { opacity: 1; } 78% { opacity: 0.3; } 86% { opacity: 1; } }
@keyframes cb-ambient { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }
@keyframes cb-draw { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes cb-converge-line { 0%, 6% { stroke-dashoffset: 100; opacity: 0.6; } 20% { stroke-dashoffset: 0; } 70% { stroke-dashoffset: 0; opacity: 0.6; } 82%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes cb-converge-q { 0%, 16% { stroke-dashoffset: 100; opacity: 1; } 34% { stroke-dashoffset: 0; } 72% { stroke-dashoffset: 0; opacity: 1; } 84%, 100% { stroke-dashoffset: 0; opacity: 0.25; } }

/* ------------------------------------------------------------------ packet-flow diagram */
[data-cyber-diagram="packet-flow"] { display: block; min-height: 420px; }
[data-cyber-diagram="packet-flow"].is-ready { min-height: 0; }
.cb-flow { color: var(--color-text); margin: 0; padding: clamp(14px, 2vw, 24px); border: 1px solid var(--color-line); border-radius: var(--radius-l); background: var(--color-surface);
  --cb-packet: var(--color-accent); --cb-fine: var(--color-line-fine); }
:root[data-theme="dark"] .cb-flow { --cb-packet: var(--citron); }
.cb-flow__svg { display: block; width: 100%; height: auto; }
.cb-flow--h .cb-flow__svg { aspect-ratio: 960 / 300; }
.cb-flow--v .cb-flow__svg { aspect-ratio: 360 / 660; max-width: 420px; margin: 0 auto; }
.cb-flow__zone { fill: color-mix(in srgb, var(--color-accent) 4%, transparent); stroke: var(--color-line-fine); stroke-width: 1; stroke-dasharray: 10 4 2 4; }
.cb-flow__zone-label, .cb-flow__check-label { font-family: var(--font-mono-stack); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; fill: var(--color-detail-ink); }
.cb-flow__check-label { fill: var(--color-text-muted); font-size: 11.5px; }
.cb-flow--v .cb-flow__zone-label, .cb-flow--v .cb-flow__check-label { font-size: 13px; letter-spacing: 0.06em; }
.cb-flow__wire { fill: none; stroke: color-mix(in srgb, var(--color-accent) 50%, transparent); stroke-width: 1.6; }
.cb-flow__wire--return { stroke-dasharray: 4 5; }
.cb-flow__node { fill: var(--color-surface); stroke: var(--color-accent); stroke-width: 1.5; }
.cb-flow__label { font-family: var(--font-body); font-size: 15px; font-weight: 640; fill: var(--color-ink); }
.cb-flow__check { fill: var(--color-surface); stroke: var(--color-line-fine); stroke-width: 1.6; }
.cb-flow__check--out { stroke: var(--color-accent); }
.cb-flow .cb-packet { stroke-width: 3; stroke-dasharray: 2.2 200; }
.cb-flow__steps { margin: 18px 0 0; padding: 0; list-style: none; counter-reset: cbstep; display: grid; gap: 10px 28px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.cb-flow .cb-flow__steps li { counter-increment: cbstep; position: relative; padding-left: 36px; font-size: var(--text-small); line-height: var(--leading-small); color: var(--color-text); }
.cb-flow__steps li::before { content: counter(cbstep, decimal-leading-zero); position: absolute; left: 0; top: 1px; font-family: var(--font-mono-stack); font-size: 0.75rem; letter-spacing: 0.08em; color: var(--color-detail-ink); }
.cb-flow .cb-flow__steps strong { color: var(--color-ink); font-weight: var(--weight-strong); }

@media (forced-colors: active) {
  .cyber-bg { display: none; }
}
@media print {
  .cyber-bg { display: none; }
}
