/* ==========================================================================
   WATCHFLOOR · The Floor · alive design system (ported from
   docs/situation-room-prototype.html, the design source of truth)

   ANIMATION INVENTORY (every entry justified, or it gets cut)
   boot stagger ......... panels rise 14px with per-panel --i delay, once per
                          session: orients the eye to the layout hierarchy
                          (transform/opacity transitions)
   label scramble ....... boot only, JS-driven textContent on [data-scramble]:
                          signals "machine assembling", eyebrows and callsigns
                          only (no CSS keyframes, listed for completeness)
   count-up ............. boot only, JS rAF on threat and tension numbers:
                          draws the eye to the key figures as they arrive
                          (no CSS keyframes, listed for completeness)
   tension pulse ........ breathe: masthead glow whose amplitude and period
                          derive from --tension, encodes the world tension
                          index (opacity/transform)
   voice cursor blink ... cursorblink: encodes "the desk is typing", steps(1)
                          opacity on the machine-voice cursor
   voice rotation ....... JS textContent typing of the prioritized rotation
                          (edition anchor in serif, situation deltas, ops
                          texture), per-line dwell scaled to length: the desk
                          speaking its own state; instant under reduced motion
                          (no CSS keyframes, listed for completeness)
   live dot blink ....... blinkdot: encodes live vs archive state in the
                          theater panel header (opacity)
   scan beam ............ JS rAF translate of the vertical scanline across the
                          flat map, 14s loop, soft trail on its west side:
                          encodes the desk re-reading the board west to east
                          and paints each situation as it crosses (transform
                          only; replaces the retired decorative radar sweep)
   paint and hold ....... dots brighten from dim slate to phase colour and
                          labels appear as the beam crosses, persisting until
                          the pass wraps, then fading ~400ms: encodes which
                          situations the current pass has re-read; the board
                          is permanently painted under reduced motion
                          (opacity, plus SVG fill/r per the prototype's dot
                          transitions)
   arc dash flow ........ arcflow: relation arcs stroke-dashoffset, encodes
                          coupling between situations (SVG stroke paint,
                          per the prototype)
   sparkline draw ....... sparkdraw: boot only, stroke-dashoffset 1 to 0 over
                          pathLength 1, presents each trajectory as arriving
                          data (SVG stroke paint, per the spec and prototype)
   ripple ............... rip: globe dot ring on a phase change, encodes a new
                          event landing (SVG r/opacity, per the prototype)
   focus ring ........... focusring: one fading ring around a card, encodes
                          arrival from a Brief item onto that situation, plays
                          once per arrival (opacity/transform)
   the drop ............. view-transition root cross-fade, 450ms: encodes the
                          register change between the Brief and the Floor
                          (browser-composited, opacity)
   brief heartbeat ...... briefbeat: low-amplitude glow on the Brief register
                          affordance, period 3.5s, coloured by the most severe
                          live phase: invites the second register, stops for
                          the session on first use (box-shadow glow only)

   Everything else is transform/opacity. prefers-reduced-motion disables
   every entry above and the page renders complete, calm, fully functional.
   ========================================================================== */

:root {
  --void:#05070C; --void2:#090D16;
  --glass:rgba(255,255,255,.04); --hair:rgba(120,180,255,.14);
  --txt:#E8EDF6; --txt2:#8B97AC; --txt3:#525E72;
  --cyan:#67E8F9; --verm:#D63A1E;
  --c-watch:#67E8F9; --c-dev:#FFD23D; --c-elev:#FF8A3D;
  --c-crit:#FF4D4D; --c-deesc:#4DE6A8; --c-res:#8A8A8A;
  --disp:'Archivo',sans-serif; --body:'Instrument Sans',sans-serif; --mono:'JetBrains Mono',monospace;
  --tension:.5;
  --beat:#67E8F9;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{background:var(--void);color:var(--txt);font-family:var(--body);overflow-x:hidden}
body{min-height:100vh;min-height:100dvh;padding-bottom:96px}

/* void: grid + vignette, parallax layer */
.bg{position:fixed;inset:-40px;z-index:0;pointer-events:none;
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(103,232,249, calc(var(--tension) * .07)), transparent 60%),
    repeating-linear-gradient(0deg, rgba(120,180,255,.035) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(90deg, rgba(120,180,255,.035) 0 1px, transparent 1px 56px),
    var(--void);
  transition:transform .3s ease-out;}
.bg::after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at 50% 30%, transparent 40%, rgba(0,0,0,.55))}

.wrap{position:relative;z-index:1;max-width:1240px;margin:0 auto;padding:20px 22px}

/* masthead */
.mast{display:flex;align-items:center;gap:18px;padding:10px 2px 16px;border-bottom:1px solid var(--hair);position:relative}
.mast .mark{width:10px;height:10px;background:var(--verm);flex:0 0 auto}
.mast h1{font-family:var(--disp);font-stretch:125%;font-weight:800;font-size:17px;letter-spacing:.34em;text-transform:uppercase}
.mast .sub{font-family:var(--mono);font-size:9px;letter-spacing:.18em;color:var(--txt3);text-transform:uppercase}
.mast .clock{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--txt2);letter-spacing:.1em;min-width:128px;text-align:right;font-variant-numeric:tabular-nums}
.tension{display:flex;align-items:center;gap:10px;font-family:var(--mono);font-size:9px;letter-spacing:.16em;color:var(--txt2)}
.tension .tval{font-size:15px;font-weight:700;color:var(--txt);position:relative;display:inline-block;min-width:26px;text-align:center;font-variant-numeric:tabular-nums}
.tension .tval::after{content:"";position:absolute;inset:-14px -18px;border-radius:50%;
  background:radial-gradient(circle, rgba(103,232,249,.28), transparent 70%);
  animation:breathe calc(9s - var(--tension) * 5s) ease-in-out infinite;z-index:-1}
@keyframes breathe{0%,100%{opacity:calc(.25 + var(--tension)*.2);transform:scale(.9)}50%{opacity:calc(.55 + var(--tension)*.45);transform:scale(1.15)}}

/* machine voice: a prioritized rotation in three registers. The fixed
   two-line reserve at every width is the scroll-jitter fix: inviolable. */
.voice{display:flex;gap:10px;align-items:flex-start;font-family:var(--mono);font-size:10.5px;color:var(--cyan);
  padding:10px 2px;letter-spacing:.04em;height:56px;min-height:56px;overflow:hidden}
.voice::before{content:"▮";animation:cursorblink 1.1s steps(1) infinite;font-size:9px;line-height:16px}
@keyframes cursorblink{50%{opacity:0}}
.voice .vts{color:var(--txt3);white-space:nowrap}
.voice .vts .vtag{color:var(--verm);font-weight:700;letter-spacing:.14em}
.voice .vts .arr-up{color:var(--c-elev);font-weight:700}
.voice .vts .arr-down{color:var(--c-deesc);font-weight:700}
.voice #vline{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.voice.v-anchor{cursor:pointer}
.voice.v-anchor #vline{font-family:'Fraunces',Georgia,serif;font-style:italic;font-weight:500;
  font-size:13.5px;line-height:1.3;letter-spacing:0;color:var(--txt)}
@media (max-width:768px){
  /* per the mock: the vermillion tag sits on its own line above the
     anchor text; the text takes the remaining line of the fixed
     two-line reserve */
  .voice.v-anchor{flex-wrap:wrap;gap:2px 10px}
  .voice.v-anchor .vts{flex-basis:calc(100% - 19px)}
  .voice.v-anchor #vline{-webkit-line-clamp:1;flex-basis:100%;line-height:1.2}
}

/* layout */
.grid{display:grid;grid-template-columns:430px 1fr;gap:14px;margin-top:8px}
.panel{background:var(--glass);border:1px solid var(--hair);border-radius:10px;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);overflow:hidden;position:relative}
.panel .phead{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--hair);
  font-family:var(--mono);font-size:9px;letter-spacing:.2em;color:var(--txt3);text-transform:uppercase}
.phead .live{margin-left:auto;display:flex;align-items:center;gap:6px;color:var(--cyan)}
.phead .live i{width:6px;height:6px;border-radius:50%;background:var(--cyan);animation:blinkdot 1.8s ease infinite}
@keyframes blinkdot{50%{opacity:.15}}

/* flat scan map: abstract dotted landmass, no borders, no graticule */
.mapwrap{padding:14px}
.mapwrap svg{width:100%;height:auto;display:block}
.landdot{fill:rgba(120,160,220,.16)}
.maplabel{pointer-events:none;transition:opacity .35s ease}
.maplabel .mlname{font-family:var(--mono);font-size:10px;fill:#8B97AC;
  letter-spacing:.12em;text-transform:uppercase}
.maplabel .mlthreat{font-family:var(--mono);font-size:10px;font-weight:700}
.mapdot-hit{fill:transparent;cursor:pointer;pointer-events:all}
.gdot{transition:r .4s, fill .4s}
.garc{fill:none;stroke-width:1;stroke-dasharray:4 7;animation:arcflow 1.6s linear infinite;opacity:.6}
@keyframes arcflow{to{stroke-dashoffset:-11}}
.ripple{fill:none;stroke-width:1.5;opacity:0;pointer-events:none}
.ripple.go{animation:rip 1.2s ease-out}
@keyframes rip{0%{opacity:.9;r:5}100%{opacity:0;r:26}}

/* situation cards */
.cards{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;align-content:start;min-height:380px}
.card{background:var(--glass);border:1px solid var(--hair);border-left:3px solid var(--pc,#8A8A8A);
  border-radius:10px;padding:14px 16px;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  position:relative;transition:border-color .5s, box-shadow .5s}
.card.crit{box-shadow:0 0 26px -8px rgba(255,77,77,.35)}
.card .ceyebrow{display:flex;justify-content:space-between;font-family:var(--mono);font-size:8.5px;
  letter-spacing:.18em;text-transform:uppercase;color:var(--txt3);margin-bottom:8px}
.card h3{font-family:var(--disp);font-stretch:118%;font-weight:750;font-size:15px;letter-spacing:.05em;text-transform:uppercase;line-height:1.2}
.card .crow{display:flex;align-items:flex-end;gap:14px;margin:10px 0 8px}
.card .threat{font-family:var(--mono);font-weight:700;font-size:30px;line-height:1;color:var(--pc);font-variant-numeric:tabular-nums}
.card .threat small{display:block;font-size:8px;letter-spacing:.18em;color:var(--txt3);font-weight:400;margin-top:3px}
.card .phase{font-family:var(--mono);font-size:9px;letter-spacing:.14em;color:var(--pc);
  border:1px solid var(--pc);border-radius:3px;padding:3px 8px;margin-bottom:4px}
.card .spark{margin-left:auto;width:120px;height:38px}
.spark polyline{fill:none;stroke:var(--pc);stroke-width:1.5;transition:stroke .5s}
.booting .spark polyline{stroke-dasharray:1;stroke-dashoffset:1}
.boot-draw .spark polyline{stroke-dasharray:1;animation:sparkdraw 1.2s ease-out forwards}
@keyframes sparkdraw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
.spark .scursor{fill:var(--pc)}
.card .csum{font-size:11.5px;color:var(--txt2);line-height:1.5;min-height:33px}
.card .cfoot{display:flex;gap:14px;margin-top:10px;font-family:var(--mono);font-size:8.5px;letter-spacing:.1em;color:var(--txt3);text-transform:uppercase}
.card .cfoot b{color:var(--txt2);font-weight:500}

/* focus ring: arrival from a Brief item */
.card{--pc:#8A8A8A}
.card.focus::after{content:"";position:absolute;inset:-3px;border:2px solid var(--pc);
  border-radius:12px;pointer-events:none;opacity:0;animation:focusring 2.4s ease-out}
@keyframes focusring{0%{opacity:0;transform:scale(1.04)}12%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(1)}}

/* archive rail: DORMANT situations live here, not the main grid */
.archiverail{margin-top:14px;border:1px solid var(--hair);border-radius:10px;background:var(--glass);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.archiverail summary{display:flex;gap:10px;align-items:center;cursor:pointer;list-style:none;
  padding:12px 16px;font-family:var(--mono);font-size:9px;letter-spacing:.2em;color:var(--txt3);text-transform:uppercase}
.archiverail summary::before{content:"▸";color:var(--txt3);font-size:9px}
.archiverail[open] summary::before{content:"▾"}
.archiverail .acount{color:var(--txt2)}
.archiverail .acards{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;padding:0 14px 14px}
.archiverail .card{padding:10px 14px}
.archiverail .card .csum,.archiverail .card .cfoot{display:none}
.archiverail .card .threat{font-size:20px}
.archiverail .card .spark{width:90px;height:30px}
@media (max-width:640px){.archiverail .acards{grid-template-columns:1fr}}

/* brief register jump + return affordance: one masthead button (always
   visible, compact on narrow screens) plus a copy in the fixed dock so
   the register switch is reachable mid-scroll */
.briefjump{font-family:var(--mono);font-size:9px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--txt2);text-decoration:none;border:1px solid var(--hair);border-radius:4px;padding:5px 9px;white-space:nowrap}
.briefjump:hover{color:var(--cyan);border-color:rgba(103,232,249,.4)}
.briefjump.beat{animation:briefbeat 3.5s ease-in-out infinite}
@keyframes briefbeat{0%,100%{box-shadow:0 0 0 0 transparent}50%{box-shadow:0 0 11px -3px var(--beat)}}
@media (max-width:640px){
  .mast .briefjump{font-size:8px;letter-spacing:.08em;padding:4px 6px}
}

/* the drop: cross-document view transition between the registers */
@view-transition{navigation:auto}
::view-transition-old(root),::view-transition-new(root){
  animation-duration:.45s;animation-timing-function:cubic-bezier(.4,0,.2,1)}

/* phase color hooks */
.p-WATCH{--pc:var(--c-watch)} .p-DEVELOPING{--pc:var(--c-dev)} .p-ELEVATED{--pc:var(--c-elev)}
.p-CRITICAL{--pc:var(--c-crit)} .p-DE_ESCALATING{--pc:var(--c-deesc)} .p-RESOLVED{--pc:var(--c-res)}
.p-DORMANT{--pc:var(--c-res)}

/* scrubber dock */
.dock{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:5;width:min(960px, calc(100% - 28px));
  background:rgba(9,13,22,.78);border:1px solid var(--hair);border-radius:12px;
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  padding:12px 18px;box-shadow:0 12px 40px rgba(0,0,0,.5)}
.dock .drow{display:flex;align-items:center;gap:14px}
.dock .dlabel{font-family:var(--mono);font-size:9px;letter-spacing:.2em;color:var(--txt3);text-transform:uppercase;white-space:nowrap}
.dock input[type=range]{flex:1;-webkit-appearance:none;appearance:none;height:3px;border-radius:2px;
  background:linear-gradient(90deg, var(--c-deesc), var(--c-dev), var(--c-elev), var(--c-crit) 70%, var(--cyan));opacity:.9}
.dock input::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;border-radius:50%;
  background:var(--cyan);border:2px solid var(--void);box-shadow:0 0 12px rgba(103,232,249,.8);cursor:grab}
.dock input::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
  background:var(--cyan);border:2px solid var(--void);box-shadow:0 0 12px rgba(103,232,249,.8);cursor:grab}
.dock .dbtn{font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--cyan);background:rgba(103,232,249,.08);border:1px solid rgba(103,232,249,.4);
  border-radius:5px;padding:6px 12px;cursor:pointer}
.dock .dbtn:hover{background:rgba(103,232,249,.16)}
.dock .dchip{display:none;font-family:var(--mono);font-size:9px;letter-spacing:.12em;color:var(--c-elev);white-space:nowrap;cursor:pointer;margin-top:6px}
.dock.scrubbed .dchip{display:block}
.dock .ddate{font-family:var(--mono);font-size:11px;color:var(--txt);min-width:86px;text-align:right;font-variant-numeric:tabular-nums}

/* boot choreography */
.booting .panel,.booting .card,.booting .dock,.booting .voice{opacity:0;transform:translateY(14px)}
.panel,.card,.dock,.voice{transition:opacity .55s ease, transform .55s ease;transition-delay:calc(var(--i,0) * 60ms)}
.no-boot .panel,.no-boot .card,.no-boot .dock,.no-boot .voice{transition:none}

footer{position:relative;z-index:1;text-align:center;font-family:var(--mono);font-size:9px;
  letter-spacing:.12em;color:var(--txt3);padding:26px 0 8px}
footer .footlink{color:var(--txt2);text-decoration:none;text-transform:uppercase;
  border:1px solid var(--hair);border-radius:4px;padding:3px 7px}
footer .footlink:hover{color:var(--cyan);border-color:rgba(103,232,249,.4)}
.nojs{position:relative;z-index:1;text-align:center;font-family:var(--mono);font-size:11px;color:var(--txt2);padding:40px 20px}

@media (max-width:980px){.grid{grid-template-columns:1fr}}
@media (max-width:640px){
  .cards{grid-template-columns:1fr}.mast h1{font-size:15px;letter-spacing:.14em}.tension{display:none}
  /* the scrub dock carries the window label; the per-card D-30 tag is
     redundant at this width and wraps the eyebrow */
  .card .ceyebrow span:last-child{display:none}
  .card .ceyebrow span:first-child{white-space:normal}
  /* keep the masthead row inside the viewport: the title block shrinks
     (sub ellipsizes) and the clock gives up its reserved width */
  .mast{gap:10px}
  .mast > div:nth-child(2){flex:1 1 auto;min-width:0}
  .mast .sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mast .clock{min-width:0;font-size:10px}
  .dock{padding:10px 12px}
  .dock .dlabel{display:none}
  .dock .drow{gap:10px}
  .dock input[type=range]{min-width:0}
  .dock .ddate{min-width:0;font-size:10px}
  .dock .dbtn{padding:5px 8px}
}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important;transition:none !important}
  .booting .panel,.booting .card,.booting .dock,.booting .voice{opacity:1;transform:none}
  .booting .spark polyline{stroke-dasharray:none;stroke-dashoffset:0}
  ::view-transition-group(*),::view-transition-image-pair(*),
  ::view-transition-old(*),::view-transition-new(*){animation:none !important}
}
