/* lib/fui/family-viewport — shared CSS for Family C (CRT viewport / surveillance)
 *
 * Used by: SECOND-PARTY, DEEPSIGNAL, STORMWATCH, KOI-90B SHRINE-SAT.
 *
 * Palette is supplied by each scenario via :root vars (--p-bg, --p-text, --p-accent,
 * --p-data, --p-dim, --p-cool, --p-alarm, --p-panel, --p-rule, --p-rule2). This file
 * references only those vars — never raw hex colors (except for the dark bezel fill,
 * which is intentionally palette-agnostic — bezels are physical hardware, not skinned).
 *
 * Layout grammar (apply to scenario root container):
 *   .fv-root                  — full-bleed, position:relative, contains everything
 *     .fv-edge-top            — top header strip (--fv-top-h, default 30px)
 *     .fv-edge-bot            — bottom status strip (--fv-bot-h, default 36px)
 *     .fv-bezel               — outer dark CRT bezel frame (between edges)
 *       .fv-bezel-label       — etched model number / serial on bezel
 *       .fv-viewport          — the live image area inside the bezel
 *         (canvas | svg | img — hero subject)
 *         .fv-recticle-overlay  — crosshair + corner brackets + range rings
 *         .fv-scanlines-heavy   — CRT scanlines (always on viewport)
 *         .fv-chromatic         — RGB-shift fringe
 *         .fv-vignette-heavy    — corner darkening
 *         .fv-curve-glass       — top/bottom highlight gradient
 *         .fv-grain             — SVG turbulence noise
 *         .fv-flicker           — brightness flicker
 *         .fv-viewport-corner   — small L-bracket registration marks (×4)
 *     .fv-gauge-col.left       — left mirrored gauge column
 *     .fv-gauge-col.right      — right mirrored gauge column
 *     .fv-stamp.tl/.tr/.bl/.br — corner classification stamps
 *
 * Distinct from Family A: bezel is a real frame, not a strip. Viewport is the hero,
 * not annotated. Post-FX (scanlines, vignette, chromatic) are noticeably HEAVIER —
 * this is a CRT, not a clean schematic.
 */

:root {
  --fv-top-h:      30px;
  --fv-bot-h:      36px;
  --fv-col-w:      130px;
  --fv-bezel-pad:  18px;
  --fv-bezel-fill: #0a0a0c;
  --fv-bezel-edge: #1a1a1e;
  --fv-bezel-etch: rgba(255, 255, 255, 0.18);
  --fv-rule:       var(--p-rule2, rgba(255, 255, 255, 0.06));
  --fv-strip-bg:   rgba(0, 0, 0, 0.62);
  --fv-mono:       'JetBrains Mono', ui-monospace, monospace;
  --fv-glow:       0 0 8px color-mix(in srgb, var(--p-accent, #aaa) 50%, transparent);
}

/* === ROOT === */

.fv-root {
  position: fixed;
  inset: 0;
  background: var(--p-bg, #000);
  color: var(--p-text, #fff);
  overflow: hidden;
  font-family: var(--fv-mono);
}

/* === BEZEL ===
 * Dark physical CRT frame. Sits between the top/bottom edge strips and inside
 * the gauge columns (gauge cols are siblings layered above). Has an inset
 * shadow simulating the bezel-to-screen lip + a faint etched brand label at
 * the top center.
 */

.fv-bezel {
  position: absolute;
  top:    var(--fv-top-h);
  bottom: var(--fv-bot-h);
  left:   var(--fv-col-w);
  right:  var(--fv-col-w);
  background:
    linear-gradient(180deg, #0d0d10 0%, #060608 50%, #0d0d10 100%),
    var(--fv-bezel-fill);
  border: 1px solid var(--fv-bezel-edge);
  border-radius: 4px;
  padding: var(--fv-bezel-pad);
  box-shadow:
    inset 0  1px 0   rgba(255, 255, 255, 0.04),
    inset 0 -1px 0   rgba(0,   0,   0,   0.50),
    inset 0  0   28px rgba(0,   0,   0,   0.70);
  z-index: 2;
}

.fv-bezel-label {
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--fv-mono);
  font-size: 8.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--fv-bezel-etch);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.85);
  user-select: none;
  pointer-events: none;
  z-index: 3;
}

/* === VIEWPORT ===
 * The live image area. Slightly inset from the bezel padding. Hero subject
 * (canvas / svg / img) goes in here; reticle + post-FX overlays sit on top.
 */

.fv-viewport {
  position: relative;
  width: 100%;
  height: 100%;
  background: #000;
  overflow: hidden;
  isolation: isolate;
}
/* Hero layers (canvas/img/reticle SVG) fill the viewport. The .fv-viewport-fill
 * class is opt-in so authors can also place small inset SVGs inside the viewport
 * (logos, coffee-mug glyphs, etc.) without those getting blown up to full size.
 * Plain canvas / img still default-fill (the common case); only SVG must be
 * opted-in via the explicit .fv-viewport-fill class. */
.fv-viewport > canvas,
.fv-viewport > img,
.fv-viewport > svg.fv-viewport-fill,
.fv-viewport > svg.fv-recticle-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Corner registration marks — small L-brackets at each viewport corner.
 * Drawn with two thin pseudo-elements per corner (border edges).
 */
.fv-viewport-corner {
  position: absolute;
  width: 14px;
  height: 14px;
  pointer-events: none;
  z-index: 4;
  border: 1px solid color-mix(in srgb, var(--p-accent, #aaa) 70%, transparent);
}
.fv-viewport-corner.tl { top: 6px;    left: 6px;    border-right: none; border-bottom: none; }
.fv-viewport-corner.tr { top: 6px;    right: 6px;   border-left:  none; border-bottom: none; }
.fv-viewport-corner.bl { bottom: 6px; left: 6px;    border-right: none; border-top:    none; }
.fv-viewport-corner.br { bottom: 6px; right: 6px;   border-left:  none; border-top:    none; }

/* === GAUGE COLUMNS === */

.fv-gauge-col {
  position: absolute;
  top:    var(--fv-top-h);
  bottom: var(--fv-bot-h);
  width:  var(--fv-col-w);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--p-panel, #111) 80%, transparent),
    color-mix(in srgb, var(--p-panel, #111) 60%, transparent));
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 8px 10px;
  z-index: 3;
  font-family: var(--fv-mono);
}
.fv-gauge-col.left  { left: 0;  border-right: 1px solid var(--fv-rule); }
.fv-gauge-col.right { right: 0; border-left:  1px solid var(--fv-rule); }

/* === RECTANGULAR GAUGE === */

.fv-gauge {
  display: grid;
  grid-template-rows: auto auto;
  gap: 2px;
  padding: 5px 7px 6px;
  border: 1px solid var(--fv-rule);
  background: color-mix(in srgb, #000 35%, transparent);
  font-size: 9px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  position: relative;
}
.fv-gauge-lbl {
  display: flex;
  justify-content: space-between;
  color: var(--p-dim, #888);
  font-size: 8px;
}
.fv-gauge-val {
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--p-text, #fff);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

/* Horizontal bar fill */
.fv-gauge-bar {
  position: relative;
  height: 4px;
  margin-top: 4px;
  background: color-mix(in srgb, var(--p-text, #fff) 8%, transparent);
  overflow: hidden;
}
.fv-gauge-bar > i {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: var(--p-accent, #aaa);
  box-shadow: 0 0 6px color-mix(in srgb, var(--p-accent, #aaa) 60%, transparent);
}

/* Tick row beneath value — small registration ticks suggesting scale. */
.fv-gauge-tick {
  display: flex;
  gap: 2px;
  margin-top: 3px;
  height: 5px;
}
.fv-gauge-tick > i {
  flex: 1 1 0;
  background: color-mix(in srgb, var(--p-dim, #888) 50%, transparent);
}
.fv-gauge-tick > i.lit {
  background: var(--p-accent, #aaa);
  box-shadow: 0 0 4px color-mix(in srgb, var(--p-accent, #aaa) 60%, transparent);
}

/* States — change accent color of bar + value glow */
.fv-gauge.normal .fv-gauge-bar > i { background: var(--p-accent, #aaa); }
.fv-gauge.warn   .fv-gauge-bar > i { background: var(--p-data,   #fa6); }
.fv-gauge.warn   .fv-gauge-val      { color:      var(--p-data,   #fa6); }
.fv-gauge.alarm  .fv-gauge-bar > i { background: var(--p-alarm,  #c44); }
.fv-gauge.alarm  .fv-gauge-val      { color:      var(--p-alarm,  #c44);
                                       text-shadow: 0 0 5px color-mix(in srgb, var(--p-alarm, #c44) 60%, transparent); }
.fv-gauge.alarm                      { border-color: color-mix(in srgb, var(--p-alarm, #c44) 70%, transparent);
                                       animation: fv-gauge-alarm-pulse 1.2s ease-in-out infinite; }
@keyframes fv-gauge-alarm-pulse {
  0%, 100% { box-shadow: inset 0 0 0   color-mix(in srgb, var(--p-alarm, #c44) 0%,  transparent); }
  50%      { box-shadow: inset 0 0 12px color-mix(in srgb, var(--p-alarm, #c44) 35%, transparent); }
}

/* === CIRCLE GAUGE (round dial, SVG-based) ===
 * The chrome.js builder constructs the SVG; this CSS styles its sub-classes.
 */

.fv-circle-gauge {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 2px;
  padding: 6px 6px 6px;
  border: 1px solid var(--fv-rule);
  background: color-mix(in srgb, #000 35%, transparent);
}
.fv-circle-gauge .fv-cg-lbl {
  font-size: 8px;
  color: var(--p-dim, #888);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
}
.fv-circle-gauge svg {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
}
.fv-circle-gauge .fv-cg-ring   { fill: none; stroke: color-mix(in srgb, var(--p-dim, #888) 50%, transparent); stroke-width: 1; }
.fv-circle-gauge .fv-cg-tick   { stroke: var(--p-dim, #888); stroke-width: 1; }
.fv-circle-gauge .fv-cg-tick.major { stroke: var(--p-text, #fff); }
.fv-circle-gauge .fv-cg-needle { stroke: var(--p-accent, #aaa); stroke-width: 1.2; stroke-linecap: round;
                                 filter: drop-shadow(0 0 3px color-mix(in srgb, var(--p-accent, #aaa) 70%, transparent)); }
.fv-circle-gauge .fv-cg-hub    { fill: var(--p-accent, #aaa); }
.fv-circle-gauge .fv-cg-val {
  text-align: center;
  font-size: 12px;
  color: var(--p-text, #fff);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.fv-circle-gauge.warn  .fv-cg-needle { stroke: var(--p-data, #fa6); filter: drop-shadow(0 0 3px var(--p-data, #fa6)); }
.fv-circle-gauge.warn  .fv-cg-val    { color:  var(--p-data, #fa6); }
.fv-circle-gauge.alarm .fv-cg-needle { stroke: var(--p-alarm, #c44); filter: drop-shadow(0 0 4px var(--p-alarm, #c44)); }
.fv-circle-gauge.alarm .fv-cg-val    { color:  var(--p-alarm, #c44);
                                        text-shadow: 0 0 4px color-mix(in srgb, var(--p-alarm, #c44) 60%, transparent); }

/* === METER STRIP (compact horizontal: lbl ─── bar ─ val) === */

.fv-meter-strip-group {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 5px 6px;
  border: 1px solid var(--fv-rule);
  background: color-mix(in srgb, #000 30%, transparent);
}
.fv-meter-strip {
  display: grid;
  grid-template-columns: 42px 1fr 36px;
  gap: 5px;
  align-items: center;
  font-size: 8px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
}
.fv-meter-strip .fv-ms-lbl { color: var(--p-dim, #888); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fv-meter-strip .fv-ms-bar {
  position: relative;
  height: 3px;
  background: color-mix(in srgb, var(--p-text, #fff) 8%, transparent);
}
.fv-meter-strip .fv-ms-bar > i {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: var(--p-accent, #aaa);
}
.fv-meter-strip .fv-ms-val {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--p-text, #fff);
  font-size: 9px;
}
.fv-meter-strip.warn  .fv-ms-bar > i { background: var(--p-data,  #fa6); }
.fv-meter-strip.warn  .fv-ms-val      { color:      var(--p-data,  #fa6); }
.fv-meter-strip.alarm .fv-ms-bar > i { background: var(--p-alarm, #c44); }
.fv-meter-strip.alarm .fv-ms-val      { color:      var(--p-alarm, #c44); }

/* === LARGE READOUT (heavy monospace numeric) === */

.fv-readout {
  display: grid;
  grid-template-rows: auto auto;
  gap: 2px;
  padding: 6px 8px 8px;
  border: 1px solid var(--fv-rule);
  background: color-mix(in srgb, #000 40%, transparent);
}
.fv-readout .fv-ro-lbl {
  font-size: 8px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--p-dim, #888);
}
.fv-readout .fv-ro-val {
  font-family: var(--fv-mono);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--p-text, #fff);
  text-shadow: var(--fv-glow);
}
.fv-readout.sm .fv-ro-val { font-size: 16px; }
.fv-readout.md .fv-ro-val { font-size: 22px; }
.fv-readout.lg .fv-ro-val { font-size: 30px; }
.fv-readout .fv-ro-units {
  font-size: 9px;
  letter-spacing: 0.10em;
  color: var(--p-dim, #888);
  margin-left: 4px;
}
.fv-readout.warn  .fv-ro-val { color: var(--p-data,  #fa6); text-shadow: 0 0 8px color-mix(in srgb, var(--p-data, #fa6) 60%, transparent); }
.fv-readout.alarm .fv-ro-val { color: var(--p-alarm, #c44); text-shadow: 0 0 10px color-mix(in srgb, var(--p-alarm, #c44) 70%, transparent); }

/* === EDGE STRIPS (top + bottom) ===
 * Same shape as Family A's edge-top/edge-bot, but wider gauge-friendly cells
 * and namespaced .fv-* to avoid collision when families coexist on a page.
 */

.fv-edge-top, .fv-edge-bot {
  position: absolute;
  left: 0; right: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  background: linear-gradient(to bottom, var(--fv-strip-bg), transparent);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  z-index: 5;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.fv-edge-top {
  top: 0;
  height: var(--fv-top-h);
  border-bottom: 1px solid var(--fv-rule);
}
.fv-edge-bot {
  bottom: 0;
  height: var(--fv-bot-h);
  border-top: 1px solid var(--fv-rule);
  background: linear-gradient(to top, var(--fv-strip-bg), transparent);
}

.fv-et-cell, .fv-eb-cell {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
.fv-et-spacer, .fv-eb-spacer { flex: 1 1 auto; }
.fv-et-lbl, .fv-eb-lbl { color: var(--p-dim, #888); }
.fv-et-id              { color: var(--p-accent, #aaa); font-weight: 500; }
.fv-et-val, .fv-eb-val { color: var(--p-text, #fff); }

.fv-et-clock {
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--p-text, #fff);
  font-variant-numeric: tabular-nums;
  text-shadow: var(--fv-glow);
}

.fv-eb-fn { display: inline-flex; gap: 4px; }
.fv-eb-fn .fv-eb-fn-btn {
  padding: 3px 8px;
  border: 1px solid var(--fv-rule);
  color: var(--p-text);
  font-size: 8px;
  letter-spacing: 0.22em;
  background: transparent;
}
.fv-eb-fn .fv-eb-fn-btn.active {
  background: var(--p-accent, #aaa);
  color: var(--p-bg, #000);
  border-color: var(--p-accent, #aaa);
}

/* === RECTICLE OVERLAY (crosshair + brackets + range rings) === */

.fv-recticle-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  mix-blend-mode: screen;
}
.fv-recticle-overlay svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.fv-recticle-overlay .fv-rt-line   { stroke: color-mix(in srgb, var(--p-accent, #aaa) 70%, transparent); stroke-width: 0.8; fill: none; }
.fv-recticle-overlay .fv-rt-ring   { stroke: color-mix(in srgb, var(--p-accent, #aaa) 35%, transparent); stroke-width: 0.6; fill: none; stroke-dasharray: 2 3; }
.fv-recticle-overlay .fv-rt-bracket { stroke: var(--p-accent, #aaa); stroke-width: 1; fill: none; }

/* === SCANLINES === */

.fv-scanlines-heavy,
.fv-scanlines-fine {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 7;
  mix-blend-mode: overlay;
}
.fv-scanlines-heavy {
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.55) 0px,
    rgba(0, 0, 0, 0.55) 1px,
    transparent          1px,
    transparent          3px
  );
  opacity: 0.45;
}
.fv-scanlines-fine {
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.32) 0px,
    rgba(0, 0, 0, 0.32) 1px,
    transparent          1px,
    transparent          2px
  );
  opacity: 0.25;
}

/* === CHROMATIC ABERRATION (RGB-shift fringe) ===
 * Two pseudo-elements with red and cyan shifts. Mounted as a child overlay
 * on the viewport — child elements inherit nothing but position.
 */

.fv-chromatic {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 6;
  mix-blend-mode: screen;
}
.fv-chromatic::before,
.fv-chromatic::after {
  content: '';
  position: absolute;
  inset: 0;
  background: inherit;
}
.fv-chromatic::before {
  box-shadow: inset  1.2px 0 0 rgba(255, 60, 60, 0.18);
}
.fv-chromatic::after {
  box-shadow: inset -1.2px 0 0 rgba(60, 200, 255, 0.18);
}

/* === VIGNETTE (heavy corner darkening) === */

.fv-vignette-heavy {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 8;
  background: radial-gradient(ellipse at center,
    transparent       30%,
    rgba(0, 0, 0, 0.30) 60%,
    rgba(0, 0, 0, 0.78) 100%);
  mix-blend-mode: multiply;
}

/* === GRAIN (SVG turbulence) === */

.fv-grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 9;
  opacity: 0.10;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 1 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 160px 160px;
  animation: fv-grain-shift 1.6s steps(6) infinite;
  mix-blend-mode: overlay;
}
@keyframes fv-grain-shift {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-8px,  4px); }
  40%  { transform: translate( 6px, -6px); }
  60%  { transform: translate(-4px, -2px); }
  80%  { transform: translate( 2px,  6px); }
  100% { transform: translate(0, 0); }
}

/* === FLICKER (occasional brightness dip) === */

.fv-flicker {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 10;
  background: rgba(255, 255, 255, 0.02);
  animation: fv-flicker-cycle 7s steps(1) infinite;
}
@keyframes fv-flicker-cycle {
  0%, 92%  { opacity: 0; }
  93%      { opacity: 0.7; }
  94%      { opacity: 0; }
  95%      { opacity: 0.4; }
  96%, 100% { opacity: 0; }
}

/* === CURVED-GLASS HIGHLIGHT === */

.fv-curve-glass {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 11;
  background:
    radial-gradient(ellipse 110% 30% at 50%   0%, rgba(255, 255, 255, 0.06), transparent 70%),
    radial-gradient(ellipse 110% 30% at 50% 100%, rgba(255, 255, 255, 0.04), transparent 70%);
  mix-blend-mode: screen;
}

/* === LED indicator (single dot) === */

.fv-led {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--p-dim, #555);
  box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.6);
  vertical-align: middle;
  flex-shrink: 0;
}
.fv-led.green { background: var(--p-accent, #5ba877);
                box-shadow: 0 0 5px color-mix(in srgb, var(--p-accent, #5ba877) 70%, transparent),
                            inset 0 0 1px rgba(0, 0, 0, 0.5); }
.fv-led.amber { background: var(--p-data, #c97f3a);
                box-shadow: 0 0 5px color-mix(in srgb, var(--p-data, #c97f3a) 70%, transparent),
                            inset 0 0 1px rgba(0, 0, 0, 0.5); }
.fv-led.red   { background: var(--p-alarm, #e8543f);
                box-shadow: 0 0 6px color-mix(in srgb, var(--p-alarm, #e8543f) 80%, transparent),
                            inset 0 0 1px rgba(0, 0, 0, 0.5);
                animation: fv-led-pulse 1s ease-in-out infinite; }
.fv-led.dim   { background: var(--p-dim, #555); box-shadow: none; opacity: 0.5; }
@keyframes fv-led-pulse {
  0%, 100% { box-shadow: 0 0 6px color-mix(in srgb, var(--p-alarm, #e8543f) 80%, transparent),
                          inset 0 0 1px rgba(0, 0, 0, 0.5); }
  50%      { box-shadow: 0 0 2px color-mix(in srgb, var(--p-alarm, #e8543f) 40%, transparent),
                          inset 0 0 1px rgba(0, 0, 0, 0.5); }
}

/* === PILL (rounded status pill) === */

.fv-pill {
  display: inline-block;
  padding: 2px 8px;
  border: 1px solid;
  border-radius: 9px;
  font-size: 8px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-family: var(--fv-mono);
}
.fv-pill.normal { color: var(--p-text, #fff); border-color: var(--fv-rule); }
.fv-pill.info   { color: var(--p-accent, #aaa); border-color: var(--p-accent, #aaa); }
.fv-pill.warn   { color: var(--p-data, #fa6); border-color: var(--p-data, #fa6); }
.fv-pill.alarm  { color: #fff; background: var(--p-alarm, #c44); border-color: var(--p-alarm, #c44);
                  animation: fv-pill-pulse 1s ease-in-out infinite; }
@keyframes fv-pill-pulse {
  0%, 100% { background: var(--p-alarm, #c44); }
  50%      { background: color-mix(in srgb, var(--p-alarm, #c44) 55%, transparent); }
}

/* === CORNER STAMPS === */

.fv-stamp {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  font-family: var(--fv-mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.fv-stamp.tl { top:    calc(var(--fv-top-h) + 12px); left:  calc(var(--fv-col-w) + 14px); }
.fv-stamp.tr { top:    calc(var(--fv-top-h) + 12px); right: calc(var(--fv-col-w) + 14px); text-align: right; }
.fv-stamp.bl { bottom: calc(var(--fv-bot-h) + 12px); left:  calc(var(--fv-col-w) + 14px); }
.fv-stamp.br { bottom: calc(var(--fv-bot-h) + 12px); right: calc(var(--fv-col-w) + 14px); text-align: right; }

.fv-stamp .fv-st-lbl  { display: block; font-size: 8px;  color: var(--p-dim, #888); }
.fv-stamp .fv-st-code { display: block; font-size: 12px; color: var(--p-text, #fff); letter-spacing: 0.12em; }

/* === REDUCED MOTION === */

@media (prefers-reduced-motion: reduce) {
  .fv-grain, .fv-flicker, .fv-led.red, .fv-pill.alarm, .fv-gauge.alarm {
    animation: none !important;
  }
}

/* === MOBILE RESPONSIVE ===
 * Bezel + viewport hero stays dominant; mirrored gauge columns shrink,
 * then drop tertiary gauges. Edge strips shrink fonts but stay visible.
 * Goal (per user, Apr 29 2026): info-packed feel preserved on phones.
 */

@media (max-width: 768px) {
  .fv-bezel { padding: 8px; }
  .fv-bezel-label { font-size: 7px; }
  .fv-gauge-col { width: 110px; padding: 4px 6px; gap: 6px; }
  .fv-gauge-col.left { padding-right: 4px; }
  .fv-gauge-col.right { padding-left: 4px; }
  .fv-gauge { padding: 4px 6px; }
  .fv-gauge-lbl { font-size: 7px; }
  .fv-gauge-val { font-size: 11px; }
  .fv-gauge-bar { height: 4px; }
  .fv-circle-gauge { width: 44px; height: 44px; }
  .fv-meter-strip { font-size: 7px; padding: 2px 4px; }
  .fv-readout.lg { font-size: 22px; }
  .fv-readout.md { font-size: 16px; }
  .fv-readout.sm { font-size: 11px; }
  .fv-edge-top, .fv-edge-bot { font-size: 7px; padding: 0 6px; }
  .fv-edge-top .fv-et-cell, .fv-edge-bot .fv-eb-status { gap: 4px; margin-right: 8px; }
  .fv-stamp .fv-st-lbl { font-size: 7px; }
  .fv-stamp .fv-st-code { font-size: 10px; }
  .fv-pill { font-size: 7px; padding: 1px 5px; }
}

@media (max-width: 480px) {
  .fv-gauge-col { width: 80px; padding: 3px 4px; gap: 4px; }
  .fv-gauge-col.left .fv-gauge:nth-child(n+5) { display: none; }
  .fv-gauge-col.right .fv-gauge:nth-child(n+5) { display: none; }
  .fv-gauge-lbl { font-size: 6.5px; }
  .fv-gauge-val { font-size: 10px; }
  .fv-circle-gauge { width: 36px; height: 36px; }
  .fv-readout.lg { font-size: 18px; }
  .fv-edge-top { font-size: 6.5px; padding: 0 4px; }
  .fv-edge-top .fv-et-cell:nth-child(n+4) { display: none; }
  .fv-edge-bot { font-size: 6.5px; padding: 0 4px; }
  .fv-stamp.tl, .fv-stamp.tr, .fv-stamp.bl, .fv-stamp.br { transform: scale(0.72); transform-origin: top left; }
}
