/* ============================================================
   INSIDE THE BLACK BOX — CHAOTIC MINIMALISM (scientific / academic)
   White (#fff) ground · royal/electric blue + black hairlines.
   A DENSE datamosh cluster explodes diagonally (top-left -> SE void).
   Signature: horizontal pixel-stretch smears, stacked status words
   with an RGB echo drag, repeated Courier echoes, 1px blueprint marks.

   The --clean dial (0..1) on <body> rationalizes the page as the user
   advances act 1 -> act 4.  --chaos = 1 - clean drives every glitch:
   datamosh intensity, smear opacity, decor opacity, scatter jitter,
   pattern density — all calm toward act 4.
   ============================================================ */

:root {
  --paper: #ffffff;
  --paper-2: #f1f3fb;
  --blue: #0a30ff;        /* royal / electric blue */
  --blue-deep: #0020c8;
  --blue-2: #1084d0;      /* win98 title gradient end */
  --navy: #000080;        /* win98 title gradient start */
  --magenta: #ff00b8;     /* rare accent only */
  --cyan: #00e5ff;
  --yellow: #f2ff00;      /* highlighter marker (intro splash) */

  /* GROUP header palette — folders named gNN_MM_Name tint their window header by group.
     1-3 are the active groups; 4-6 are pre-defined so adding groups stays scalable.
     All chosen to carry white winbar text. Add --grp-7+ here to extend further. */
  --grp-1: #0a30ff;       /* group 1 — electric blue  */
  --grp-2: #00a36c;       /* group 2 — emerald green (swapped with 3) */
  --grp-3: #ff1f8f;       /* group 3 — hot magenta  (swapped with 2) */
  --grp-4: #7a3cff;       /* group 4 — violet         */
  --grp-5: #e2641a;       /* group 5 — burnt orange   */
  --grp-6: #0a93b8;       /* group 6 — deep teal      */
  --ink: #06060c;
  --hair: #0b0b14;        /* black hairline */

  /* win95 chrome — kept thin / 1px to match blueprint line quality */
  --face: #eef0f7;
  --face-2: #f6f7fc;
  --hi: #ffffff;
  --sh: #b7bdd4;
  --dsh: #6a7193;

  --font-mono: "Courier New", "Courier", monospace;
  --font-disp: "Archivo Black", "Arial Black", sans-serif;     /* heavy slab display */
  --font-stack: "Anton", "Archivo Black", sans-serif;          /* condensed status words */
  --font-cond: "Saira Condensed", "Anton", sans-serif;         /* condensed system text */

  --ease: cubic-bezier(.2, .8, .2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }

body {
  --chaos: calc(1 - var(--clean, 0));
  --ground: #ffffff;                 /* WHITE ground */
  --deco-ink: var(--blue);
  background-color: var(--ground);
  transition: background-color .55s var(--ease), color .55s var(--ease);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 15px;
  line-height: 1.35;
  overflow: hidden;
  position: fixed;
  inset: 0;
  cursor: none;
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .1s !important; }
}
::selection { background: var(--blue); color: #fff; }

/* Act 1 sits on the electric blue (intro splash + the team / Matias slides are all blue), so the
   base ground is blue too — nothing white can ever flash through between Act-1 slide transitions. */
body[data-act="1"] { background-color: var(--blue); }

/* ---- CALM: when the RATIONALIZATION screen appears (act 3), the page STAYS on the
   clean light/white theme and the chaotic, repetitive decor switches off — so the
   screen reads as a quiet transition into calm. (Act 4 / the chat stays light too.) ---- */
/* NOTE on acts: an INDEX graph was inserted as Act 2, so the calm acts shifted:
   Act 1 splash · Act 2 index · Act 3 messy/rationalizing · Act 4 rationalized · Act 5 chat. */
/* images glide into their final grid with a gentle, floaty easing (the rationalized act) */
body[data-act="4"] .item {
  transition: transform 1.15s cubic-bezier(.22, 1, .36, 1), opacity .8s var(--ease), filter .8s var(--ease);
}
/* In the rationalized act the windows START exactly where the canvas left them (no re-settle)
   and then drift gently in place — each with its own random phase (--fp) so the whole grid
   floats softly, like the calm settling in. */
body[data-act="4"] .item .win { animation: gridfloat calc(5.5s + var(--fp, 0) * 3.5s) ease-in-out infinite; }
@keyframes gridfloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
/* the repetitive background decor disappears from Act 2 onward (index, messy canvas,
   rationalized, chat) — only the Act-1 splash keeps the textured decor. So the messy
   canvas (Act 3) sits on a completely clean white field. */
body[data-act="2"] .deco, body[data-act="3"] .deco, body[data-act="4"] .deco, body[data-act="5"] .deco { opacity: 0; }
body[data-act="2"] .fx-vignette,  body[data-act="3"] .fx-vignette,  body[data-act="4"] .fx-vignette,  body[data-act="5"] .fx-vignette,
body[data-act="2"] .fx-grain,     body[data-act="3"] .fx-grain,     body[data-act="4"] .fx-grain,     body[data-act="5"] .fx-grain,
body[data-act="2"] .fx-scanlines, body[data-act="3"] .fx-scanlines, body[data-act="4"] .fx-scanlines, body[data-act="5"] .fx-scanlines,
body[data-act="2"] .fx-rgb,       body[data-act="3"] .fx-rgb,       body[data-act="4"] .fx-rgb,       body[data-act="5"] .fx-rgb { opacity: 0; }

/* thin 1px blueprint bevels (no heavy Win98 chunk) */
.bevel-up {
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--hair);
}
.bevel-down {
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--sh);
}

/* ============================================================
   GLOBAL FX — faint halftone/dither, datamosh smear washes
   All tied to --chaos so they fade to near-zero by act 4.
   ============================================================ */
.fx { position: fixed; inset: 0; pointer-events: none; transition: opacity .5s var(--ease); }

/* ---- boot window flood: clones of the real canvas windows, in front, as snakes ---- */
/* white blurred backdrop behind popups / zoomed slides (white acts only).
   Lives inside #stage at z 250: above the messy/receding canvas (items z 1..30 / grid z 10,
   focus-receding z 1) but below the hero on top — zoomed slide (z 500), intro window (z 400),
   chat modal (z 600). #world must NOT trap items in its own context (see .world z-index: auto). */
#scrim { position: absolute; inset: 0; z-index: 250; pointer-events: none; opacity: 0; visibility: hidden;
  background: rgba(255,255,255,.82); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: opacity .6s var(--ease), visibility .6s var(--ease), background-color .9s var(--ease); }
#scrim.show { opacity: 1; visibility: visible; }
/* at the chat (act 5) the veil settles SOLID into the electric blue of Act 1 — the scene
   comes full circle, calm and saturated, with everything behind it gone. */
body[data-act="5"] #scrim { background: var(--blue); backdrop-filter: none; -webkit-backdrop-filter: none; }

#flood { position: fixed; inset: 0; z-index: 40; pointer-events: none; transition: opacity .5s var(--ease); }
#flood.gone { opacity: 0; }
.floatwin { position: absolute; overflow: hidden; box-shadow: 2px 2px 0 rgba(0,0,0,.18); animation: fwpop .15s var(--ease) both; }
.floatwin .win { width: 100%; height: 100%; }
@keyframes fwpop { from { transform: scale(.72); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* faint halftone / dither dot texture (reads on white) */
.fx-vignette {
  z-index: 1;
  opacity: calc(.05 + var(--chaos) * .12);
  background-image: radial-gradient(var(--blue) 0.6px, transparent 0.7px);
  background-size: 7px 7px;
}

/* tiny technical marks scattered as background texture (registration ticks) */
.fx-grain {
  z-index: 2;
  opacity: calc(.04 + var(--chaos) * .12);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cg fill='none' stroke='%230a30ff' stroke-width='1'%3E%3Cpath d='M20 14h8M24 10v8'/%3E%3Cpath d='M120 30h8M124 26v8'/%3E%3Crect x='60' y='70' width='9' height='9'/%3E%3Cpath d='M30 120h8M34 116v8'/%3E%3Crect x='130' y='120' width='7' height='7'/%3E%3Cpath d='M150 150h8M154 146v8'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 180px 180px;
  /* drift animation removed — registration marks hold still (no background glitch) */
}

/* DATAMOSH smear wash — horizontal pixel-stretch in blue, anchored top-left */
.fx-scanlines {
  z-index: 3;
  opacity: calc(var(--chaos) * .9);
  background:
    repeating-linear-gradient(0deg,
      transparent 0 5px,
      rgba(10, 48, 255, .045) 5px 6px,
      transparent 6px 12px),
    linear-gradient(118deg,
      rgba(10, 48, 255, .14) 0%,
      rgba(10, 48, 255, .07) 26%,
      transparent 52%);
}
/* a single travelling smear band (the dragged-window streak) */
.fx-scanlines::after {
  content: "";
  position: absolute; left: 0; width: 46%; height: 16px;
  background: repeating-linear-gradient(90deg,
    var(--blue) 0 2px, transparent 2px 7px,
    rgba(10,48,255,.4) 7px 9px, transparent 9px 18px);
  filter: blur(.3px);
  opacity: calc(var(--chaos) * .6);
  top: 18%;
  /* travelling-band animation removed — the smear stays put (no background glitch) */
}

/* faint blue diagonal wash from the dense corner */
.fx-rgb { z-index: 2; opacity: calc(var(--chaos) * .22); background: linear-gradient(125deg, rgba(10,48,255,.12), transparent 48%); }

.fx-glitchburst { z-index: 8000; opacity: 0; mix-blend-mode: multiply; }
.fx-glitchburst.on {
  animation: burst .4s steps(3) 1;
  background: linear-gradient(90deg, var(--blue) 0 16%, transparent 16%), linear-gradient(270deg, rgba(10,48,255,.5) 0 12%, transparent 12%);
}
@keyframes burst {
  0% { opacity: 0; transform: translateX(0); clip-path: inset(0 0 85% 0); }
  30% { opacity: .5; transform: translateX(-16px); clip-path: inset(28% 0 38% 0); }
  60% { opacity: .35; transform: translateX(12px); clip-path: inset(62% 0 8% 0); }
  100% { opacity: 0; transform: translateX(0); clip-path: inset(0 0 100% 0); }
}

/* ============================================================
   DECOR LAYER — the chaotic cluster (fades + de-jitters with clean)
   ============================================================ */
.deco {
  position: fixed; inset: 0; z-index: 4; pointer-events: none;
  opacity: calc(.18 + var(--chaos) * .82);
  transition: opacity .5s var(--ease);
}

/* the toolbar strip (was menubar) — thin technical chrome on white */
.menubar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 450; height: 22px;
  display: flex; align-items: center; gap: 2px; padding: 0 6px;
  background: var(--paper);
  box-shadow: inset 0 -1px 0 var(--hair);
  font: 700 11px/22px var(--font-cond); letter-spacing: .5px; text-transform: uppercase; color: var(--ink);
}
.menubar span { padding: 0 8px; }
.menubar span:hover { color: var(--blue); }
.menubar .mb-spacer { flex: 1; }
.menubar .mb-clock { font-family: var(--font-mono); font-weight: 400; letter-spacing: 0; padding-right: 4px; color: var(--blue); }

/* ---- the datamosh field: horizontal pixel-stretch smear bands ---- */
.moshfield { position: absolute; inset: 0; }
.mosh {
  position: absolute; display: block;
  background: repeating-linear-gradient(90deg,
    var(--blue) 0 3px,
    rgba(10,48,255,.55) 3px 5px,
    var(--paper) 5px 7px,
    rgba(10,48,255,.85) 7px 9px,
    transparent 9px 12px);
  box-shadow: 1px 0 0 rgba(0,0,0,.18);
  /* jitter scales with chaos: calm to 0 by act 4 */
  transform: translateX(calc(var(--chaos) * 0px));
  opacity: calc(.35 + var(--chaos) * .55);
}
.mosh.m2 { background: repeating-linear-gradient(90deg, var(--blue-deep) 0 2px, var(--paper) 2px 4px, rgba(10,48,255,.6) 4px 7px, transparent 7px 11px); }
.mosh.m3 {
  background:
    repeating-linear-gradient(90deg, var(--blue) 0 4px, var(--paper) 4px 6px, rgba(10,48,255,.4) 6px 10px, transparent 10px 16px),
    repeating-linear-gradient(0deg, rgba(0,0,0,.06) 0 1px, transparent 1px 4px);
}

/* repeated Win95 dialog clones — flat, 1px lines, datamoshed variants */
.miniwin {
  position: absolute; width: 86px; transform-origin: top left;
  border: 1px solid var(--blue); background: var(--paper);
  font: 700 8px/1 var(--font-cond); letter-spacing: .5px; color: var(--blue);
}
.miniwin b { display: block; background: var(--blue); color: #fff; padding: 3px 4px; }
.miniwin s { display: block; height: 4px; margin: 5px 6px 0; background: var(--blue); opacity: .35; }
.miniwin s:last-child { margin-bottom: 6px; width: 58%; }
/* echo-drag glitch removed — mini-window clones render flat, no lateral blue echo */
.miniwin.mw-mosh { }

/* ---- HERO MOTIF: stacked status words, smeared with RGB echo drag ---- */
.statusstack { position: absolute; display: flex; flex-direction: column; }
.statusword {
  position: relative;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(28px, 4.2vw, 56px);
  line-height: .92;
  letter-spacing: 0;
  text-transform: none;
  color: var(--blue);
  white-space: nowrap;
  /* RGB echo/drag glitch removed — words render as plain blue, no colour fringing */
}
.statusstack .statusword:nth-child(1) { opacity: .9; }
.statusstack .statusword:nth-child(3) { opacity: .82; }
.statusword.sw-on { color: var(--blue-deep); }
/* pixel-stretch echo clone removed — no ghost behind the words */

/* ---- top toolbar strip: row of tiny repeated square icons ---- */
.toolstrip {
  position: absolute; top: 30px; left: 3%;
  display: flex; gap: 4px;
  opacity: calc(.4 + var(--chaos) * .6);
}
.toolstrip i {
  width: 12px; height: 12px; display: block;
  border: 1px solid var(--blue);
  background:
    linear-gradient(45deg, transparent 45%, var(--blue) 45% 55%, transparent 55%),
    var(--paper);
}
.toolstrip i:nth-child(3n) { background: var(--blue); }
.toolstrip i:nth-child(4n) { background: linear-gradient(0deg, var(--blue) 0 50%, var(--paper) 50%); }

/* ---- registration crosshairs (+) ---- */
.xhair { position: absolute; width: 18px; height: 18px; }
.xhair::before, .xhair::after { content: ""; position: absolute; background: var(--hair); }
.xhair::before { left: 50%; top: 0; width: 1px; height: 100%; transform: translateX(-.5px); }
.xhair::after { top: 50%; left: 0; height: 1px; width: 100%; transform: translateY(-.5px); }
.xhair.sm { width: 10px; height: 10px; }
.xhair.sm::before, .xhair.sm::after { background: var(--blue); }

/* ---- thin arrows ---- */
.arrow { position: absolute; width: 34px; height: 1px; background: var(--blue); transform-origin: left center; }
.arrow::after { content: ""; position: absolute; right: 0; top: 50%; width: 6px; height: 6px; border-top: 1px solid var(--blue); border-right: 1px solid var(--blue); transform: translateY(-50%) rotate(45deg); }

/* ---- dashed leader lines ---- */
.leader { position: absolute; height: 1px; background: repeating-linear-gradient(90deg, var(--hair) 0 4px, transparent 4px 8px); transform-origin: left center; }

/* ---- registration clock icon ---- */
.regclock {
  position: absolute; width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--hair);
}
.regclock::before, .regclock::after { content: ""; position: absolute; left: 50%; top: 50%; background: var(--hair); transform-origin: bottom center; }
.regclock::before { width: 1px; height: 9px; transform: translate(-50%, -100%) rotate(28deg); }
.regclock::after { width: 1px; height: 6px; transform: translate(-50%, -100%) rotate(-70deg); }

/* ---- tiny boxes ---- */
.tickbox { position: absolute; width: 9px; height: 9px; border: 1px solid var(--blue); }
.tickbox::after { content: ""; position: absolute; inset: 2px; border-left: 1px solid var(--blue); border-bottom: 1px solid var(--blue); transform: rotate(-45deg); transform-origin: center; }

/* ---- vertical rotated sidebar caption (90deg) ---- */
.vcaption {
  position: absolute;
  transform-origin: top left; transform: rotate(90deg);
  font: 700 12px/1 var(--font-cond); letter-spacing: 3px; text-transform: uppercase;
  color: var(--blue); opacity: .6; white-space: nowrap;
}

/* ---- repeated Courier echo block (fading down) ---- */
.echoblock { position: absolute; display: flex; flex-direction: column; gap: 1px; }
.echoblock span {
  font: 400 13px/1.25 var(--font-mono); color: var(--ink); white-space: nowrap;
}
.echoblock span:nth-child(1) { color: var(--blue); }
.echoblock span:nth-child(2) { opacity: .7; transform: translateX(calc(var(--chaos) * 4px)); }
.echoblock span:nth-child(3) { opacity: .5; transform: translateX(calc(var(--chaos) * 9px)); }
.echoblock span:nth-child(4) { opacity: .34; transform: translateX(calc(var(--chaos) * 16px)); }
.echoblock span:nth-child(5) { opacity: .2; transform: translateX(calc(var(--chaos) * 26px)); }

/* ---- rating-style badge ---- */
.ratebox { position: absolute; border: 1px solid var(--hair); background: var(--paper); padding: 3px; text-align: center; }
.ratebox b { display: block; font: 900 16px/1 var(--font-disp); color: var(--ink); letter-spacing: 1px; }
.ratebox s { display: block; font: 400 7px/1.4 var(--font-mono); color: var(--blue); text-decoration: none; letter-spacing: 1px; }

/* ============================================================
   CUSTOM CURSOR — thin blue/black registration crosshair
   ============================================================ */
.cursor { position: fixed; left: 0; top: 0; z-index: 10000; pointer-events: none; mix-blend-mode: multiply; transform: translate(-200px, -200px); }
.cur { position: absolute; width: 22px; height: 22px; transform: translate(-50%, -50%); transition: width .15s, height .15s; }
.cur::before, .cur::after { content: ""; position: absolute; background: currentColor; }
.cur::before { left: 0; top: 50%; width: 100%; height: 1px; transform: translateY(-50%); }
.cur::after { top: 0; left: 50%; height: 100%; width: 1px; transform: translateX(-50%); }
.cur-c { color: var(--blue); }
/* RGB-split duplicates removed — single clean blue crosshair, no color fringing */
.cur-m, .cur-y { display: none; }
/* act 1 (blue splash) and act 5 (blue chat): the crosshair turns YELLOW — and blends normally
   (not multiply) so it stays a clean, bright yellow on the blue field. */
body[data-act="1"] .cursor, body[data-act="5"] .cursor { mix-blend-mode: normal; }
body[data-act="1"] .cur-c, body[data-act="5"] .cur-c { color: var(--yellow); }
.cursor.hot .cur { width: 34px; height: 34px; }
/* no text label on the cursor */
.cur-tag { display: none; }

/* ============================================================
   HUD
   ============================================================ */
.hud {
  position: fixed; top: 22px; left: 0; right: 0; z-index: 500;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; padding: 8px;
}
.hud-title { font: 700 12px/1 var(--font-cond); letter-spacing: 2px; text-transform: uppercase; color: var(--blue); padding: 6px 8px; background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair); }
.hud-meta { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.hud-chip { font: 700 10px/1 var(--font-cond); letter-spacing: 1px; text-transform: uppercase; padding: 6px 8px; color: var(--ink); background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair); }
.hud-chip-alt { color: #fff; background: var(--blue); box-shadow: none; }

/* ============================================================
   BUTTONS — thin blueprint, blue ink
   ============================================================ */
.btn {
  font: 700 12px/1 var(--font-cond); letter-spacing: 1px; color: var(--ink);
  background: var(--paper); border: 0; padding: 10px 16px; cursor: none; position: relative;
  box-shadow: inset 0 0 0 1px var(--hair);
  text-transform: uppercase;
  transition: color .15s, box-shadow .15s, background .15s;
}
.btn:hover { color: #fff; background: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }
.btn:active { transform: translate(1px, 1px); }
.btn:disabled { color: var(--sh); box-shadow: inset 0 0 0 1px var(--sh); pointer-events: none; }
.btn:focus-visible { outline: 1px dotted var(--blue); outline-offset: 2px; }
.btn-big { font-size: 15px; padding: 12px 22px; letter-spacing: 1.5px; }
.btn-big:hover { background: var(--blue-deep); }
.btn-arrow { display: inline-block; animation: nudge 1s var(--ease) infinite; }
@keyframes nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }

/* ============================================================
   STAGE / ACTS
   ============================================================ */
.stage { position: fixed; inset: 0; z-index: 100; }
.act { position: absolute; inset: 0; opacity: 0; visibility: hidden; transition: opacity .5s var(--ease); }
.act.is-active { opacity: 1; visibility: visible; }

/* ---- ACT 1 : INTRO as a thin blueprint dialog ---- */
.act-intro { display: grid; place-items: center; padding: 7vh 4vw; z-index: 120; }
.intro-grid { width: min(900px, 94vw); }
.intro-box { display: none; }
.intro-marquee { display: none; }

.win-dialog { }

/* Act 1 is a calm full-screen splash. The messy canvas, its decor and the boot
   flood all belong to Act 2 — keep them fully inert (no paint, no animation, no
   running timers reaching visible DOM) while we are still on the intro (step 0). */
body[data-step="0"] #world,
body[data-step="0"] #flood,
body[data-step="0"] .deco,
body[data-step="0"] .fx-grain,
body[data-step="0"] .fx-rgb,
body[data-step="0"] .fx-scanlines { display: none !important; }

/* ============================================================
   ACT 1 — FULL-SCREEN BLUE SPLASH (the title page)
   Flat electric-blue field, dim monospace margin notes in the four
   corners, a yellow-highlighter manifesto + team in the centre.
   ============================================================ */
.intro-win {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: 400;
  transition: visibility 0s var(--ease) 0s;
}
/* Act 1 -> Act 2 transition: the pieces don't fall — they switch OFF in staggered
   waves (several at a time, dissolving with a soft blur), then the blue field clears
   last to reveal the messy canvas of Act 2 underneath. */
.intro-win.hidden { visibility: hidden; pointer-events: none; transition-delay: 1.25s; }

.intro-screen { transition: opacity .55s var(--ease); }
.intro-eyebrow, .intro-headline, .intro-sub,
.intro-manifesto span, .intro-team, .inote p {
  transition: opacity .34s var(--ease), filter .34s var(--ease);
}

.intro-win.hidden .intro-eyebrow,
.intro-win.hidden .intro-headline,
.intro-win.hidden .intro-sub,
.intro-win.hidden .intro-manifesto span,
.intro-win.hidden .intro-team,
.intro-win.hidden .inote p { opacity: 0; filter: blur(2px); }

/* scattered delays so groups go dark "several at once", not in a single sweep */
.intro-win.hidden .intro-eyebrow                  { transition-delay: .04s; }
.intro-win.hidden .intro-sub                       { transition-delay: .12s; }
.intro-win.hidden .intro-headline                  { transition-delay: .20s; }
.intro-win.hidden .intro-manifesto span:nth-child(1){ transition-delay: .16s; }
.intro-win.hidden .intro-manifesto span:nth-child(2){ transition-delay: .30s; }
.intro-win.hidden .intro-manifesto span:nth-child(3){ transition-delay: .22s; }
.intro-win.hidden .intro-manifesto span:nth-child(4){ transition-delay: .34s; }
.intro-win.hidden .intro-team                      { transition-delay: .44s; }
.intro-win.hidden .inote-tl p:nth-child(1)         { transition-delay: .04s; }
.intro-win.hidden .inote-tl p:nth-child(2)         { transition-delay: .10s; }
.intro-win.hidden .inote-tr p:nth-child(1)         { transition-delay: .08s; }
.intro-win.hidden .inote-tr p:nth-child(2)         { transition-delay: .14s; }
.intro-win.hidden .inote-bl p:nth-child(1)         { transition-delay: .26s; }
.intro-win.hidden .inote-bl p:nth-child(2)         { transition-delay: .32s; }
.intro-win.hidden .inote-br p:nth-child(1)         { transition-delay: .30s; }
.intro-win.hidden .inote-br p:nth-child(2)         { transition-delay: .36s; }

/* the blue field is the last to go — it fades after the content, revealing Act 2 */
.intro-win.hidden .intro-screen { opacity: 0; transition-delay: .70s; }

.intro-screen {
  position: absolute; inset: 0; overflow: hidden;
  background: var(--blue); color: #fff;
  font-family: var(--font-mono);
}

/* TEAM slide (between Act 1 and Act 2) — four square, blue-filtered portraits in a row */
.team-win {
  position: fixed; inset: 0; width: 100%; height: 100%; z-index: 399;
  /* appears INSTANTLY (fully opaque) so it covers the field before the previous slide leaves —
     no white ever shows between Act-1 slides; only the OUTGOING slide fades (see .hidden). */
}
.team-win.hidden { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .55s var(--ease), visibility 0s linear .55s; }
.team-screen {
  position: absolute; inset: 0; overflow: auto;
  background: var(--blue); color: #fff; font-family: var(--font-mono);
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; justify-content: safe center;     /* fallback, then safe-center */
  gap: clamp(14px, 3.5vh, 40px); padding: clamp(16px, 5vh, 56px) 5vw;
}
.team-eyebrow { font: 700 clamp(11px, 1.3vw, 15px)/1 var(--font-cond); letter-spacing: 6px; text-transform: uppercase; color: rgba(255,255,255,.8); margin: 0; }
/* discreet line about us, under the roster */
.team-tagline { margin: 0; text-align: center; font: 400 clamp(12px, 1.4vw, 16px)/1.5 var(--font-mono); font-style: italic; color: rgba(255,255,255,.6); letter-spacing: .3px; max-width: 42ch; }
.team-row { display: flex; gap: clamp(14px, 3vw, 48px); align-items: flex-start; flex-wrap: wrap; justify-content: center; }
/* size by the SMALLER of width/height so four square cards always fit vertically too */
.team-row .team-card.item { position: static; left: auto; top: auto; transform: none; margin: 0; width: clamp(110px, min(17vw, 22vh), 230px); }
.team-card .win { width: 100%; }
.team-photo { aspect-ratio: 1 / 1; overflow: hidden; background: var(--blue); }
.team-photo img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: grayscale(1) contrast(1.05);
  mix-blend-mode: luminosity;
}

/* MATIAS DEL CAMPO profile slide — same blue field + window chrome as THE TEAM, but a
   portrait + write-up layout. */
.matias-row {
  display: flex; gap: clamp(20px, 4vw, 56px); align-items: center; justify-content: center;
  flex-wrap: wrap; width: min(1100px, 92vw);
}
/* portrait sized by the smaller of width/height so the 3:4 frame never overflows vertically */
.matias-row .matias-card.item { position: static; left: auto; top: auto; transform: none; margin: 0; width: clamp(150px, min(26vw, 32vh), 340px); flex: 0 0 auto; }
.matias-card .win { width: 100%; }
/* portrait is 760×1013 (exact 3:4) — match the frame so the whole image shows, no crop/pan */
.matias-card .team-photo { aspect-ratio: 3 / 4; }
.matias-info { flex: 1 1 360px; max-width: 560px; min-width: 280px; text-align: left; }
.matias-name { font: 700 clamp(22px, 3.2vw, 40px)/1.05 var(--font-mono); letter-spacing: 1px; text-transform: uppercase; color: #fff; margin: 0 0 10px; }
.matias-role { font: 400 clamp(13px, 1.5vw, 17px)/1.45 var(--font-mono); color: rgba(255,255,255,.85); margin: 0 0 16px; }
.matias-role b { color: var(--yellow); font-weight: 700; }
.matias-points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.matias-points li { position: relative; padding-left: 18px; font: 400 clamp(12px, 1.3vw, 15px)/1.45 var(--font-mono); color: rgba(255,255,255,.8); }
.matias-points li::before { content: '▸'; position: absolute; left: 0; color: var(--yellow); }
.matias-points b { color: #fff; font-weight: 700; }
.matias-points i { color: rgba(255,255,255,.92); font-style: italic; }
.matias-logo.item { position: static; left: auto; top: auto; transform: none; margin: 18px 0 0; width: clamp(150px, 18vw, 200px); }
.matias-logo .win { width: 100%; }
.matias-logo-body { aspect-ratio: 16 / 7; overflow: hidden; background: #fff; display: grid; place-items: center; padding: 10px; }
.matias-logo-body img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }

@media (max-width: 720px) {
  .matias-info { text-align: center; }
  .matias-points { text-align: left; }
  .matias-logo.item { margin-left: auto; margin-right: auto; }
}

/* corner margin notes — dim, low-contrast, lightly staggered */
.inote { position: absolute; width: min(300px, 30vw); }
.inote p { margin: 0 0 16px; font: 400 12px/1.5 var(--font-mono); color: rgba(255,255,255,.6); }
.inote p:last-child { margin-bottom: 0; }
.inote b { color: #fff; font-weight: 700; margin-right: 6px; letter-spacing: .5px; }
.inote span { display: inline-block; padding-left: 1.6em; color: rgba(255,255,255,.55); }
.inote-tl { top: 10vh; left: 3vw; }
.inote-bl { bottom: 8vh; left: 3vw; }
.inote-tr { top: 10vh; right: 3vw; }
.inote-br { bottom: 8vh; right: 3vw; }

/* centre column */
.intro-center {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(1000px, 92vw); text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.intro-eyebrow { font: 700 clamp(11px, 1.3vw, 15px)/1 var(--font-cond); letter-spacing: 5px; text-transform: uppercase; color: rgba(255,255,255,.75); margin-bottom: 11px; }
/* title + attribution are now the hero (the yellow manifesto was removed) */
.intro-headline { font: 700 clamp(26px, 4.6vw, 58px)/1.05 var(--font-mono); letter-spacing: 2.5px; text-transform: uppercase; color: #fff; margin: 0; }
.intro-sub { font: 400 clamp(13px, 1.5vw, 19px)/1.4 var(--font-mono); color: rgba(255,255,255,.78); margin: 13px 0 0; }
.intro-sub em { color: var(--yellow); font-style: italic; font-weight: 700; }

/* yellow-highlighter manifesto — the hero. Big monospace marker lines whose yellow
   boxes STICK together vertically (no gap, no vertical padding) and stagger sideways,
   as in the reference. */
.intro-manifesto { margin: 26px 0; display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
.intro-manifesto span {
  background: var(--yellow); color: var(--ink);
  font: 700 clamp(17px, 3vw, 38px)/1.32 var(--font-mono);
  letter-spacing: .2px; text-transform: uppercase; padding: 0 .34em;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.intro-manifesto span em { font-style: italic; color: var(--blue); }
.intro-manifesto span:nth-child(2) { margin-left: 2.1em; }
.intro-manifesto span:nth-child(3) { margin-left: .9em; }
.intro-manifesto span:nth-child(4) { margin-left: 1.6em; }

/* team credits */
.intro-team {
  margin-top: 30px; display: flex; flex-wrap: wrap; justify-content: center;
  align-items: center; gap: 8px 14px;
  font: 700 11px/1 var(--font-cond); letter-spacing: 2px; text-transform: uppercase;
  color: rgba(255,255,255,.82);
}
.intro-team b { color: var(--ink); background: var(--yellow); padding: 3px 7px; letter-spacing: 2px; }
.intro-team span { position: relative; }
.intro-team span + span::before { content: "·"; position: absolute; left: -9px; color: rgba(255,255,255,.45); }

@media (max-width: 860px) {
  .inote { display: none; }
  .intro-manifesto span { margin-left: 0 !important; }
}
/* on short screens the corner notes would crowd / overlap the centred title — hide them */
@media (max-height: 620px) {
  .inote { display: none; }
}

/* ============================================================
   CANVAS / WINDOWS / ITEMS
   --- DO NOT set transform/width/height on .item (JS owns those) ---
   ============================================================ */
/* z-index: auto (not 10) so .world does NOT create a stacking context — its items keep
   their own z (focused 500 above #scrim 250, receding 1 below it) within the stage context. */
.world { position: absolute; inset: 0; z-index: auto; }

/* group-coloured connection graph behind the canvas windows (Act 3 / 4). Stroke colour is
   set per line in canvas.js; sits below every window (z 0) and its lines follow them live. */
.world-edges { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; overflow: visible; }
.world-edge { stroke-width: 1.2; opacity: .22; }

.load-state { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font: 700 18px/1 var(--font-cond); letter-spacing: 2px; text-transform: uppercase; color: var(--blue); z-index: 5; }
.blink { animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* JS sets inline transform / width / height on .item — we only set transition */
.item { position: absolute; left: 0; top: 0; transform-origin: center; will-change: transform, opacity; transition: transform .85s var(--ease), opacity .5s var(--ease), filter .5s var(--ease); transition-delay: var(--d, 0s); }

/* thin blueprint window chrome (used for canvas items + intro/chat/mini) */
.win {
  width: 100%; height: 100%; display: flex; flex-direction: column; overflow: hidden;
  background: var(--paper); padding: 0;
  border: 1px solid #000;                 /* every element window: one thin black outline, no shadow */
  box-shadow: none;
  transition: background-color .45s var(--ease);
}
.item .win { box-shadow: none; }
.item .win:hover { box-shadow: none; }
.winbar {
  height: 19px; flex: 0 0 19px; display: flex; align-items: center; gap: 5px; padding: 0 3px 0 5px;
  color: #fff; font: 700 10px/19px var(--font-cond); letter-spacing: .8px; text-transform: uppercase;
  background: var(--blue); user-select: none; cursor: none;
  border-bottom: 1px solid var(--hair);
}
.wb-dot { width: 9px; height: 9px; flex: 0 0 auto; background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair); }
/* group chip: explicit "which group/chapter" cue on every window's title bar (G1, G2, …) —
   a dark inset pill that stays legible on any mega-group hue/shade. */
.wb-grp { flex: 0 0 auto; font: 700 8px/1 var(--font-cond); letter-spacing: .5px; color: #fff; background: rgba(0, 0, 0, .32); padding: 2px 4px; border-radius: 2px; }
.wb-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-btns { display: flex; gap: 2px; pointer-events: none; }   /* decorative only — no button does anything */
.wb-btns i { width: 14px; height: 12px; background: var(--paper); color: var(--ink); font-style: normal; font: 700 8px/12px var(--font-cond); text-align: center; box-shadow: inset 0 0 0 1px var(--hair); }
.wb-x { font-weight: 700; }
.winbody { flex: 1; min-height: 0; position: relative; overflow: hidden; background: var(--paper); }
.winbody img, .winbody video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* CAROUSEL (numbered image sequence): show the whole frame (contain) + a bottom nav panel
   in the window's own chrome. The prev/next buttons reuse the beveled title-button look but
   are interactive (the title bar's .wb-btns are not). */
.type-carousel .winbody { background: var(--paper); }
.type-carousel .winbody img { object-fit: contain; }
.winfoot {
  flex: 0 0 20px; height: 20px; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 0 4px; background: var(--paper); border-top: 1px solid var(--hair);
  font: 700 9px/1 var(--font-cond); letter-spacing: .6px; color: var(--ink); user-select: none;
}
.cz-count { min-width: 34px; text-align: center; }
.cz-btn {
  width: 18px; height: 14px; padding: 0; border: 0; cursor: pointer;
  background: var(--paper); color: var(--ink); font: 700 8px/14px var(--font-cond); text-align: center;
  box-shadow: inset 0 0 0 1px var(--hair);
}
.cz-btn:hover { background: var(--blue); color: #fff; }
.cz-btn:active { box-shadow: inset 0 0 0 1px var(--hair), inset 1px 1px 2px rgba(0,0,0,.3); }

/* WINDOW BUTTONS (Act-3 canvas items): only ⊡ magnify and _ restore are interactive — close
   stays decorative. Magnify lifts the window to a big centered popup over a blurred backdrop. */
.item .winbar .wb-min, .item .winbar .wb-max { pointer-events: auto; cursor: pointer; }
.item .winbar .wb-min:hover, .item .winbar .wb-max:hover { background: var(--blue); color: #fff; }
#magScrim {
  position: fixed; inset: 0; z-index: 690; opacity: 0; visibility: hidden; pointer-events: none;
  background: rgba(255, 255, 255, .72); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: opacity .4s var(--ease), visibility .4s var(--ease);
}
#magScrim.show { opacity: 1; visibility: visible; pointer-events: auto; }
/* size (width/height) is set inline by JS to the content's exact aspect — no letterbox */
.item.maximized {
  position: fixed !important; left: 50% !important; top: 50% !important;
  transform: translate(-50%, -50%) !important; transform-origin: 0 0 !important;
  z-index: 700 !important; opacity: 1 !important; filter: none !important; transition: none !important;
}
.item.maximized .winbody { background: var(--paper); }
.item.maximized .winbody img, .item.maximized .winbody video { object-fit: contain; animation: none; }   /* static — no vertical pan while magnified */
.item.maximized .win::after { display: none; }   /* drop the "past" white veil while magnified */

/* Active (non-dimmed) windows breathe: their content gently auto-scrolls down, pauses,
   then scrolls back up — a slow ping-pong pan of the cropped image. Dimmed "past"
   windows hold still. */
@keyframes winpan {
  0%, 10%  { object-position: 50% 0%; }
  50%, 60% { object-position: 50% 100%; }
  100%     { object-position: 50% 0%; }
}
.item:not(.past) .winbody img,
.item:not(.past) .winbody video { animation: winpan 14s ease-in-out infinite; }
.item.past .winbody img, .item.past .winbody video { animation: none; }

/* ── "web window" chrome for the act 1 / 3 / 4 popups ──────────────────────────
   A nod to old Windows (98 navy→blue title gradient, beveled title buttons, red
   close hover) rendered with the page's modern, light, crisp finish. Scoped to the
   three dialog popups so the canvas item windows stay flat/sharp. */
.win-dialog, .chat-win, .rat-win {
  box-shadow: inset 0 0 0 1px var(--hair), 0 16px 46px rgba(8, 16, 48, .12);
}
.win-dialog > .winbar, .chat-win > .winbar, .rat-win > .winbar {
  height: 26px; flex-basis: 26px; line-height: 26px;
  padding: 0 4px 0 8px; gap: 7px; letter-spacing: 1px;
  background: linear-gradient(90deg, var(--navy) 0%, var(--blue) 55%, var(--blue-2) 100%);
  border-bottom: 1px solid var(--hair);
}
.win-dialog > .winbar .wb-dot, .chat-win > .winbar .wb-dot, .rat-win > .winbar .wb-dot {
  width: 12px; height: 12px;
}
.win-dialog > .winbar .wb-btns i, .chat-win > .winbar .wb-btns i, .rat-win > .winbar .wb-btns i {
  width: 19px; height: 17px; line-height: 15px; font-size: 9px;
  background: var(--face); color: var(--ink); box-shadow: inset 1px 1px 0 var(--hi), inset -1px -1px 0 var(--dsh);
}
.win-dialog > .winbar .wb-x:hover, .chat-win > .winbar .wb-x:hover, .rat-win > .winbar .wb-x:hover {
  background: #e81123; color: #fff; box-shadow: inset 1px 1px 0 #ff5a66, inset -1px -1px 0 #a20d18;
}

.type-image .winbar { background: var(--blue); }
.type-gif   .winbar { background: var(--magenta); }     /* rare accent */
.type-video .winbar { background: var(--blue-2); }
.type-text  .winbar { background: var(--blue); }

/* GROUP-coloured headers — a window from folder gNN_MM_* gets its group's colour on the
   title bar (overrides the per-type colour above by specificity). A subtle text shadow
   keeps the white label legible on the brighter hues. Extend with more groups as needed. */
.item[data-group] .winbar { text-shadow: 0 1px 0 rgba(0, 0, 0, .28); }
.item[data-group="1"] .winbar { background: var(--grp-1); }
.item[data-group="2"] .winbar { background: var(--grp-2); }
.item[data-group="3"] .winbar { background: var(--grp-3); }
.item[data-group="4"] .winbar { background: var(--grp-4); }
.item[data-group="5"] .winbar { background: var(--grp-5); }
.item[data-group="6"] .winbar { background: var(--grp-6); }

.gif-tag, .vid-tag { position: absolute; right: 4px; bottom: 4px; font: 700 8px/1 var(--font-cond); letter-spacing: .5px; background: var(--blue); color: #fff; padding: 2px 4px; }
.type-gif .gif-tag { background: var(--magenta); }
/* text windows keep a real vertical scrollbar; their copy auto-scrolls (JS, ping-pong),
   and the moment the reader uses the scrollbar that one window's auto-scroll stops. */
.textcard { padding: 10px 12px; height: 100%; overflow-y: auto; overflow-x: hidden; background: var(--paper); color: var(--ink); font: 400 10px/1.5 var(--font-mono); }
.textscroll { white-space: pre-wrap; word-break: break-word; }
.textcard::-webkit-scrollbar { width: 12px; }
.textcard::-webkit-scrollbar-track { background: var(--paper); box-shadow: inset 0 0 0 1px var(--sh); }
.textcard::-webkit-scrollbar-thumb { background: var(--face); box-shadow: inset 1px 1px 0 var(--hi), inset -1px -1px 0 var(--dsh), inset 0 0 0 1px var(--sh); }
.textcard::-webkit-scrollbar-thumb:hover { background: var(--blue); }
/* firefox */
.textcard { scrollbar-width: thin; scrollbar-color: var(--dsh) var(--paper); }

/* cascade "open window" clones removed — each item is a single clean window,
   no offset echo copies stacked behind it (notably the zoomed images in act 2). */
.item::before, .item::after { display: none; content: none; }

.item.dragging { transition: none; z-index: 9999 !important; }
.item.dragging .win { box-shadow: none; }

/* all element windows keep the same thin black frame — no blue marker, no shadow */
.item.fresh .win { box-shadow: none; }

/* PAST slides (earlier folders already placed): the WHOLE window — blue title bar
   included — washes toward WHITE. The window stays 100% OPAQUE (no transparency): a
   solid white veil sits over it, so nothing behind ever shows through. It reads as a
   faded "previous slide" while remaining a solid white card. */
.item .win { position: relative; }
.item .win::after {
  content: ""; position: absolute; inset: 0; z-index: 6; pointer-events: none;
  background: #fff; opacity: 0; transition: opacity .6s var(--ease);
}
.item.past .win::after { opacity: .62; }

/* item glitch jitter removed — windows stay still (no occasional tremor) */

/* ---- FOLDER TITLE ---- */
/* small, centred, discreet folder label near the top (not a huge hero title) */
.folder-title { position: absolute; left: 50%; top: 8.5vh; z-index: 520; display: flex; align-items: baseline; gap: 8px; opacity: 0; transform: translate(-50%, 6px); transition: opacity .45s, transform .45s; pointer-events: none; }
.folder-title.show { opacity: .8; transform: translate(-50%, 0); }
/* group chip — coloured to match the group's window headers (hidden when ungrouped) */
.ft-grp { font: 700 11px/1 var(--font-cond); letter-spacing: 1.5px; color: #fff; background: var(--blue); padding: 3px 6px; text-shadow: 0 1px 0 rgba(0, 0, 0, .28); }
.folder-title:not([data-group]) .ft-grp { display: none; }
.folder-title[data-group="1"] .ft-grp { background: var(--grp-1); }
.folder-title[data-group="2"] .ft-grp { background: var(--grp-2); }
.folder-title[data-group="3"] .ft-grp { background: var(--grp-3); }
.folder-title[data-group="4"] .ft-grp { background: var(--grp-4); }
.folder-title[data-group="5"] .ft-grp { background: var(--grp-5); }
.folder-title[data-group="6"] .ft-grp { background: var(--grp-6); }
.ft-idx { font: 700 13px/1 var(--font-mono); color: var(--blue); }
.ft-name { font: 700 12px/1 var(--font-cond); letter-spacing: 2px; text-transform: uppercase; color: var(--ink); max-width: 60vw; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- MEGA-GROUP BAND ----
   A thin top accent in the current mega-group's base hue while walking its chapters (Act 3).
   Subtle super-chapter cue: it stays the same colour across a mega-group's groups, so a hue
   change quietly signals "new super-chapter". --mega-col is set per stop in state.js. */
.stage::before {
  content: ''; position: absolute; left: 0; top: 0; height: 3px; width: 100%;
  background: var(--mega-col, transparent); z-index: 540; pointer-events: none;
  opacity: 0; transition: opacity .5s var(--ease), background-color .5s var(--ease);
}
body[data-mega]:not([data-mega=""]) .stage::before { opacity: .6; }

/* ---- RATIONALIZATION ---- */
.rationalize { position: absolute; inset: 0; z-index: 60; display: grid; place-items: center; opacity: 0; visibility: hidden; transition: opacity .6s var(--ease); pointer-events: none; padding: 5vw; background: rgba(255,255,255,.66); backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px); }
.rationalize.show { opacity: 1; visibility: visible; }
.rat-win { width: min(900px, 92vw); height: auto; max-height: 86vh; transform-origin: center; }
/* the RATIONALIZED.LOG window EMERGES with a zoom (like the Act-2 focus images snapping
   into place): it scales up from small and settles via the page's easing. */
.rationalize.show .rat-win { animation: ratpop .62s var(--ease) both; }
@keyframes ratpop {
  0%   { transform: scale(.55); opacity: 0; }
  60%  { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.rat-inner { text-align: center; background: var(--paper); padding: 6vh 4vw; overflow: auto; }
.rat-kicker { font: 700 11px/1 var(--font-cond); letter-spacing: 5px; text-transform: uppercase; color: var(--blue); margin-bottom: 22px; }
.rat-line { font-family: var(--font-mono); font-weight: 700; font-size: clamp(18px, 3vw, 38px); line-height: 1.1; margin: 6px 0; color: var(--ink); }
.rat-dim { color: var(--sh); font-weight: 400; }
.rat-big { font-family: var(--font-disp); font-weight: 400; font-style: normal; font-size: clamp(26px, 5vw, 60px); margin-top: 16px; color: var(--blue); text-transform: uppercase; }

/* ACT 4 — the panel reframed as an audience QUESTION (lead + a list of prompts). */
.rat-inner--q { padding: 7vh 5vw; }
.rat-q-lead { font-family: var(--font-disp); font-weight: 400; font-size: clamp(26px, 4.6vw, 56px); line-height: 1.05; color: var(--ink); text-transform: uppercase; margin: 0 0 30px; }
.rat-q-lead .hl { color: var(--blue); }
.rat-q-list { list-style: none; margin: 0 auto; padding: 0; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.rat-q-list li { font-family: var(--font-mono); font-weight: 700; font-size: clamp(16px, 2.6vw, 34px); line-height: 1.15; color: var(--blue); white-space: nowrap; }
.rat-q-list li::before { content: "▸ "; color: var(--magenta); }

/* ACT 3 — exclusive lone-text panel (important statement / audience question). Same dialog
   chrome + zoom-in as the Act-4 panel, but layered ABOVE the zoomed Act-3 hero (z 520) and
   below the nav (z 550) so it fully takes over the screen for that slide. */
.bigtext { position: absolute; inset: 0; z-index: 545; display: grid; place-items: center; opacity: 0; visibility: hidden; transition: opacity .55s var(--ease); pointer-events: none; padding: 5vw; background: rgba(255,255,255,.72); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.bigtext.show { opacity: 1; visibility: visible; pointer-events: auto; }   /* block interaction with the windows behind */
.bigtext .rat-win { width: min(900px, 92vw); height: auto; max-height: 86vh; transform-origin: center; }
.bigtext.show .rat-win { animation: ratpop .62s var(--ease) both; }
.bigtext-inner { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
.bigtext-body { font-family: var(--font-mono); font-weight: 700; font-size: clamp(20px, 3.4vw, 40px); line-height: 1.25; color: var(--ink); white-space: pre-line; margin: 0; }
/* a question to the audience reads in the page's blue, slightly larger */
.bigtext.is-question .bigtext-body { color: var(--blue); font-size: clamp(22px, 3.8vw, 46px); }
.bigtext.is-question .rat-kicker { color: var(--magenta); }

/* ACT 3 — LARGE numbered-sequence viewer (same overlay treatment as the lone-text panel, but
   VERY big: a dominant image stage + bottom arrows, and the folder's text smaller underneath). */
.bigseq { position: absolute; inset: 0; z-index: 545; display: grid; place-items: center; opacity: 0; visibility: hidden; transition: opacity .55s var(--ease); pointer-events: none; padding: 3vh 3vw; background: rgba(255,255,255,.72); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.bigseq.show { opacity: 1; visibility: visible; pointer-events: auto; }   /* backdrop captures clicks → never reach the windows behind */
.bigseq .rat-win { width: min(1200px, 95vw); height: min(86vh, 780px); max-height: 90vh; transform-origin: center; }
.bigseq.show .rat-win { animation: ratpop .62s var(--ease) both; }
/* two columns: image + arrows on the LEFT, the folder's text on the RIGHT — keeps the panel
   short enough to fit vertically instead of stacking everything in a tall column. */
.bigseq-body { flex: 1; min-height: 0; display: flex; }
.bigseq-main { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.bigseq-stage { flex: 1; min-height: 0; background: var(--paper); display: grid; place-items: center; overflow: hidden; padding: 14px; }
.bigseq-stage img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.bigseq-foot { flex: 0 0 32px; height: 32px; gap: 14px; }
.bigseq-foot .cz-btn { width: 30px; height: 20px; font-size: 11px; line-height: 20px; }
.bigseq-foot .cz-count { font-size: 12px; min-width: 52px; }
.bigseq-side { flex: 0 0 clamp(220px, 26%, 360px); min-height: 0; background: var(--paper); border-left: 1px solid var(--hair); display: flex; }
.bigseq-text { flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 16px 18px; font: 400 14px/1.55 var(--font-mono); color: var(--ink); white-space: pre-line; text-align: left; }
.bigseq-side:has(.bigseq-text:empty) { display: none; }     /* no text file → image fills the panel */

@media (max-width: 760px) {
  .bigseq-body { flex-direction: column; }
  .bigseq-side { flex: 0 0 auto; max-height: 26vh; border-left: 0; border-top: 1px solid var(--hair); }
}

/* ============================================================
   CHAT MODAL — thin blueprint dialog
   ============================================================ */
.chat-modal { position: fixed; inset: 0; z-index: 600; display: grid; place-items: center; opacity: 0; visibility: hidden; transition: opacity .6s var(--ease), visibility .6s var(--ease); padding: 16px; background: transparent; }
.chat-modal.show { opacity: 1; visibility: visible; }
/* height: auto — size to content (the base .win sets height:100%, which left a tall band
   of empty white below the form). position: relative for the complete frame overlay. */
.chat-win { width: min(680px, 96vw); height: auto; max-height: 86vh; position: relative;
  display: flex; flex-direction: column; background: var(--paper); padding: 0;
  /* gentle, floating Act-4 feel: soft pop-in, then a slow continuous drift */
  animation: popin .5s var(--ease) both, chatfloat 7s ease-in-out .5s infinite; }
/* the thin black hairline as a TOP overlay so it stays complete all the way around
   (the inner paper panels were painting over the shared inset border) */
.chat-win::after { content: ""; position: absolute; inset: 0; z-index: 4; pointer-events: none; box-shadow: inset 0 0 0 1px var(--hair); }
@keyframes popin { from { transform: translateY(18px) scale(.96); opacity: 0; } }
@keyframes chatfloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.winbar-chat { font-size: 10px; }
.chat-body { background: var(--paper); padding: 16px; display: flex; flex-direction: column; gap: 12px; min-height: 0; }
.chat-prompt { font-family: var(--font-cond); font-weight: 700; letter-spacing: .5px; font-size: clamp(14px, 1.9vw, 18px); line-height: 1.3; text-transform: uppercase; color: var(--ink); }
.chat-log { flex: 0 1 auto; overflow: auto; display: flex; flex-direction: column; gap: 9px; min-height: 0; max-height: 42vh; padding-right: 2px; }
.chat-log:empty { display: none; }
.msg { font: 400 14px/1.5 var(--font-mono); padding: 8px 11px; max-width: 92%; white-space: pre-wrap; box-shadow: inset 0 0 0 1px var(--hair); animation: msgin .4s var(--ease) both; }
@keyframes msgin { from { opacity: 0; transform: translateY(7px); } }
.msg-you { align-self: flex-end; background: var(--blue); color: #fff; box-shadow: none; }
.msg-bot { align-self: flex-start; background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--blue); }
.msg-bot .caret { animation: blink 1s steps(1) infinite; color: var(--blue); }
.chat-suggest { display: flex; flex-wrap: wrap; gap: 6px; }
.chat-limit { font: 700 11px/1.4 var(--font-cond); letter-spacing: .5px; text-transform: uppercase; color: var(--blue); background: var(--paper); padding: 8px 10px; box-shadow: inset 0 0 0 1px var(--blue); }
.sugg { font: 700 10px/1 var(--font-cond); letter-spacing: .5px; text-transform: uppercase; color: var(--ink); background: var(--paper); padding: 7px 9px; cursor: none; box-shadow: inset 0 0 0 1px var(--hair); }
.sugg:hover { color: #fff; background: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }
.chat-form { display: flex; align-items: center; gap: 8px; border-top: 1px solid var(--hair); padding-top: 12px; }
.chat-prefix { font: 700 13px/1 var(--font-mono); color: var(--blue); white-space: nowrap; }
.chat-input { flex: 1; background: var(--paper); color: var(--ink); font: 400 15px/1 var(--font-mono); padding: 10px; cursor: none; border: 0; box-shadow: inset 0 0 0 1px var(--hair); }
.chat-input:focus { outline: 1px dotted var(--blue); outline-offset: -4px; }
.chat-send { font-size: 11px; padding: 9px 12px; }

/* ============================================================
   NAV / PROGRESS — thin taskbar
   ============================================================ */
.nav { position: fixed; bottom: 0; left: 0; right: 0; z-index: 550; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 8px; background: var(--paper); box-shadow: inset 0 1px 0 var(--hair); }
/* PROGRESS BAR — a compact, structural MAP of the whole run that rebuilds itself from the
   live sequence. Each stop is a clickable dot coloured by its mega-group hue / group shade
   (so the bar mirrors the content's order); group entries are taller ticks and a new
   mega-group is set off by a gap. One single row that scrolls the active dot into view, so it
   stays compact no matter how many megas / groups / slides there are. */
.progress { flex: 1; min-width: 0; display: flex; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -ms-overflow-style: none; }
.progress::-webkit-scrollbar { display: none; }
.progress-track { display: flex; align-items: center; gap: 4px; margin: auto; padding: 6px 2px; }
.pdot {
  --dc: var(--blue);
  width: 8px; height: 8px; flex: 0 0 auto; padding: 0; border: 0; cursor: pointer;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair);
  transition: background .3s, box-shadow .3s, transform .25s, width .3s, height .3s;
}
.pdot:hover { transform: scale(1.3); }
.pdot.done { background: var(--dc); box-shadow: inset 0 0 0 1px var(--dc); }
.pdot.active { background: var(--dc); box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--dc); transform: scale(1.35); animation: pdotpulse 1.5s var(--ease) infinite; }
/* group entry = a taller tick that labels the start of a group/chapter */
.pdot.group-start { width: 5px; height: 14px; }
/* a new mega-group (super-chapter) is set apart with a gap */
.pdot.mega-start { margin-left: 13px; }
/* special (non-content) stops keep neutral tones */
.pdot.k-intro, .pdot.k-team, .pdot.k-matias { --dc: #9aa3bd; }
.pdot.k-index { --dc: var(--ink); width: 10px; height: 10px; }
.pdot.k-grid, .pdot.k-gridlog { --dc: var(--ink); }
.pdot.k-chat { --dc: var(--blue); border-radius: 50%; }
@keyframes pdotpulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--dc); }
  50%      { box-shadow: 0 0 0 2px var(--paper), 0 0 0 5px var(--dc); }
}
.btn-nav { min-width: 96px; }
/* compact full-screen toggle, left of NEXT */
.btn-fs { min-width: 0; padding: 10px 12px; font-size: 15px; line-height: 1; flex: 0 0 auto; }
.btn-fs.is-fs { color: #fff; background: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }

/* ============================================================
   GLITCH TEXT UTILITY — RGB split, intensity scales with chaos
   ============================================================ */
.glitch { position: relative; }
/* RGB-split text glitch removed — titles render as plain, single-colour text */
.glitch::before, .glitch::after { display: none; content: none; }
.glitch::before { color: var(--blue); transform: translate(calc(var(--chaos) * -2px), 0); clip-path: inset(0 0 60% 0); animation: gl1 2.6s steps(2) infinite; }
.glitch::after { color: var(--magenta); transform: translate(calc(var(--chaos) * 2px), 0); clip-path: inset(60% 0 0 0); animation: gl2 3.2s steps(2) infinite; }
@keyframes gl1 { 0%, 90%, 100% { clip-path: inset(0 0 100% 0); } 92% { clip-path: inset(0 0 55% 0); } 96% { clip-path: inset(8% 0 72% 0); } }
@keyframes gl2 { 0%, 88%, 100% { clip-path: inset(100% 0 0 0); } 90% { clip-path: inset(58% 0 10% 0); } 94% { clip-path: inset(72% 0 6% 0); } }

/* ============================================================
   ACT 2 — THE INDEX (force-directed graph of every item)
   A clean white field; nodes coloured + clustered by group, linked by thin grey
   edges, all floating gently (float driven by graph.js). Hover isolates a group;
   click enters that group's presentation.
   ============================================================ */
.act-index {
  position: absolute; inset: 0; z-index: 300; background: #fff;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .32s var(--ease), visibility .32s var(--ease);
}
.act-index.show { opacity: 1; visibility: visible; pointer-events: auto; }

/* both layers share one pan/zoom transform (set inline by graph.js); origin top-left so
   the wheel-zoom maths is simple. The .idx-ui (head + legend) is NOT transformed, so it
   stays pinned while the graph zooms/pans underneath. */
.idx-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; transform-origin: 0 0; }
.idx-edge { stroke: #c7ccdd; stroke-width: 1; transition: opacity 3s var(--ease), stroke 3s var(--ease); }
.idx-edge.cross { stroke: #dfe2ee; }
.idx-edge.dim { opacity: .05; }

.idx-nodes { position: absolute; inset: 0; z-index: 2; transform-origin: 0 0; }
/* each node wears the same flat "web window" chrome as the Act-3 canvas, with a soft float
   shadow; the title bar is tinted by the node's group colour (--gc set in graph.js). */
.idx-node {
  position: absolute; left: 0; top: 0; display: block; padding: 0; border: 0;
  background: transparent; cursor: none; will-change: transform;
  transition: opacity 3s var(--ease), filter 3s var(--ease);
}
.idx-node .win { width: 100%; height: 100%; box-shadow: none; }
.idx-node .winbar { background: var(--gc, #9aa3bd); text-shadow: 0 1px 0 rgba(0, 0, 0, .28); }
.idx-node .wb-title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.idx-node .wb-grp { font-size: 6px; padding: 1px 2px; letter-spacing: 0; }
.idx-node .winbody img, .idx-node .winbody video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* text cards: same notepad look as Act 3, but the type is scaled WAY down to suit the small
   index windows (≈ the same text-to-window ratio as the full-size Act-3 cards). */
.idx-node .textcard { padding: 5px 6px; font-size: 6.5px; line-height: 1.45; }
.idx-node.idx-broken .winbody { background: repeating-linear-gradient(45deg, #f3f4fa 0 6px, #e9ebf5 6px 12px); }
.idx-node:focus-visible { outline: none; }
.idx-node:hover .win, .idx-node:focus-visible .win { box-shadow: none; }
.idx-node.dim { opacity: .1; filter: grayscale(.95); }
.idx-node.lit { z-index: 5; }
.idx-node.lit .win { box-shadow: none; }

/* first-appearance entrance: each node "turns on" — fades up from dark with a soft glow, in a
   staggered order (per-node animation-delay set in graph.js). Only opacity/filter animate so the
   per-frame float transform isn't disturbed; the class is removed when done, returning the node
   to its normal state. */
@keyframes idxTurnOn {
  0%   { opacity: 0; filter: brightness(2.2) saturate(.4); }
  60%  { opacity: 1; }
  100% { opacity: 1; filter: none; }
}
.idx-node.idx-enter { animation: idxTurnOn .6s var(--ease) both; }

/* head + legend chrome */
.idx-ui { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.idx-head { position: absolute; top: 7.5vh; left: 50%; transform: translateX(-50%); text-align: center; display: flex; flex-direction: column; gap: 5px; }
.idx-kicker { font: 800 13px/1 var(--font-cond); letter-spacing: 4px; text-transform: uppercase; color: var(--blue); }
.idx-hint { font: 700 10px/1 var(--font-cond); letter-spacing: 1.2px; text-transform: uppercase; color: #8b91ab; }
.idx-legend { position: absolute; left: 14px; bottom: 56px; display: flex; flex-direction: column; gap: 5px; pointer-events: auto; }
.idx-leg {
  display: flex; align-items: center; gap: 8px; padding: 5px 9px 5px 6px; border: 0; cursor: none;
  background: var(--paper); box-shadow: inset 0 0 0 1px var(--hair);
  font: 700 10px/1 var(--font-cond); letter-spacing: 1px; text-transform: uppercase; color: var(--ink);
  transition: box-shadow .2s var(--ease), transform .2s var(--ease);
}
.idx-leg i { width: 12px; height: 12px; flex: 0 0 12px; background: var(--gc, #9aa3bd); }
.idx-leg em { font-style: normal; color: #8b91ab; margin-left: 2px; }
.idx-leg:hover, .idx-leg.active { box-shadow: inset 0 0 0 1px var(--gc), 0 4px 14px rgba(8, 16, 48, .14); transform: translateX(3px); }
.idx-leg.active i { box-shadow: 0 0 0 2px rgba(255,255,255,.6); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 820px) {
  .sidetext, .deco-echo.a { display: none; }
  .hud-title { font-size: 10px; }
  .vcaption { display: none; }
  .echoblock { font-size: 11px; }
  .folder-title { top: 11vh; }
}
@media (max-width: 520px) {
  .hud { flex-direction: column; }
  .menubar span:not(:first-child):not(.mb-clock) { display: none; }
  .statusstack { left: 30% !important; }
  .toolstrip { display: none; }
  .btn-nav { min-width: 72px; padding: 9px 10px; }
}
