/* ==========================================================================
   Air Market - v3 shell core (REDESIGN.md §11).

   v3 turns the sidenav into a commerce top nav. This file owns the SHELL and
   nothing else: hide the sidebar, turn .window into a column, put #topbar above
   .content, and declare the custom properties the four feature stylesheets
   consume. Cards, grids, heroes and typography are inherited from store-v2.css,
   whose selectors now read :root:is([data-ui="v2"],[data-ui="v3"],[data-ui="v4"],[data-ui="v5"]).

   v4 rides on this entire shell unchanged (V4-SPEC.md §2.3): it is a detail-page
   reorder, not a new shell, so every gate below reads "v3 or v4" rather than
   gaining a private v4 branch. store-v4.css only carries the detail-page deltas.

   LOAD ORDER (index.html): tokens → fonts → cursors → components → store →
   store-v2 → store-v3-core → store-v3-topnav → store-v3-mega →
   store-v3-filters → store-v3-stack → store-v4.

   EVERY rule here - and in the four feature files - is scoped under
   :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]), so v0, v1 and v2 render byte-identically.
   The one exception below is explicitly commented.

   HOUSE RULES: no hardcoded hex (tokens.css custom properties only); cursors
   only via var(--cur-*), never a bare `cursor: pointer`; JetBrains Mono only on
   machine identifiers; links at --color-brand-800 for contrast.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. THE SHARED v3 CUSTOM PROPERTIES - part of the contract.

   Declared on :root so every feature stylesheet can read them, and so a single
   edit here re-proportions the whole bar. Feature files must CONSUME these
   rather than repeating literals; if you need a new shared measurement, ask
   for it to be added here instead of inventing a private one.

   HEIGHTS
     --v3-tier1-h            tier 1, the utility / trust strip. Scrolls away
                             with the page? No - .content scrolls, the bar does
                             not, so tier 1 collapses to 0 via the condensed
                             state instead (see --v3-tier1-h-condensed).
     --v3-tier1-h-condensed  tier 1 once the reader has scrolled past
                             V3.CONDENSE_AT (40px). 0 = fully collapsed.
     --v3-bar-h              tier 2 at rest - wordmark, links, search, Stack.
     --v3-bar-h-condensed    tier 2 once condensed (64 → 56, REDESIGN §11.4).
     --v3-filterbar-h        tier 3, catalogue routes only.
     --v3-bar-total          convenience: tier 1 + tier 2. It is substituted at
                             USE time, so inside #topbar.is-condensed it already
                             resolves to the condensed heights. Anything that
                             needs to offset itself under the bar reads this
                             rather than summing the parts again.

   RHYTHM
     --v3-gutter             horizontal inset of every tier's inner row.
                             Matches .page's 40px padding so the wordmark lines
                             up with the page title beneath it.
     --v3-max                max inner width of a tier row and of .page under
                             v3. The bar is full-bleed; its CONTENT is capped.
     --v3-sb                 the scrollbar measure .content reserves on both
                             edges, mirrored as padding on #topbar so the two
                             capped rows stay concentric at every width. Tracks
                             `.content::-webkit-scrollbar { width }`, store.css
                             ~line 1027 - change both together or the bar and
                             the page drift apart again.

   LAYERS  (store.css uses z-index 20 for .sidebar-rail and nothing higher in
            the shell; Air_DS dialogs sit above everything via UI.openDialog.)
     --v3-z-bar              the topbar itself.
     --v3-z-scrim            the dim behind an open mega panel.
     --v3-z-mega             the mega panel, above the scrim, below the bar's
                             own tier 2 so the toggle stays clickable.

   MOTION
     --v3-ease               the single transition used by the condense effect.
                             Respect prefers-reduced-motion (bottom of file).
     --v3-ease-t             its duration alone, for the one place a delay has
                             to agree with it: tier 1 defers visibility:hidden
                             until the strip has finished closing (topnav §2).

   COLOUR ALIASES
     v3 inherits v2's palette rather than inventing a second one. These four
     aliases exist so a v3 file never has to write `--v2-*`; they resolve to the
     same tokens. --v2-ink / --v2-paper / --v2-field / --v2-line / --v2-verif
     are declared in store-v2.css under the widened selector, so they are live
     under [data-ui="v3"] and [data-ui="v4"] alike.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) {
  --v3-tier1-h: 32px;
  --v3-tier1-h-condensed: 0px;
  --v3-bar-h: 64px;
  --v3-bar-h-condensed: 56px;
  --v3-filterbar-h: 48px;
  --v3-bar-total: calc(var(--v3-tier1-h) + var(--v3-bar-h));

  --v3-gutter: var(--space-40);
  --v3-max: 1440px;
  --v3-sb: 14px;

  --v3-z-bar: 60;
  --v3-z-scrim: 55;
  --v3-z-mega: 58;

  --v3-ease-t: 160ms;
  --v3-ease: var(--v3-ease-t) ease;

  /* Palette aliases - same values v2 uses, v3-facing names. */
  --v3-ink: var(--v2-ink);
  --v3-paper: var(--v2-paper);
  --v3-field: var(--v2-field);
  --v3-line: var(--v2-line);
  --v3-verif: var(--v2-verif);
}

/* --------------------------------------------------------------------------
   2. RETIRE THE SIDEBAR (visually - the markup MUST stay).

   app.js's mount guard is `if (!content || !si) return;` with si = #sideSearch,
   and renderSidebar() dereferences #nav with no null check, so deleting the
   sidebar from index.html blanks the entire app with no console error. It is
   hidden here instead. #sidebarTrigger, #sidebarRail and #sideSearchBox go with
   it; ⌘B still toggles a data-sidebar value nothing renders, which is harmless.

   display:none rather than visibility/width:0 so the hidden subtree is out of
   the accessibility tree and out of the tab order too - a keyboard user must
   not tab through eight invisible nav buttons before reaching the top bar.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .sidebar,
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .sidebar-rail { display: none; }

/* --sidebar-w still resolves (store.css declares it unconditionally) and the
   collapse transition is still armed. Neutralise both so no stale state can
   reach through: nothing in v3 consumes the variable, but a future rule might. */
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) { --sidebar-w: 0px; }

/* --------------------------------------------------------------------------
   3. THE COLUMN SHELL.

   .window is a flex ROW in store.css (sidebar | content). v3 turns it into a
   column so #topbar stacks above .content. .content keeps flex:1 and
   overflow-y:auto, which is what makes route()'s three `content.scrollTop = 0`
   resets keep working and is why the bar needs no position:sticky at all - it
   is simply not inside the scrolling box.

   min-height:0 on .content is the flexbox footgun this layout would otherwise
   hit: a flex item's default min-height is auto, so a tall child would stretch
   the item past the container instead of scrolling inside it.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .window {
  flex-direction: column;
}

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .content {
  min-height: 0;
  /* The bar centres a --v3-max row inside the full window width; .page centres
     the same measure inside .content, which is 14px narrower because it carries
     the scrollbar. Measured in-browser: the wordmark landed at x=184 and the
     page title at x=177, a visible 7px disagreement on the one edge v3 asks the
     reader to read down. Reserving the gutter on BOTH edges makes .content's
     content box concentric with the window, so the two agree exactly - and it
     also stops the whole page shifting when a short route has no scrollbar. */
  scrollbar-gutter: stable both-edges;
}

/* --------------------------------------------------------------------------
   4. #topbar - the frame only.

   Everything visible inside the bar (tiers, wordmark, links, search, slots)
   belongs to store-v3-topnav.css. This file guarantees three things and stops:
   the bar is visible under v3, it does not scroll, and it does not shrink.

   [hidden] is on the element in index.html so v0/v1/v2 never paint it. The
   attribute is removed by V3.mountShell() under v3; the rule below is the
   belt-and-braces for the frame between first paint and the first route.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar {
  position: relative;
  z-index: var(--v3-z-bar);
  flex: none;
  display: flex;
  flex-direction: column;
  background: var(--v3-paper);
  border-bottom: 1px solid var(--v3-line);
  /* The mega panel drops out of the bar, so overflow must not clip it. */
  overflow: visible;
  transition: height var(--v3-ease);
  /* Concentric with .content at EVERY width. .content reserves --v3-sb on both
     edges (scrollbar-gutter, §3); the bar is outside that box, so without the
     same inset the two --v3-max rows centre on different boxes. Reserving it
     only on .content fixed the disagreement above ~1470px and created a
     14px one across 1024-1440 - the exact band v3 is scoped to. Padding
     both boxes identically is what makes the alignment width-independent. */
  padding-inline: var(--v3-sb);
}

/* Un-hide under v3 or v4 only. The attribute selector beats [hidden]'s UA
   display:none because it is more specific, but say it explicitly so the
   intent survives a refactor. */
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar[hidden] { display: flex; }

/* Outside v3/v4 the bar must be gone even if JS never ran (file:// with
   scripts blocked, or a mid-session switch before the next route). This is
   the one rule in the file not scoped to "is v3 or v4" - it scopes to
   "is neither v3 nor v4", which is the same guarantee from the other side. */
:root:not(:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"])) #topbar { display: none !important; }

/* --------------------------------------------------------------------------
   5. THE CONDENSED STATE.

   Core owns the scroll subscription (exactly one, for the life of the page) and
   toggles `.is-condensed` on #topbar past V3.CONDENSE_AT. Feature files style
   `:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar.is-condensed …` - do not add another scroll
   listener, and do not toggle this class yourself.

   Only the heights change here; what the tiers do with the space is theirs.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar.is-condensed {
  --v3-tier1-h: var(--v3-tier1-h-condensed);
  --v3-bar-h: var(--v3-bar-h-condensed);
}

/* --------------------------------------------------------------------------
   6. THE PAGE, WIDENED.

   232px of sidebar came back (REDESIGN §11.2 - "full width for the grid"), so
   the measure grows from v2's 1320px to --v3-max. Deliberately checked: the
   inherited .card-grid is repeat(auto-fill, minmax(258px, 1fr)) with a 20px
   gap, which still lands on FOUR columns at this width - the cards get wider,
   the rhythm does not change, and the 16:10 output preview §3 made the point of
   the card gets more room. Revert by deleting this one rule.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .page {
  max-width: var(--v3-max);
  padding-left: var(--v3-gutter);
  padding-right: var(--v3-gutter);
}

/* --------------------------------------------------------------------------
   7. THE DESIGN SWITCH, RELOCATED.

   store-v2.css's .ui-switch rule assumes the sidebar's flex column
   (margin-top:auto) and is deliberately NOT widened to v3 or v4. v3 renders
   its own copy - V3.uiSwitchHTML(), markup-compatible, id-less so it cannot
   collide with #uiSwitch - into [data-v3-slot="uiswitch"] in tier 1, and v4
   reuses that same v3 copy since it shares the shell. Core injects it as a
   fallback if topnav somehow doesn't, because without it a reviewer who lands
   on v3 or v4 has no way back to v2.

   The shared, unscoped .ui-switch-seg rules in store-v2.css do the rest, so
   only the wrapper needs a home here. Its buttons are literal version
   identifiers, which is the one sanctioned use of mono in the chrome.
   -------------------------------------------------------------------------- */

:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: 11px;
  color: var(--text-3);
}
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch-label { font-weight: 500; }

/* The shared `.ui-switch-seg button { color: var(--text-3) }` in store-v2.css
   measures 4.39:1 against the sunken strip these buttons sit on - --text-3's
   4.81:1 is a figure against WHITE. Corrected for v3 and v4 only: widening the
   shared rule would change how v1 and v2 paint, and they must stay
   byte-identical. (v1/v2 keep the pre-existing 4.39:1 on this control;
   flagged, not fixed.) */
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch-seg button { color: var(--text-2); }

/* store-v2.css's three collapsed-sidebar rules (lines ~392-394) are UNSCOPED -
   they key off [data-sidebar], not [data-ui] - so they reach into the topbar's
   copy of the switch and stack it into an 84px vertical column clipped inside
   the 32px tier-1 strip, with the outer buttons unclickable. Neither v3 nor v4
   has a sidebar, but data-sidebar="collapsed" still arrives: persisted in
   localStorage by any earlier v1/v2 session and re-applied pre-paint by
   index.html. That put the reviewer's only way back to v2 one keystroke from
   destruction, so the state has to be neutralised here rather than merely
   prevented at the keystroke. Specificity (1,3,0) beats the (0,3,0) rules it
   corrects - unchanged by widening, since :is() takes the highest specificity
   of its arguments rather than summing them. */
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch-seg { flex-direction: row; }
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch-label { display: inline; }
:root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar .ui-switch {
  justify-content: flex-start;
  padding-left: 0;
  padding-right: 0;
}

/* --------------------------------------------------------------------------
   8. Motion.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) #topbar { transition: none; }
}
