/* Showroom — scroll-tied parallax depth + spotlight glow (Showroom-owned file; AboutUs/site/assets/
   site.css is NEVER edited from here, per the hard boundary). This PORTS THE CONCEPT from site.css's
   "SCROLL-TIED PARALLAX DEPTH + SPOTLIGHT SHADOWS" system (search that string in site.css for the
   original), reimplemented against Showroom's OWN page shape — it does not reuse site.css's selectors,
   because Showroom's tool pages don't have a .hero/.sec window-panel layout at all (they're a single
   centered `.room` column: `.room-head` crumb+title+lede+badges, then a sequence of panel-shaped blocks
   — `.stat` cards, `.cr-curve`/`.cr-log`/`.cr-stage`/`.fc-stage`/`.or-runs`, or Analyst's `.chart-card`/
   `.col-card`/`.chip`). Same mechanism, same tuning philosophy, different anchor elements:
     - Tier "far"  = an ambient wallpaper wash on <main> (every route renders inside it — see
       Layout/MainLayout.razor), tied to the WHOLE document's scroll (scroll(root)). No shadow — it IS
       the backdrop, not an object with depth of its own. Direct analogue of site.css's
       `body.os-chrome` wallpaper.
     - Tier "near" = `.room-head`, the first thing on every tool page and the thing that most visibly
       scrolls away — the closest Showroom equivalent to site.css's `.prism-beam` foreground graphic
       (Showroom has no decorative hero SVG, so the hero TEXT BLOCK itself plays that role here).
     - Tier "mid"  = the panel-shaped UI blocks a tool actually presents (see class list below) —
       direct analogue of site.css's `.sec:has(.sec-head)` window panels, settling into place as they
       scroll into view.
   Zero JS, zero scroll listener: pure `animation-timeline: scroll()/view()`, gated entirely inside
   `@media (prefers-reduced-motion:no-preference)` exactly like site.css, same reason (a JS scroll
   handler would fight the mobile perf budget the whole app is already tuned around — see CLAUDE.md
   "Real WASM multithreading"/boot-screen sections for how seriously this app treats that budget).

   MAGNITUDE: starts from site.css's ALREADY-TRIPLED, real-device-corrected numbers (that file's own
   history: an initial "close inspection" tuning was found imperceptible on a real phone and tripled) —
   not the original subtle pass, so this doesn't repeat that mistake. translateY travel, drop-shadow
   blur/spread, and alpha % below are the same magnitudes site.css settled on for its own near/mid
   tiers.

   ANGLE — re-derived, not copied: site.css's tier "near" (`.prism-beam`) uses an off-centre shadow
   (X != 0) because that graphic sits right-aligned in its hero. `.room-head` and every "mid" panel
   here are NOT off-centre — `.room` itself is a centred column (`margin:0 auto`) and every panel
   listed below is a full-width block inside it — so both tiers use the SAME straight-down (X=0)
   convention site.css's own "mid" tier uses for its centred panels. This is the page-structure
   judgement call the task asked for, not a blind copy-paste of site.css's near-tier numbers.

   OPACITY-MULTIPLIER TRAP — checked per site.css's own documented gotcha (a `filter:drop-shadow()`
   sits UNDER an element's own `opacity` and gets silently dimmed by it): every class below
   (`.room-head`, `.stat`, `.cr-curve`, `.cr-log`, `.cr-stage`, `.fc-stage`, `.or-runs`, `.chart-card`,
   `.col-card`, `.chip`) was checked against all four tools' own `.razor.css` files and none carries
   its own `opacity`. `.dropzone` (Analyst) was DELIBERATELY EXCLUDED from the mid-tier list for this
   exact reason — its `.dropzone.busy` state carries `opacity:.6`, which would dim this glow during a
   real upload-in-progress state; simpler to leave it out than special-case a transient state.

   BOX-SHADOW vs FILTER — same reasoning as site.css: none of these classes currently carry a static
   `box-shadow` of their own (checked; they only use `border`/`border-left`), so there's nothing to
   duplicate — still `filter:drop-shadow()`, not an animated `box-shadow`, to match the site's own
   established choice and stay compositor-cheap.

   PER-PACKAGE RECOLOUR (2026-08-28, follow-up to the placeholder note this comment used to carry):
   the website's 4-bucket Foundation/Data/ML/Spatial model was replaced by a distinct hue per NuGet
   package (see AboutUs/site/assets/site.css's ":root" per-package palette table + AboutUs/CLAUDE.md's
   "Per-package palette" section for the full hex table + placement reasoning — that table is the
   single source of truth this file duplicates by hand, since there is no shared token file across the
   AboutUs/Showroom repo boundary, the same known limitation on record in both repos' CLAUDE.md). Each
   [data-cat] value below is now a real dependency name, not a bucket: "holodb" (Analyst, HoloDb only —
   was wrongly sharing --c-data blue with 3 unrelated tools), "algformer" (Forecaster/Prism, AlgFormer
   only — was wrongly sharing --c-ml violet with Creature despite a different real dependency set), and
   "algformer-tracer" (Creature, AlgFormer+Tracer — a genuine two-package composite, same situation as
   the static site's own prose.html chord). `var(--c-holodb, #66c1aa)` etc. follow the SAME pattern this
   file already used for the old bucket tokens: site.css IS linked into this same page (see
   wwwroot/index.html), so the var() resolves to the live token when site.css is present, falling back
   to the hand-typed hex (this file's own duplicated copy of the source-of-truth table) if it isn't —
   not a guess, the same fallback-authoritative convention already established here for --accent/
   --spectrum-1/--bg above. Creature's chord follows the same "hard-edged, not a soft blend" mechanism
   site.css uses for its own chord pages: TWO stacked drop-shadow() layers (see the *-chord keyframes
   and their [data-cat="algformer-tracer"] override selectors below), never a single color-mix()'d
   third hue — a real two-tone glow, not a purple compromise between blue and coral. */

.room[data-cat="holodb"]{ --glow-near:var(--c-holodb, #66c1aa); --glow-mid:var(--c-holodb, #66c1aa); }
.room[data-cat="algformer"]{ --glow-near:var(--c-algformer, #5998ff); --glow-mid:var(--c-algformer, #5998ff); }

/* Prose's chord: HoloDb (mined-knowledge store) + AlgFormer (optional plausibility HoloFormer), both
   real dependencies (Prose.csproj ProjectReferences both; ProseEngine.Store is a ProseStore backed by
   HoloDb, TrainPlausibilityText/Plausibility is a PrismFormer.HoloFormer.Mini) — same genuine two-
   package composite situation as Creature (above) and the static site's own prose.html chord
   (body[data-cat="holodb-algformer"] there). HoloDb sits before AlgFormer here to match the site's own
   canonical Foundation->Data->ML domain order (packages.html's own section order), same convention
   Creature's algformer-tracer chord above follows. */
.room[data-cat="holodb-algformer"]{
  --glow-near:var(--c-holodb, #66c1aa);
  --glow-mid:var(--c-holodb, #66c1aa);
  --glow-near-a:var(--c-holodb, #66c1aa);
  --glow-near-b:var(--c-algformer, #5998ff);
  --glow-mid-a:var(--c-holodb, #66c1aa);
  --glow-mid-b:var(--c-algformer, #5998ff);
}

/* Creature's chord: AlgFormer (brain) + Tracer (pathfinding), both real dependencies (see
   Creature.razor's own @using PrismFormer / @using Tracer.Helpers + GridTactics.Reachable call).
   --glow-near/--glow-mid still get a plain single-tone fallback (AlgFormer) here, same role
   site.css's --cat-root plays for its own chord cards — a safety net for any current or future
   mid/near-tier element inside this room that isn't in the *-chord override selector list below. */
.room[data-cat="algformer-tracer"]{
  --glow-near:var(--c-algformer, #5998ff);
  --glow-mid:var(--c-algformer, #5998ff);
  --glow-near-a:var(--c-algformer, #5998ff);
  --glow-near-b:var(--c-tracer, #f0796a);
  --glow-mid-a:var(--c-algformer, #5998ff);
  --glow-mid-b:var(--c-tracer, #f0796a);
}

/* Static wallpaper wash — unconditional (visible with or without reduced-motion; only the DRIFT below
   is motion-gated), same 3-stop mix as site.css's own body.os-chrome wallpaper (accent violet + data
   blue + warm coral) so Showroom reads as one brand with the static site even before any animation
   kicks in. Applied to <main> (Layout/MainLayout.razor wraps every route in exactly one <main>@Body</
   main>, verified — no other <main> element exists anywhere in this app) rather than <body>, because
   <body> lives in the single shared wwwroot/index.html and can't carry a per-route data-cat attribute
   the way the static site's per-page <body data-cat="..."> can. */
main{
  background:
    radial-gradient(1100px 560px at 12% -8%, color-mix(in srgb, var(--accent, #8b7dff) 9%, transparent), transparent 60%),
    radial-gradient(900px 520px at 100% 0%, color-mix(in srgb, var(--spectrum-5, #4aa3ff) 7%, transparent), transparent 55%),
    radial-gradient(820px 480px at 46% 104%, color-mix(in srgb, var(--spectrum-1, #f0796a) 7%, transparent), transparent 55%),
    var(--bg, #050608);
}

@media (prefers-reduced-motion:no-preference){
  @keyframes sr-parallax-far{
    from{ background-position: 0% 0%, 0% 0%, 0% 0%, 0% 0%; }
    to{ background-position: 0% 12%, 0% -9%, 0% 6%, 0% 0%; }
  }
  @keyframes sr-parallax-near{
    from{ transform: translateY(0); filter: drop-shadow(0 32px 24px color-mix(in srgb, var(--glow-near, #fff) 55%, transparent)); }
    to{ transform: translateY(-70px); filter: drop-shadow(0 16px 12px color-mix(in srgb, var(--glow-near, #fff) 25%, transparent)); }
  }
  @keyframes sr-parallax-mid{
    from{ transform: translateY(30px); filter: drop-shadow(0 12px 15px color-mix(in srgb, var(--glow-mid, var(--accent)) 20%, transparent)); }
    to{ transform: translateY(0); filter: drop-shadow(0 36px 48px color-mix(in srgb, var(--glow-mid, var(--accent)) 55%, transparent)); }
  }

  /* CHORD keyframes (Creature only, [data-cat="algformer-tracer"]) — same transform/timing/angle math
     as sr-parallax-near/-mid above, only the filter carries TWO stacked drop-shadow() layers (one per
     domain colour, --glow-*-a/--glow-*-b) instead of one — a real two-tone glow, not a color-mix()'d
     blend into a third hue. Mirrors site.css's own ea-parallax-mid-chord mechanism (search that name in
     AboutUs/site/assets/site.css) — Showroom additionally chords the "near" tier (.room-head), since
     unlike site.css's page-specific .prism-beam, Showroom's near tier (the hero text block) appears on
     every tool page and so needs a real per-page tint here too, not just the mid tier. */
  @keyframes sr-parallax-near-chord{
    from{ transform: translateY(0); filter: drop-shadow(0 32px 24px color-mix(in srgb, var(--glow-near-a, #5998ff) 55%, transparent)) drop-shadow(0 32px 24px color-mix(in srgb, var(--glow-near-b, #f0796a) 55%, transparent)); }
    to{ transform: translateY(-70px); filter: drop-shadow(0 16px 12px color-mix(in srgb, var(--glow-near-a, #5998ff) 25%, transparent)) drop-shadow(0 16px 12px color-mix(in srgb, var(--glow-near-b, #f0796a) 25%, transparent)); }
  }
  @keyframes sr-parallax-mid-chord{
    from{ transform: translateY(30px); filter: drop-shadow(0 12px 15px color-mix(in srgb, var(--glow-mid-a, #5998ff) 20%, transparent)) drop-shadow(0 12px 15px color-mix(in srgb, var(--glow-mid-b, #f0796a) 20%, transparent)); }
    to{ transform: translateY(0); filter: drop-shadow(0 36px 48px color-mix(in srgb, var(--glow-mid-a, #5998ff) 55%, transparent)) drop-shadow(0 36px 48px color-mix(in srgb, var(--glow-mid-b, #f0796a) 55%, transparent)); }
  }

  /* Tier "far" — tied to scroll(root), the whole document's own scroll range, so the drift only
     completes once the entire page has been scrolled — the slowest-reading layer, exactly what a
     distant backdrop should do. Unconditional across all viewports (matches site.css's own tier-far
     scope), since it's cheap (background-position only) and site.css itself doesn't width-gate it. */
  main{
    animation-name: sr-parallax-far;
    animation-timing-function: linear;
    animation-timeline: scroll(root);
  }

  /* >=901px matches site.css's own breakpoint for its near/mid tiers (and Showroom's own tablet/
     desktop boundary — every tool's .razor.css already uses 640px as the ONLY narrow-viewport
     breakpoint, so 901px sits cleanly above it with no new tuning needed). Below this, room-head and
     the panel list render exactly as they do today — flat, motionless — same "don't add a half-tuned
     third chrome variant for tablet" call site.css itself made. */
  @media (min-width:901px){
    /* Tier "near" — .room-head (crumb + h1 + lede + badges), the first block on every tool page and
       the one that most visibly scrolls past. view() timeline scoped to room-head's OWN visibility
       (an exit, same technique as site.css's .prism-beam tier), not the whole document. Also applied
       to .hero — Home.razor (the "/" tool gallery, `@page "/"`) reuses site.css's own .hero class
       verbatim (no Showroom-scoped equivalent exists for that page), so this is the one place this
       file's selectors reach a site.css-defined class name; still a Showroom-owned RULE in a
       Showroom-owned file, not an edit to site.css itself. Home.razor has no single package domain to
       tag (it lists all four tools), so it gets no [data-cat] override and falls through to the
       var(--glow-near,#fff)/var(--glow-mid,var(--accent)) defaults in the keyframes above — same
       "no single focus -> site accent default" call site.css itself makes for index.html/packages.html. */
    .room-head, .hero{
      animation-name: sr-parallax-near;
      animation-timing-function: linear;
      animation-timeline: view();
    }

    /* Chord override (Creature only) — same specificity-wins mechanism site.css uses for its own
       chord override (an attribute-selector-qualified rule naturally beats the bare class selector
       above; every other animation-* property still cascades from the base rule, only animation-name
       changes here). Higher specificity ([data-cat=...] + .room-head vs. bare .room-head) means this
       doesn't need !important or to come after the base rule in source order, though it does anyway. */
    .room[data-cat="algformer-tracer"] .room-head,
    .room[data-cat="holodb-algformer"] .room-head{
      animation-name: sr-parallax-near-chord;
    }

    /* Tier "mid" — every panel-shaped block a tool actually presents. One shared rule (comma-separated
       selectors) covers all four tools without a per-tool CSS fork: .stat/.cr-curve/.cr-log/.cr-stage/
       .fc-stage/.or-runs (Creature, Forecaster, Prism's stat cards + curve/log/stage/REPL panels) and
       .chart-card/.col-card/.chip (Analyst, which has no .stat/.cr-* shape of its own).
       DELIBERATELY NOT INCLUDED: Home.razor's `.card.tool` gallery cards — site.css's `.card:hover`
       already animates its OWN `transform:translateY(-2px)`, and a running scroll-linked animation's
       value for the SAME property wins over an ordinary hover rule in the cascade, so adding this
       tier there would have silently broken the existing hover-lift affordance on every tool card.
       Fixing that properly needs a wrapper element (animate the wrapper's transform, leave `.card`'s
       own hover transform alone) — flagged as follow-up, not attempted in this pass. Each panel below
       settles a few px as it individually scrolls into view (animation-range caps it to the first 45%
       of its own entry — a quick settle, not a long drift), same as site.css's own tier "mid". */
    .stat, .cr-curve, .cr-log, .cr-stage, .fc-stage, .or-runs,
    .chart-card, .col-card, .chip, .pr-panel, .pr-out, .cg-panel{
      animation-name: sr-parallax-mid;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 0% entry 45%;
    }

    /* Chord override (Creature only) — same reasoning as the near-tier override above. Lists only the
       mid-tier classes Creature's own .razor.css actually uses (.stat/.cr-curve/.cr-log/.cr-stage,
       verified by grep) rather than the whole shared list, since .fc-stage/.or-runs/.chart-card/
       .col-card/.chip can never appear inside a [data-cat="algformer-tracer"] room — this is Creature's
       only data-cat value site-wide, not a hedge against a future tool reusing it. */
    .room[data-cat="algformer-tracer"] .stat,
    .room[data-cat="algformer-tracer"] .cr-curve,
    .room[data-cat="algformer-tracer"] .cr-log,
    .room[data-cat="algformer-tracer"] .cr-stage,
    .room[data-cat="holodb-algformer"] .pr-panel,
    .room[data-cat="holodb-algformer"] .pr-out{
      animation-name: sr-parallax-mid-chord;
    }
  }
}
