
  /* ============ DESKTOP ============ */
  #desktop{position:fixed;inset:0;overflow:hidden;
    background:
      radial-gradient(1200px 700px at 78% -10%,rgba(90,160,255,.16),transparent 60%),
      radial-gradient(900px 600px at 10% 110%,rgba(var(--accent-rgb),.12),transparent 55%),
      linear-gradient(160deg,var(--bg1),var(--bg2) 55%,var(--bg3));
  }
  /* faint grid + wordmark */
  #desktop::before{content:"";position:absolute;inset:0;opacity:.5;pointer-events:none;
    background:
      linear-gradient(rgba(255,255,255,.025) 1px,transparent 1px) 0 0/44px 44px,
      linear-gradient(90deg,rgba(255,255,255,.025) 1px,transparent 1px) 0 0/44px 44px}
  .wmark{position:absolute;bottom:90px;right:44px;font-family:var(--mono);
    font-size:120px;font-weight:800;letter-spacing:-.04em;color:rgba(255,255,255,.03);
    pointer-events:none;user-select:none}
  /* ============ SUSPICION OVERLAY ============
     Heat 0-100 is the only real danger in the game and it used to be a number in a corner. The three
     tiers are the story's own (HEAT_LINES: 25/50/75), so the picture degrades in the same beat VECTOR
     tells you to cool down.

     TWO FAILED ATTEMPTS ARE BAKED INTO THESE NUMBERS.
     1. Black scanlines and saturate(.86) over a #0b1018 desktop measured a mean shift of 0.37/255 -
        invisible - and tier 3 came out WEAKER than tier 2, whose only extra was an edge vignette.
        Darkening a dark theme does nothing; what reads here is LIGHT scanlines and a brightness drop.
     2. Fixing that by washing the whole screen red made tier 2 sepia and threw away the app's navy.
        That was chasing the measurement instead of the design.
     So: light and colour DRAIN as heat climbs, globally. Red only ever invades the RIM, and only in
     the top tier. The centre of the screen stays recognisably this OS, because code is read there.

     Sits above the desktop, windows and the Wire, but UNDER the ceremony (z 400) and the time skip
     (z 600) - a promotion should never arrive through interference. */
  #heatfx{position:absolute;inset:0;pointer-events:none;z-index:146;display:none;overflow:hidden}
  #heatfx.t1,#heatfx.t2,#heatfx.t3{display:block}
  /* Scanlines are LIGHT, not dark: on this palette a black line lands on near-black and vanishes. */
  #heatfx::before{content:"";position:absolute;inset:0;
    background:repeating-linear-gradient(to bottom,rgba(255,255,255,0) 0 2px,rgba(255,255,255,.05) 3px,rgba(255,255,255,0) 4px)}
  #heatfx.t2::before{background:repeating-linear-gradient(to bottom,rgba(255,255,255,0) 0 2px,rgba(255,255,255,.08) 3px,rgba(255,255,255,0) 4px)}
  #heatfx.t3::before{background:repeating-linear-gradient(to bottom,rgba(255,255,255,0) 0 2px,rgba(255,255,255,.10) 3px,rgba(255,255,255,0) 4px)}
  /* t1 (25+) - something noticed. Present, but nothing you could point at. */
  #heatfx.t1{backdrop-filter:brightness(.97)}
  /* t2 (50+) - the signal is going: the light drops and the colour drains. Still navy, still yours. */
  #heatfx.t2{backdrop-filter:brightness(.88) saturate(.66)}
  /* t3 (75+) - one mistake from a meeting with security. */
  #heatfx.t3{backdrop-filter:brightness(.80) saturate(.48) contrast(1.14)}
  /* The rim closing in. Transparent at the centre by design - it must never tint what you are reading. */
  #heatfx.t2::after,#heatfx.t3::after{content:"";position:absolute;inset:0}
  #heatfx.t2::after{background:radial-gradient(112% 86% at 50% 48%,rgba(0,0,0,0) 52%,rgba(0,0,0,.34) 100%)}
  #heatfx.t3::after{animation:hxBreathe 5.5s ease-in-out infinite;
    background:radial-gradient(112% 86% at 50% 48%,rgba(255,48,36,0) 44%,rgba(255,42,30,.30) 100%),
               radial-gradient(112% 86% at 50% 48%,rgba(0,0,0,0) 50%,rgba(0,0,0,.30) 100%)}
  /* One slow band travelling down the screen - a failing signal, deliberately not a strobe. */
  #heatfx .hx-band{position:absolute;left:0;right:0;top:-25%;height:22%;display:none;
    background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.055),rgba(255,255,255,0))}
  #heatfx.t2 .hx-band,#heatfx.t3 .hx-band{display:block;animation:hxRoll 9s linear infinite}
  #heatfx.t3 .hx-band{animation-duration:5.5s;background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,150,130,.09),rgba(255,255,255,0))}
  @keyframes hxRoll{from{top:-25%}to{top:105%}}
  @keyframes hxBreathe{0%,100%{opacity:.78}50%{opacity:1}}
  /* Reduce motion keeps the INFORMATION and drops the movement: scanlines, dimming and rim stay,
     nothing travels and nothing pulses. */
  body.reduce-motion #heatfx .hx-band{display:none;animation:none}
  body.reduce-motion #heatfx.t3::after{animation:none;opacity:.9}

  /* ============ THE DESK ============
     Icons live top-left: #hud and #notifs own the top-right, the dock and the Wire own the bottom.
     Under #winlayer (z 50), because a desktop icon belongs beneath every window.
     pointer-events:none on the container so a click on bare desktop still reaches the desktop -
     the icons themselves take it back. */
  #deskicons{position:absolute;top:44px;left:10px;z-index:5;pointer-events:none;
    display:flex;flex-direction:column;flex-wrap:wrap;align-content:flex-start;gap:2px;
    max-height:calc(100% - 190px)}
  .dsk-i{pointer-events:auto;width:84px;padding:7px 4px 5px;border:0;background:none;cursor:default;
    display:flex;flex-direction:column;align-items:center;gap:3px;border-radius:9px;
    font:inherit;color:#fff;text-align:center}
  .dsk-i:hover{background:rgba(255,255,255,.07)}
  .dsk-i.sel{background:rgba(61,245,161,.16);box-shadow:inset 0 0 0 1px rgba(61,245,161,.4)}
  /* The label sits on top of a photograph, so it carries its own contrast rather than trusting the
     wallpaper to be dark where the text lands. */
  .dsk-nm{max-width:80px;font-size:10.5px;line-height:1.25;letter-spacing:.01em;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    text-shadow:0 1px 3px rgba(0,0,0,.95),0 0 8px rgba(0,0,0,.7)}
  .dsk-i.sel .dsk-nm{text-shadow:none}
