/* H.I.P.S. surveillance: rank-based cameras and the shared field monitor. */

/* min-width:0 is the screen lock: without it the panel (a grid item) refuses
   to shrink below the strip's full content width, the whole page overflows
   sideways, and the strip's own scrolling never engages. */
.battlePanel.surv-wall{position:relative;display:block;height:auto;min-height:0;min-width:0;padding:0;border:0}
.battlePanel.surv-wall .revealCard,
.battlePanel.surv-wall .panelIdle{display:none}

.surv-cluster{display:none;width:100%}
/* Batcomputer wall: one horizontal strip you swipe through, no vertical
   stack. Windows are different sizes, staggered, and layered over each
   other; the next window peeking in from the right edge is what says
   there is more — no labels, no directions. */
.battlePanel.surv-wall .surv-cluster{display:flex;overflow-x:auto;align-items:flex-start;min-width:0;padding:6px 2px 16px;scroll-snap-type:none;touch-action:pan-x pan-y;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.battlePanel.surv-wall .surv-cluster::-webkit-scrollbar{display:none}
/* The strip remains a native horizontal scroller in every state. touch-action is pan-x pan-y (bradley's order 2026-11-05): sideways swipes scroll the strip, vertical swipes pass through to the page so nobody gets stuck on the center screen. NEVER pan-y alone: pan-y kills horizontal finger scroll on iOS (2026-10-26, back again 2026-11-01). */

/* Window chrome, Aven's language: title bar, three dots, feed name. */
.surv-win{position:relative;flex:0 0 auto;background:#06100d;box-shadow:0 8px 20px rgba(0,0,0,.35)}
/* Visual order flanks the dossier: two cameras left, two right, so the wall
   scrolls both ways from the first view instead of favoring one side.
   (nth-of-type still counts DOM order: dossier is 1st, cameras 2nd-5th.)
   Overlaps stay at or under the OSD inset so no label, time, or mark is
   ever covered — only image edges and padding tuck under. */
.surv-dossier{z-index:1;order:3;width:350px;margin-left:-12px;margin-top:10px;transform:rotate(-.3deg);border:1px solid var(--line)}
.surv-cam:nth-of-type(2){z-index:2;order:1;width:250px;transform:rotate(.25deg)}
.surv-cam:nth-of-type(3){z-index:3;order:2;width:290px;margin-left:-16px;margin-top:16px;transform:rotate(-.4deg)}
.surv-cam:nth-of-type(4){z-index:4;order:4;width:230px;margin-left:-12px;margin-top:8px;transform:rotate(.3deg)}
.surv-cam:nth-of-type(5){z-index:5;order:5;width:280px;margin-left:-16px;margin-top:22px;transform:rotate(-.2deg)}
.surv-bar{display:flex;align-items:center;gap:5px;padding:5px 8px;font:600 8px var(--mono);letter-spacing:.14em;color:var(--muted);text-transform:uppercase}
/* Dossier header is the system itself, not a file name: H.I.P.S. in
   wide-tracked, brighter mono — Pentagon terminal, not a label. */
.surv-dossier .surv-bar-name{letter-spacing:.32em;color:#d5ded3;font-weight:700}
/* Window dots are status LEDs in the three moon colors, left to right:
   lavender, soft rose-gold, icy blue. Slow traveling light, one lit at a
   time — status, not alarm. Opacity only: a glowing shadow would repaint
   every frame on a phone, and the wall must stay light. */
.surv-bar i{display:block;width:6px;height:6px;border-radius:50%;opacity:.45;animation:surv-led 3s linear infinite}
.surv-bar i:nth-of-type(1){background:#c9a7eb;animation-delay:0s}
.surv-bar i:nth-of-type(2){background:#e8b4a0;animation-delay:1s}
.surv-bar i:nth-of-type(3){background:#a8d4f0;animation-delay:2s}
@keyframes surv-led{0%,25%{opacity:1}33%,100%{opacity:.45}}

/* Dossier window: the face sits bare beside the info (same 88px size), no
   inner box — the dossier window itself is the one slight box, because it
   holds two things. Camera windows float borderless, like Aven's
   transmissions: title bar + picture + shadow, no outline. The wider
   dossier window reads rectangular, like the TV monitors, instead of square. */
.surv-dossier-body{padding:10px 10px 14px}
.surv-dossier-row{display:flex;gap:8px;align-items:flex-start}
.surv-face{width:88px;flex:0 0 88px;aspect-ratio:3/4;object-fit:contain;background:#020605}
/* Left column: face on top, LAST 5 strip stacked in the void beneath it.
   The column is exactly the face's width, so the dossier box never widens;
   the strip only fills space the tall right readout already leaves. */
.surv-face-col{width:88px;flex:0 0 88px;display:flex;flex-direction:column}
.surv-last5{margin-top:9px;font:400 7.5px/1.45 var(--mono);letter-spacing:.06em}
.surv-last5[hidden]{display:none}
.surv-last5-head{display:flex;align-items:baseline;gap:6px;margin-bottom:4px}
.surv-last5-title{font-size:7px;letter-spacing:.24em;color:#9db8a2}
.surv-last5-record{font-size:7.5px;letter-spacing:.1em;color:#aebba9}
.surv-last5-row{display:flex;align-items:center;gap:5px;white-space:nowrap;margin-top:3px}
.surv-last5-chip{flex:0 0 11px;text-align:center;font-size:7.5px;font-weight:700;line-height:1.45;border:1px solid}
.surv-last5-w{color:#7ee2a8;border-color:rgba(99,214,138,.55)}
.surv-last5-l{color:#ff8d84;border-color:rgba(255,102,92,.55)}
.surv-last5-unit{font-size:5.5px;letter-spacing:.02em;color:#8fa393}
.surv-last5-date{font-size:5.5px;letter-spacing:.02em;color:#c8beb0}
/* Face pictures fit whole, never cropped: a tall or wide portrait sits
   smaller in the box on its dark background, chin and arms intact, most
   of the shot visible. Camera shots stay object-fit:cover — clipping
   those is fine, faces are the exception. */
.surv-id{min-width:0;flex:1}
.surv-name{display:block;font-size:25px;line-height:1.05;letter-spacing:.08em;color:#ff665c}
.surv-pos{display:block;margin-top:8px;font:9px var(--mono);letter-spacing:.14em;color:var(--green)}
.surv-state{display:block;margin:0;padding:0;border:0;font:400 11px/1.5 var(--mono);letter-spacing:.1em;color:#d5ded3;text-align:center;overflow-wrap:anywhere}
/* Points readout beside the current ranking status. */
.surv-spec{display:block;font:400 10px/1.7 var(--mono);letter-spacing:.02em;color:#c9b6ec}
.surv-spec:empty{display:none}
/* Camera switcher: a matrix-selector row in the dossier footer. Numbered
   buttons, one lit = the centered camera. Flat, mono, understated. */
.surv-nav{display:flex;gap:4px;padding:6px 7px 9px}.surv-cam .surv-nav{position:relative;z-index:5;background:#06100d}
.surv-nav-btn{flex:1;appearance:none;background:transparent;border:1px solid var(--line);padding:10px 2px;font:600 9px var(--mono);letter-spacing:.04em;color:var(--muted);cursor:pointer;-webkit-tap-highlight-color:transparent}
.surv-nav-btn:active{transform:scale(.97)}
.surv-nav-btn:focus-visible{outline:1px solid var(--line);outline-offset:1px}

/* Camera windows. */
.surv-feed{position:relative;aspect-ratio:16/10;overflow:hidden;background:#020605}
.surv-feed > img.surv-shot{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.surv-feed::after{content:'';position:absolute;inset:0;pointer-events:none;box-shadow:inset 0 0 42px rgba(0,0,0,.6)}

/* Persistent feed texture: faint grain + scanlines, so the picture never
   reads as a pure clean render. The arrival burst below is the strong hit. */
.surv-grain{position:absolute;inset:0;pointer-events:none;opacity:.12;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E"),
    repeating-linear-gradient(to bottom,rgba(0,0,0,.35) 0 1px,transparent 1px 3px)}
.surv-burst{position:absolute;inset:0;pointer-events:none;opacity:0;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E")}

/* Player switch: dim the dossier window and the camera photos while the
   contents swap, then brighten back through the tune. Opacity only, so it
   never fights the tune's blur/scale. */
.surv-cluster.surv-fading .surv-dossier-body,
.surv-cluster.surv-fading .surv-shot{opacity:.2}
.surv-dossier-body,
.surv-shot{transition:opacity .3s ease}

/* Arrival: static burst flickers out while the lens pulls focus, one camera
   after another, like each feed locking on in turn. */
.surv-cluster.tuning .surv-shot{animation:surv-tune 1s ease-out forwards}
.surv-cluster.tuning .surv-burst{animation:surv-burst 1s steps(5) forwards}
.surv-cluster.tuning .surv-cam:nth-of-type(2) .surv-shot,
.surv-cluster.tuning .surv-cam:nth-of-type(2) .surv-burst{animation-delay:0s}
.surv-cluster.tuning .surv-cam:nth-of-type(3) .surv-shot,
.surv-cluster.tuning .surv-cam:nth-of-type(3) .surv-burst{animation-delay:.15s}
.surv-cluster.tuning .surv-cam:nth-of-type(4) .surv-shot,
.surv-cluster.tuning .surv-cam:nth-of-type(4) .surv-burst{animation-delay:.3s}
.surv-cluster.tuning .surv-cam:nth-of-type(5) .surv-shot,
.surv-cluster.tuning .surv-cam:nth-of-type(5) .surv-burst{animation-delay:.45s}
@keyframes surv-tune{
  0%{filter:blur(10px) brightness(1.3) saturate(.6);transform:scale(1.04)}
  60%{filter:blur(2px) brightness(1.1) saturate(.9);transform:scale(1.01)}
  100%{filter:blur(0) brightness(1) saturate(1);transform:scale(1)}}
@keyframes surv-burst{
  0%{opacity:.9}20%{opacity:.35}40%{opacity:.8}60%{opacity:.25}80%{opacity:.5}100%{opacity:0}}

/* OSD: what the camera itself burns into its picture. */
.surv-osd{position:absolute;z-index:2;font:600 8px var(--mono);letter-spacing:.12em;color:#d6dfd3;text-shadow:0 1px 2px #000,0 0 4px #000;pointer-events:none}
.surv-osd-tl{top:6px;left:7px}
.surv-osd-tr{top:6px;right:20px;display:flex;align-items:center;gap:4px}
.surv-rec{display:inline-block;width:6px;height:6px;border-radius:50%;background:#ff3b30;animation:surv-rec 1.2s steps(1) infinite}
@keyframes surv-rec{0%,49%{opacity:1}50%,100%{opacity:.15}}
.surv-mark{position:absolute;z-index:2;right:20px;bottom:6px;width:34px;opacity:.85;pointer-events:none;filter:drop-shadow(0 1px 2px #000)}

@media(max-width:760px){
  .surv-name{font-size:21px}
  .surv-pos{font-size:8px}
}
@media(prefers-reduced-motion:reduce){
  .surv-cluster.tuning .surv-shot,
  .surv-cluster.tuning .surv-burst,
  .surv-static,
  .surv-bar i,
  .surv-rec{animation:none}
  .surv-bar i{opacity:.8}
  .surv-burst{display:none}
  .surv-shot{filter:none}
  .surv-dossier,
  .surv-shot{transition:none}
  .surv-hold-ground,
  .surv-cluster.surv-dormant .surv-shot{animation:none}
  .surv-first-open .surv-bounce-logo{left:50%;top:50%;transform:translate(-50%,-50%)}
}

/* Hold screen: the H.I.P.S. mark, full-window, while the wall is dormant
   (no subject yet, or the ping sweep between subjects). It covers the
   whole window, chrome included — a standby card, not a label. */
.surv-hold{position:absolute;inset:0;z-index:1;display:none;align-items:center;justify-content:center;background:transparent;overflow:hidden;pointer-events:none}
.surv-cluster.surv-dormant .surv-hold{display:flex;background:#14201b url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");animation:surv-static-shift .18s steps(3) infinite}
.surv-cluster.surv-dormant .surv-hold>img{display:none}
@media(prefers-reduced-motion:reduce){.surv-cluster.surv-dormant .surv-hold{animation:none}}
/* Standby redesign: empty ground drifting + Raven on watch. Ground shots
   cover their windows; the Raven sits small in the dossier corner, never
   the centerpiece. The hold sits under the OSD, so camera chrome stays. */
.surv-hold-ground{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.surv-hold-raven{position:absolute;right:10px;bottom:10px;width:30%;aspect-ratio:1;object-fit:cover;opacity:.9;box-shadow:0 2px 10px rgba(0,0,0,.6)}
.surv-hold-small{position:absolute;width:38%;aspect-ratio:4/3;object-fit:cover;box-shadow:0 2px 12px rgba(0,0,0,.65)}
.surv-hold-small-a{left:8px;top:8px;transform:rotate(-3deg)}
.surv-hold-small-b{right:8px;bottom:8px;transform:rotate(2.5deg)}
.surv-dossier .surv-hold-small-b{top:8px;bottom:auto}
/* First-open attract mode: one large HIPS logo bouncing DVD-style
   around the panel until the first girl shows. Holds hide under it. */
.surv-bounce-logo{position:absolute;left:0;top:0;z-index:6;width:36%;display:none;pointer-events:none;filter:drop-shadow(0 0 18px rgba(88,192,227,.35))}
.surv-first-open .surv-bounce-logo{display:block}
.surv-first-open .surv-cluster.surv-dormant .surv-hold{display:none}
.surv-first-open .surv-cluster.surv-dormant .surv-dossier .surv-hold{display:flex;background:#06100d;animation:none}

@keyframes surv-hold-drift{from{transform:scale(1) translate(0,0)}to{transform:scale(1.08) translate(-1.5%,1%)}}
.surv-hold-mark{display:none}
.surv-cam .surv-hold-mark{width:84px}
/* Cameras-down card for zones with no photos yet: the technical card —
   mark + CAMERAS DOWN + zone name over the grain, OSD still on top.
   Overlays never block strip swiping. */
.surv-down{position:absolute;inset:0;z-index:1;display:none;flex-direction:column;align-items:center;justify-content:center;gap:10px;background:rgba(2,6,5,.88);pointer-events:none}
.surv-cam.surv-no-signal .surv-down{display:flex}
.surv-down-mark{width:64px;opacity:.85;filter:drop-shadow(0 0 10px rgba(88,192,227,.22))}
.surv-down b{font:600 11px var(--mono);letter-spacing:.22em;color:#d5ded3}
.surv-down-zone{font:400 9px var(--mono);letter-spacing:.18em;color:var(--muted)}
.surv-down-zone:empty{display:none}
.surv-static{position:absolute;inset:0;z-index:1;display:none;pointer-events:none;opacity:.55;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E")}
.surv-cam.surv-no-signal .surv-static{display:block;animation:surv-static-shift .9s steps(3) infinite}
.surv-cam.surv-no-signal .surv-shot{display:none}
@keyframes surv-static-shift{0%{background-position:0 0}33%{background-position:40px 20px}66%{background-position:10px 34px}100%{background-position:0 0}}
/* Dossier face placeholder: same grain, no picture. */
.surv-face-static{display:none;width:88px;flex:0 0 88px;aspect-ratio:3/4;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");opacity:.55}
.surv-dossier.surv-no-face .surv-face-static{display:block}
.surv-dossier.surv-no-face .surv-face{display:none}




/* Seamless edge, Lady's World style: no fade into the page background,
   no panel gap. Cards stay solid to the edge, and on phones the strip
   bleeds past the shell padding to the screen edge, so the next window
   peeks solid at the corner instead of being cut off by the wallpaper.
   The screen edge itself is the only cut, like a full-screen room. */
@media(max-width:760px){
  .battlePanel.surv-wall .surv-cluster{margin-left:-12px;margin-right:-12px}
}


/* Field monitor: restrained heraldic insignia and ranking telemetry. */
.surv-field-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:8px;align-items:center;min-height:108px;margin-top:8px;border-top:1px solid var(--line);background:radial-gradient(ellipse at 90% 50%,rgba(164,182,124,.045),transparent 65%)}
.surv-has-sigil .surv-field-grid{grid-template-columns:minmax(0,1fr) 76px}
.surv-field-readout{min-width:0;padding-top:8px}
.surv-field-readout .surv-spec-points{margin-top:7px;font-variant-numeric:tabular-nums}
.surv-insignia{position:relative;margin:0;min-width:0;align-self:stretch;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:7px 2px 4px;border-left:1px solid rgba(164,182,124,.13)}
.surv-insignia[hidden]{display:none}
.surv-insignia::before{content:'';position:absolute;inset:5px 6px 15px;background:linear-gradient(145deg,rgba(164,182,124,.04),transparent);clip-path:polygon(0 0,100% 0,100% 70%,50% 100%,0 70%);pointer-events:none}
.surv-insignia img{position:relative;width:66px;height:78px;object-fit:contain;opacity:.78;mix-blend-mode:screen;filter:drop-shadow(0 0 4px rgba(167,114,220,.14))}
.surv-insignia figcaption{font:500 6px var(--mono);letter-spacing:.14em;color:#9caa9f;margin-top:3px;text-align:center}
/* One live trace carries the motion; the split crystal is a still direction cue. */
.surv-signal{margin-top:12px;color:#38C995}
.surv-signal[data-band=rising]{color:#C58AFF}
.surv-signal[data-band=falling]{color:#E3A0AA}
.surv-signal[data-band=unknown]{color:#718078}
.surv-signal-label{display:grid;grid-template-columns:minmax(0,1fr);gap:6px;text-align:center;align-items:center;font:600 8px var(--mono);letter-spacing:.12em;color:#87998e}
.surv-movement{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;min-width:0;font:600 10px/1.4 var(--mono);letter-spacing:.08em;color:currentColor;overflow-wrap:anywhere}
.surv-movement-mark{position:relative;display:inline-block;width:14px;height:20px;flex:none}
.surv-movement-mark i{position:absolute;left:0;width:100%;height:9px;background:#38C995;opacity:.18}
.surv-movement-mark i:first-child{top:0;clip-path:polygon(50% 0,100% 100%,0 100%)}
.surv-movement-mark i:last-child{bottom:0;clip-path:polygon(0 0,100% 0,50% 100%)}
.surv-signal[data-band=rising] .surv-movement-mark i:first-child{background:#C58AFF;opacity:1}
.surv-signal[data-band=falling] .surv-movement-mark i:last-child{background:#E3A0AA;opacity:1}
.surv-signal[data-band=holding] .surv-movement-mark i{opacity:.8}
.surv-signal[data-band=unknown] .surv-movement-mark{visibility:hidden}
/* A readable resting trace, soft edge trail, and crisp moving core.
   Path lengths are normalized so the trail stays behind its head in every band. */
.surv-trace{position:relative;height:48px;margin-top:6px;overflow:hidden;background:repeating-linear-gradient(0deg,transparent 0 9px,rgba(133,189,169,.065) 9px 10px),repeating-linear-gradient(90deg,transparent 0 19px,rgba(133,189,169,.045) 19px 20px)}
.surv-trace::before{content:'';position:absolute;left:0;right:0;top:50%;border-top:1px solid rgba(133,189,169,.12);pointer-events:none}
.surv-trace svg{position:relative;width:100%;height:100%;overflow:visible;color:#38C995}
.surv-trace path{fill:none;stroke:currentColor;vector-effect:non-scaling-stroke;stroke-linecap:round;stroke-linejoin:round}
.surv-trace-base{stroke-width:1.9;opacity:.72}
.surv-trace-trail{color:#C58AFF;stroke-width:5;stroke-dasharray:72 188;opacity:.25;animation:surv-rank-trail var(--signal-duration,4.2s) linear infinite}
.surv-trace-live{color:#C58AFF;stroke:currentColor;stroke-width:2.6;stroke-dasharray:32 228;animation:surv-rank-trace var(--signal-duration,4.2s) linear infinite;opacity:1}
.surv-signal[data-band=unknown] .surv-trace-live,.surv-signal[data-band=unknown] .surv-trace-trail{animation:none;opacity:0}
.surv-signal[data-band=unknown] .surv-trace-base{stroke-dasharray:3 6;opacity:.25}
@keyframes surv-rank-trace{from{stroke-dashoffset:260}to{stroke-dashoffset:0}}
@keyframes surv-rank-trail{from{stroke-dashoffset:300}to{stroke-dashoffset:40}}
.surv-cluster.surv-dormant .surv-trace-live{animation-play-state:paused}
.surv-cluster.surv-dormant .surv-trace-trail{animation-play-state:paused}
@media(prefers-reduced-motion:reduce){.surv-trace-live{animation:none;stroke-dasharray:none;opacity:.8}.surv-trace-trail{animation:none;opacity:0}}

/* Emerald pulse and purple trajectory occupy one existing monitor surface. */
.surv-trace .surv-rank-line{fill:none;stroke:#C58AFF;stroke-width:2;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.surv-rank-dot{fill:#38C995;stroke:#38C995;stroke-width:1.3;vector-effect:non-scaling-stroke}
.surv-rank-label{fill:#efdcff;font:600 6px var(--mono);stroke:#07120e;stroke-width:2;paint-order:stroke;stroke-linejoin:round}



.surv-rank-label-stem{stroke:#C58AFF;stroke-width:.55;opacity:.5;vector-effect:non-scaling-stroke}

/* Intrinsic frame sizing owns page height; only the camera strip scrolls. */
html,body{overflow:hidden}
