/* ═══════════════════════════════════════════════════════════════════════
   VWIO Layout Contract — sticky-offset chain, embedded-chrome suppression,
   container width and a responsive grid primitive.

   CH-2026-0811-LINK-DESIGNSYS-001 phase 1. Generalised from the grader
   pilot (rebuilt 2026-08-11), which had all four of these working
   correctly but only for itself. Load after tokens.css, before any
   page-local <style>:
     <link rel="stylesheet" href="/vwio/_shared/tokens.css?v=20260811a">
     <link rel="stylesheet" href="/vwio/_shared/layout.css?v=20260811a">

   Usage: apply these as COMPANION classes alongside a surface's own
   selectors, e.g. <div class="header vwio-header vwio-container">. This
   file never assumes a surface's element is literally named .header or
   .mode-tabs — only that it opts in with one of the classes below.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Sticky offset chain ──────────────────────────────────────────────
   Every surface sets --hdr-h (and --tabs-h, if it has a second sticky
   row) to its own measured height; anything beneath chains off these
   two variables instead of a hardcoded pixel guess. Defaults below are
   the grader pilot's own numbers — the only real data point phase 1 has
   to generalise from — override per surface as needed. A surface with
   no secondary tab row simply never sets --tabs-h and gets 0. */
:root{
  --hdr-h: 44px;
  --tabs-h: 0px;
}

.vwio-header{ position:sticky; top:0; z-index:100; height:var(--hdr-h) }
.vwio-tabs{ position:sticky; top:var(--hdr-h); z-index:99; height:var(--tabs-h) }
.vwio-sticky{ position:sticky; top:calc(var(--hdr-h) + var(--tabs-h)); z-index:98 }

/* ── Embedded chrome suppression ──────────────────────────────────────
   Inside the Command Center iframe the shell already shows the event
   name, date and active tab — repeating them is the same two-stacked-
   bars problem the staff nav hit earlier. Any element carrying
   .vwio-header is hidden and the sticky chain collapses to 0 so nothing
   beneath it floats in dead space. The embedding page is responsible
   for adding class="embedded" to <body> — grader does this via
   `if (window.self !== window.top) document.body.classList.add('embedded')`. */
body.embedded .vwio-header{ display:none }
body.embedded{ --hdr-h:0px }

/* ── Container width ──────────────────────────────────────────────────
   Reuses --bp-xl (tokens.css) rather than a second number — the
   platform's widest breakpoint and its content cap are already the same
   1100px in every surface that has both (the pilot and /vwio/sla/), so
   they stay one fact here too, not two. */
.vwio-container{
  max-width: var(--bp-xl,1100px);
  margin: 0 auto;
}

/* ── Responsive grid primitive ────────────────────────────────────────
   Single column until there is genuinely room for more than one, then
   auto-fills at a comfortable card width. Below --bp-lg this applies no
   grid at all — normal block flow, byte-for-byte how the grader pilot
   behaved before this file existed, including the fact that grid `gap`
   and a child element's own margin can both apply once the grid is
   active (an existing minor quirk carried over unchanged, not
   introduced here — see the WRIGHT report on this ticket).

   --grid-min lets a surface ask for a different card width without a
   second class; unset, it matches the pilot's own 340px exactly. */
@media(min-width:900px){ /* --bp-lg — keep this literal in sync with tokens.css; @media cannot read a custom property */
  .vwio-grid{
    display:grid;
    grid-template-columns:repeat(auto-fill,minmax(var(--grid-min,340px),1fr));
    gap:var(--space-2,8px);
    align-items:start;
  }
}
