/* ============================================================
   Lighthouse — §02 Applications: bespoke per-industry visuals
   Each use case gets the simplest, most appropriate picture rather
   than one repeated readout. Shared vocabulary: thin hairlines, sharp
   corners, mono micro-labels, marigold = resolved/positive signal,
   periwinkle = secondary voice, dim = unresolved.
   ============================================================ */

.appviz { display: none; flex: 1; flex-direction: column; }
.appviz.on { display: flex; }

.viz-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 16px; border-bottom: 1px solid var(--hair); }
.viz-head .vlab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--text-tertiary); }
.viz-head .vstate { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--periwinkle); display: inline-flex; align-items: center; gap: 9px; }

.viz-canvas { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 30px 6px; }

/* ---- shared reveal primitives (robust; play on .appviz.on.in) ---- */
.appviz .anim { opacity: 0; }
.appviz.in .anim { animation: vzFade 620ms var(--ease-out-quint) var(--d, 0ms) both; }
@keyframes vzFade { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

.appviz .pop { opacity: 0; transform: scale(0.55); transform-box: fill-box; transform-origin: center; }
.appviz.in .pop { animation: vzPop 540ms var(--ease-out-expo) var(--d, 0ms) both; }
@keyframes vzPop { from { opacity: 0; transform: scale(0.55); } to { opacity: 1; transform: scale(1); } }

/* travel-and-halt (V15): one pass from the authored position to +--tx, decelerating in.
   Under frozen/reduced-motion the override below drops the transform entirely, so the
   dots stand at their authored (pre-travel) lane positions - today's static picture. */
.appviz .trav { opacity: 0; transform-box: fill-box; }
.appviz.in .trav { animation: vzTravel 900ms var(--ease-out-expo) var(--d, 0ms) both; }
@keyframes vzTravel { from { opacity: 0; transform: translateX(0); } 8% { opacity: 1; } to { opacity: 1; transform: translateX(var(--tx, 0px)); } }

body.frozen .appviz .anim { opacity: 1 !important; transform: none !important; animation: none !important; }
body.frozen .appviz .pop { opacity: 1 !important; transform: scale(1) !important; animation: none !important; }
body.frozen .appviz .trav { opacity: 1 !important; transform: none !important; animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  .appviz .anim { opacity: 1 !important; transform: none !important; animation: none !important; }
  .appviz .pop { opacity: 1 !important; transform: scale(1) !important; animation: none !important; }
  .appviz .trav { opacity: 1 !important; transform: none !important; animation: none !important; }
}

/* ============================================================
   01 · BANKING — wire held until the counterparty resolves
   ============================================================ */
.vz-bank svg { width: 100%; height: 130px; overflow: visible; display: block; }
.vz-bank .lane { stroke: var(--hair-strong); stroke-width: 1; stroke-dasharray: 3 5; }
.vz-bank .ep { fill: none; stroke: var(--text-dim); stroke-width: 1.5; }
.vz-bank .ep.payer { fill: var(--surface-2); }
.vz-bank .check { stroke: var(--canvas); stroke-width: 1.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.vz-bank .gate { stroke: var(--marigold); stroke-width: 1.8; }
.vz-bank .nlab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-bank .dot { fill: var(--marigold); }
.vz-bank .hold-tick { stroke: var(--marigold); stroke-width: 2; }
.vz-bank .release-row { display: flex; align-items: center; justify-content: space-between; margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--hair); }
.vz-bank .rl-state { display: inline-flex; align-items: center; gap: 12px; }
.vz-bank .rl-state .tag { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: #141416; background: var(--marigold); padding: 5px 12px; }
.vz-bank .rl-state .sub { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-tertiary); }
.vz-bank .amount { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 32px; color: var(--text-primary); letter-spacing: -0.03em; }
.vz-bank .amount .cur { color: var(--text-tertiary); font-size: 0.66em; margin-right: 4px; }
.vz-bank .coach { fill: none; stroke: var(--periwinkle); stroke-width: 1.5; }
.vz-bank .coach-link { stroke: rgba(136,156,231,0.5); stroke-width: 1; stroke-dasharray: 3 4; }
.vz-bank .coach-lab { fill: var(--periwinkle); }
.vz-bank .recip-glow { fill: rgba(136,156,231,0.12); }
.vz-bank .recip-ring { fill: none; stroke: var(--periwinkle); stroke-width: 1.5; }
.vz-bank .qm { fill: var(--periwinkle); font-family: var(--font-mono); font-size: 14px; }
.vz-bank .rl-state .tag.hold { background: transparent; border: 1px dashed var(--text-dim); color: var(--periwinkle); }

/* ============================================================
   02 · PLATFORMS — real vs. synthetic at the door
   ============================================================ */
.vz-plat .tiles { display: grid; grid-template-columns: repeat(8, 1fr); gap: 10px; }
.vz-plat .tile { position: relative; aspect-ratio: 1; border: 1px solid var(--hair-strong); display: flex; align-items: center; justify-content: center; }
.vz-plat .tile .glyph { width: 9px; height: 9px; border-radius: 50%; }
.vz-plat .tile.real { border-color: rgba(202,169,11,0.4); background: rgba(202,169,11,0.05); }
.vz-plat .tile.real .glyph { background: var(--marigold); box-shadow: 0 0 8px 1px rgba(202,169,11,0.5); }
.vz-plat .tile.synth { border-color: rgba(226,80,75,0.55); border-style: dashed; } /* synthetic-at-the-door reads as risk */
.vz-plat .tile.synth::before, .vz-plat .tile.synth::after { content: ''; position: absolute; width: 13px; height: 1.5px; background: var(--flag); }
.vz-plat .tile.synth::before { transform: rotate(45deg); }
.vz-plat .tile.synth::after { transform: rotate(-45deg); }
/* V16: history ticks - a small run of past under every real tile, none under the synthetic.
   Sized to survive the 0.85-zoom accordion (4x2px ticks stay >=1px and clear the glyph). */
.vz-plat .tile .hist { position: absolute; left: 0; right: 0; bottom: 5px; display: flex; justify-content: center; gap: 2px; }
.vz-plat .tile .hist i { width: 4px; height: 2px; background: rgba(202,169,11,0.55); }
.vz-plat .legend { display: flex; gap: 28px; margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--hair); }
.vz-plat .leg { display: flex; flex-direction: column; gap: 6px; }
.vz-plat .leg .num { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 34px; line-height: 1; letter-spacing: -0.02em; color: var(--text-primary); }
.vz-plat .leg.synth .num { color: var(--text-tertiary); }
.vz-plat .leg .lb { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-tertiary); display: flex; align-items: center; gap: 7px; }
.vz-plat .leg .lb .sw { width: 8px; height: 8px; border-radius: 50%; background: var(--marigold); }
.vz-plat .leg.synth .lb .sw { background: transparent; border: 1px dashed var(--text-dim); border-radius: 0; }

/* ============================================================
   04 · CORPORATE SECURITY — what's already in the open
   (V10: compressed to 210px; fragments named to recon's standard)
   ============================================================ */
.vz-corp svg { width: 100%; height: 210px; overflow: visible; display: block; }
.vz-corp .ring { fill: none; stroke: var(--hair-strong); stroke-width: 1; stroke-dasharray: 3 5; }
.vz-corp .principal { fill: var(--surface-2); stroke: var(--text-secondary); stroke-width: 1.5; }
.vz-corp .plab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-corp .slab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-corp .conn { stroke: rgba(202,169,11,0.3); stroke-width: 1; }
.vz-corp .frag { fill: var(--marigold); }
.vz-corp .frag-glow { fill: rgba(202,169,11,0.14); }
.vz-corp .count { display: flex; align-items: baseline; gap: 12px; margin-top: 6px; padding-top: 18px; border-top: 1px solid var(--hair); }
.vz-corp .count .num { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 34px; line-height: 1; letter-spacing: -0.02em; color: var(--marigold); }
.vz-corp .count .lb { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-tertiary); }

/* ============================================================
   HIRING - the resume vs. the discovered history (horizontal)
   ============================================================ */
.vz-lend svg { overflow: visible; } /* siblings declare this; without it the UA default clips the last label */
.vz-lend .hd-doc { fill: var(--surface); stroke: var(--text-dim); stroke-width: 1.3; }
.vz-lend .hd-docline { stroke: var(--text-dim); stroke-width: 1.4; }
.vz-lend .hd-axis { stroke: rgba(202,169,11,0.34); stroke-width: 1.4; }
.vz-lend .hd-node { fill: var(--marigold); }
.vz-lend .hd-node.hd-deep { stroke: var(--marigold); stroke-width: 1.4; fill: var(--surface-2); }
.vz-lend .hd-glow { fill: rgba(202,169,11,0.15); }
.vz-lend .nlab { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-lend .hd-lab { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-lend .hd-lab.ac { fill: var(--marigold); }
/* ride-along count row - recon's payoff-row pattern, verbatim */
.vz-lend .count { display: flex; align-items: baseline; gap: 12px; margin-top: 6px; padding-top: 18px; border-top: 1px solid var(--hair); }
.vz-lend .count .num { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 34px; line-height: 1; letter-spacing: -0.02em; color: var(--marigold); }
.vz-lend .count .lb { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-tertiary); }

/* ============================================================
   THREAT & INVESTIGATIONS — fragments → unmasked subject
   ============================================================ */
.vz-recon svg { width: 100%; height: 180px; overflow: visible; display: block; }
.vz-recon .frag-src { fill: none; stroke: var(--text-dim); stroke-width: 1.3; stroke-dasharray: 3 3; }
.vz-recon .flink { stroke: rgba(202,169,11,0.3); stroke-width: 1; }
.vz-recon .slab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; fill: var(--text-tertiary); }
.vz-recon .subj-glow { fill: rgba(202,169,11,0.14); }
.vz-recon .subj-ring { fill: none; stroke: var(--marigold); stroke-width: 1.5; }
.vz-recon .subj-core { fill: var(--surface-2); stroke: var(--marigold); stroke-width: 1.5; }
.vz-recon .subj-check { fill: none; stroke: var(--marigold); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.vz-recon .plab { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; fill: var(--text-secondary); }
.vz-recon .count { display: flex; align-items: baseline; gap: 12px; margin-top: 6px; padding-top: 18px; border-top: 1px solid var(--hair); }
.vz-recon .count .num { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 34px; line-height: 1; letter-spacing: -0.02em; color: var(--marigold); }
.vz-recon .count .lb { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-tertiary); }
