/* ==========================================================================
   IX · HEADER — the sticky bar's scroll posture.

   State comes from elsewhere; appearance lives here:
   · main.js flips `.is-scrolled` on .rb-nav at scrollY > 8.
   · The studio mirrors the variant onto body[data-rbs-header].
   · js/areas/header.js adds `.rbs-header-hidden` (retreat), `.rbs-header-flip`
     (invert + float, past the flip distance), writes --rbs-header-scroll-p
     (0–1 scroll fraction) onto .rb-nav, and builds two runtime elements:
     .rbs-navplate (float's card) and .rbs-navrail (rail's section ticks).

   Knobs
     --rbs-header-blur      condense — backdrop blur, px        (12px)
     --rbs-header-bg-a      condense — surface opacity, 0–1     (0.85)
     --rbs-header-ink       invert   — the flipped bar's tone   (ink)
     --rbs-header-float-x   float    — side inset, px           (32px)
     --rbs-header-float-y   float    — top gap, px              (12px)
     --rbs-header-rail-h    rail     — rail height, px          (28px)
     --rbs-header-progress  all — 2px progress hairline on/off  (0)
   JS-read (no cssVar): reveal · flipAfter · railSize · railFill.

   Motion gates
     Geometry morphs (bar padding, logo scale, retreat slide, the float
     clip) run only at data-rbs-motion-level="authored". Paint fades
     (shadow, hairline, surface, the invert recolour) survive "essential" —
     reduced motion keeps colour, drops travel; invert's curtain stops
     travelling and cross-fades in place instead. "static" snaps everything
     and hides the progress hairline.
   ========================================================================== */

/* --- BASIC — refined scrolled treatment ----------------------------------
   Ships as `current`: also correct with the studio absent (no body attr),
   and inert with all JS absent (.is-scrolled never appears). Retreat keeps
   this scrolled treatment too; condense overrides it below. */
.rb-nav {
  transition:
    box-shadow   var(--rb-sys-duration-2) ease,
    border-color var(--rb-sys-duration-2) ease;
}

.rb-nav.is-scrolled {
  border-block-end-color: var(--rb-sys-border-default);
  box-shadow: var(--rb-ref-shadow-md);
}

/* --- CONDENSE — slim, translucent, blur-fade edge ------------------------ */
body[data-rbs-header="condense"] .rb-nav {
  transition:
    background-color var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    -webkit-backdrop-filter var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    backdrop-filter var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    border-color var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    box-shadow var(--rb-sys-duration-2) ease;
}

body[data-rbs-header="condense"] .rb-nav.is-scrolled {
  /* solid fallback first — browsers without color-mix stay on canvas */
  background: var(--rb-sys-bg-canvas);
  background: color-mix(in srgb,
    var(--rb-sys-bg-canvas) calc(var(--rbs-header-bg-a, 0.85) * 100%),
    transparent);
  -webkit-backdrop-filter: blur(var(--rbs-header-blur, 12px));
  backdrop-filter: blur(var(--rbs-header-blur, 12px));
  border-block-end-color: transparent;
  box-shadow: none;
}

/* Bar eases down 84px → 68px; the logotype settles to 0.92 toward its left
   edge. Geometry is motion-pass material: transitions gate on "authored",
   so reduced motion still condenses — instantly. */
body[data-rbs-header="condense"] .rb-nav.is-scrolled .rb-nav__bar {
  padding-block: var(--rb-ref-space-3);
}

body[data-rbs-header="condense"] .rb-nav__logotype {
  transform-origin: 0 50%;
}
body[data-rbs-header="condense"] .rb-nav.is-scrolled .rb-nav__logotype {
  transform: scale(0.92);
}

body[data-rbs-motion-level="authored"][data-rbs-header="condense"] .rb-nav__bar {
  transition: padding var(--rb-sys-duration-3) var(--rb-sys-ease-morph);
}
body[data-rbs-motion-level="authored"][data-rbs-header="condense"] .rb-nav__logotype {
  transition: transform var(--rb-sys-duration-3) var(--rb-sys-ease-morph);
}

/* Blur-fade edge — the studied replacement for a hard shadow line: ~16px of
   backdrop blur hanging below the bar, masked to nothing. Follows the blur
   knob at half strength. */
body[data-rbs-header="condense"] .rb-nav::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  height: var(--rb-ref-space-4);
  pointer-events: none;
  -webkit-backdrop-filter: blur(calc(var(--rbs-header-blur, 12px) * 0.5));
  backdrop-filter: blur(calc(var(--rbs-header-blur, 12px) * 0.5));
  -webkit-mask-image: linear-gradient(to bottom, var(--rb-ref-black), transparent);
  mask-image: linear-gradient(to bottom, var(--rb-ref-black), transparent);
  opacity: 0;
  transition: opacity var(--rb-sys-duration-3) var(--rb-sys-ease-swift);
}
body[data-rbs-header="condense"] .rb-nav.is-scrolled::after { opacity: 1; }

/* --- RETREAT — hide fast going down, return calm on reach-up --------------
   State class comes from JS (direction + 8px hysteresis, never in the first
   viewport, never while the panel is open or the bar holds focus). */
body[data-rbs-header="retreat"] .rb-nav.rbs-header-hidden {
  transform: translateY(-100%);
}

/* Return: calm — 320ms morph. */
body[data-rbs-motion-level="authored"][data-rbs-header="retreat"] .rb-nav {
  transition:
    transform var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    box-shadow var(--rb-sys-duration-2) ease,
    border-color var(--rb-sys-duration-2) ease;
}

/* Hide: exits are faster — 240ms swift. Transitions retarget mid-flight, so
   a direction flip mid-slide bends the bar back without a restart. */
body[data-rbs-motion-level="authored"][data-rbs-header="retreat"] .rb-nav.rbs-header-hidden {
  transition-duration:
    calc(var(--rb-sys-duration-3) * 0.75),
    var(--rb-sys-duration-2),
    var(--rb-sys-duration-2);
  transition-timing-function: var(--rb-sys-ease-swift), ease, ease;
}

/* --- INVERT — the bar changes mode, not shape -----------------------------
   Past the flip distance the chrome goes ink and the type goes light. The
   ground is an ink curtain (.rb-nav::before) that opens from the bar's
   centre line outward — not a top-down wipe. That ordering is the whole
   trick: a wipe leaves the type row on white for the first half of the
   move, so light type on a light bar flashes; opening from the middle inks
   the type row in the first frames and the recolour can safely trail it.
   Swift (fast-out) for the same reason — the ground is essentially there by
   ~150ms, and the type follows 80ms in over 150ms.

   The curtain covers the whole header box, so an open mobile panel inverts
   with the bar instead of hanging white beneath an ink rail. */
body[data-rbs-header="invert"] .rb-nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--rbs-header-ink, var(--rb-ref-ink));
  transform: scaleY(0);
  transform-origin: 50% 50%;
  pointer-events: none;
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip::before { transform: scaleY(1); }
body[data-rbs-header="invert"] .rb-nav__bar { z-index: 1; }
body[data-rbs-header="invert"] .rb-nav__panel { position: relative; z-index: 1; background: transparent; }

/* Base = leaving (240ms), state = arriving (320ms). Exits are faster. */
body[data-rbs-motion-level="authored"][data-rbs-header="invert"] .rb-nav::before {
  transition: transform calc(var(--rb-sys-duration-3) * 0.75) var(--rb-sys-ease-swift);
}
body[data-rbs-motion-level="authored"][data-rbs-header="invert"] .rb-nav.rbs-header-flip::before {
  transition-duration: var(--rb-sys-duration-3);
}

/* Essential / static: keep the colour, drop the travel. The curtain is
   already full height and cross-fades instead — gentler, never dead. This
   is also the state with the studio absent, where the flip never happens.
   Static gets the same swap with no transition declared at all. */
body:not([data-rbs-motion-level="authored"])[data-rbs-header="invert"] .rb-nav::before {
  transform: scaleY(1);
  opacity: 0;
}
body:not([data-rbs-motion-level="authored"])[data-rbs-header="invert"] .rb-nav.rbs-header-flip::before {
  opacity: 1;
}
body[data-rbs-motion-level="essential"][data-rbs-header="invert"] .rb-nav::before {
  transition: opacity var(--rb-sys-duration-2) ease;
}

/* The scrolled hairline and shadow belong to a light bar; ink supplies its
   own edge. */
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip {
  border-block-end-color: transparent;
  box-shadow: none;
  /* the default ring is a mid-teal link colour — too quiet on ink */
  --rb-sys-focus-ring: var(--rb-ref-teal-400);
}

/* Type + marks. Links sit at 72% white so hover still has somewhere to go;
   the logotype and the CTA go the whole way. One rule carries the whole
   recolour; the pace lives in two inherited properties so the arrive/leave
   pair (and the static override) never have to repeat this list. */
body[data-rbs-header="invert"] .rb-nav {
  --rbs-header-flip-dur: var(--rb-sys-duration-2);
  --rbs-header-flip-delay: 0ms;
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip {
  --rbs-header-flip-dur: var(--rb-sys-duration-1);
  --rbs-header-flip-delay: 80ms;   /* lets the ink arrive under the type first */
}
body[data-rbs-header="invert"] .rb-nav :is(.rb-nav__link, .rb-nav__logotype, .rb-nav__toggle, .rb-nav__lang, .rb-nav__globe, .rb-nav__cta, .rb-field__row, .rb-field__input, .rb-field__icon, .rb-nav__search .rb-btn, .rb-nav__panel-item) {
  transition:
    color            var(--rbs-header-flip-dur) var(--rbs-header-flip-delay) ease,
    background-color var(--rbs-header-flip-dur) var(--rbs-header-flip-delay) ease,
    border-color     var(--rbs-header-flip-dur) var(--rbs-header-flip-delay) ease;
}

body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__link {
  color: var(--rb-sys-fg-on-dark);
  color: color-mix(in srgb, var(--rb-sys-fg-on-dark) 72%, transparent);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__link:hover,
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__logotype {
  color: var(--rb-sys-fg-on-dark);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__panel-item + .rb-nav__panel-item {
  border-block-start-color: var(--rb-sys-border-on-dark);
}

/* Language pill: a tinted glass chip instead of the teal fill, globe on the
   bright accent so the one spot of brand colour survives the flip. */
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__lang {
  background: var(--rb-sys-border-on-dark);
  background: color-mix(in srgb, var(--rb-sys-fg-on-dark) 12%, transparent);
  color: var(--rb-sys-fg-on-dark);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__globe { color: var(--rb-sys-fg-accent); }

body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__toggle {
  border-color: var(--rb-sys-border-on-dark);
  color: var(--rb-sys-fg-on-dark);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__toggle:hover {
  background: color-mix(in srgb, var(--rb-sys-fg-on-dark) 8%, transparent);
  border-color: color-mix(in srgb, var(--rb-sys-fg-on-dark) 32%, transparent);
}

/* Ask Rubrik: the field becomes a well in the ink, and its submit swaps the
   deep-teal fill for the bright accent, which is the pair that reads. */
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-field__row {
  background: transparent;
  border-color: var(--rb-sys-border-on-dark);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-field__row:focus-within {
  border-color: var(--rb-sys-fg-accent);
  box-shadow: none;
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip :is(.rb-field__input, .rb-field__icon) {
  color: var(--rb-sys-fg-on-dark);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-field__input::placeholder {
  color: color-mix(in srgb, var(--rb-sys-fg-on-dark) 56%, transparent);
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__search .rb-btn {
  background: var(--rb-sys-bg-accent);
  border-color: var(--rb-sys-bg-accent);
  color: var(--rb-sys-fg-on-accent);
}

/* The CTA carries the bar's own tone as its type colour, so the tone knob
   moves the whole mode together. */
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__cta {
  background: var(--rb-sys-fg-on-dark);
  border-color: var(--rb-sys-fg-on-dark);
  color: var(--rbs-header-ink, var(--rb-ref-ink));
}
body[data-rbs-header="invert"] .rb-nav.rbs-header-flip .rb-nav__cta:hover {
  background: var(--rb-sys-cta-secondary-bg-hover);
  border-color: var(--rb-sys-cta-secondary-bg-hover);
  color: var(--rbs-header-ink, var(--rb-ref-ink));
}

/* --- FLOAT — the bar detaches from the page edges -------------------------
   Past the flip distance the chrome stops being an edge and becomes a card:
   inset from three sides, rounded, lifted. The shape change is a clip-path
   on a runtime plate — never width/inset — so nothing lays out mid-flight.
   The plate nests two elements on purpose: filter is applied BEFORE
   clip-path on the same element, so a drop-shadow on the clipped face would
   be clipped away with it. Outer carries the shadow, inner carries the clip.

   Geometry: the plate hangs --float-y below the bar; at rest the face is
   clipped back to exactly the header's padding box (the bar's own hairline
   still shows beneath it), and floated it is clipped to a card of the same
   height, pushed down by the gap. The bar and the panel translate by the
   same gap, so content and card stay concentric through the whole move. */
.rbs-navplate {
  position: absolute;
  inset: 0 0 calc(-1 * var(--rbs-header-float-y, 12px)) 0;
  z-index: 0;
  pointer-events: none;
  filter: drop-shadow(0 0 0 transparent);
}
.rbs-navplate__face {
  display: block;
  height: 100%;
  background: var(--rb-sys-bg-canvas);
  clip-path: inset(0 0 var(--rbs-header-float-y, 12px) 0 round 0);
}

/* The bar hands its ground to the plate — but only once the plate is really
   in the DOM, so a module that never booted can't leave a see-through bar. */
body[data-rbs-header="float"] .rb-nav:has(.rbs-navplate) { background: transparent; }
body[data-rbs-header="float"] .rb-nav { box-shadow: none; }
body[data-rbs-header="float"] .rb-nav__bar { z-index: 1; }

body[data-rbs-header="float"] .rb-nav.rbs-header-flip { border-block-end-color: transparent; }
body[data-rbs-header="float"] .rb-nav.rbs-header-flip .rbs-navplate {
  filter: drop-shadow(var(--rb-ref-shadow-lg));
}
body[data-rbs-header="float"] .rb-nav.rbs-header-flip .rbs-navplate__face {
  clip-path: inset(
    var(--rbs-header-float-y, 12px)
    var(--rbs-header-float-x, 32px)
    0
    var(--rbs-header-float-x, 32px)
    round var(--rb-ref-radius-xl));
}

/* Content follows the card. The bar is clipped to the card's silhouette too,
   which keeps the progress hairline inside the rounded corners. (Anything
   that later needs to overflow the bar — a desktop dropdown panel — must
   live outside .rb-nav__bar, as the mobile panel already does.) */
body[data-rbs-header="float"] :is(.rb-nav__bar, .rb-nav__panel) {
  clip-path: inset(0 0 0 0 round 0);
}
body[data-rbs-header="float"] .rb-nav.rbs-header-flip :is(.rb-nav__bar, .rb-nav__panel) {
  transform: translateY(var(--rbs-header-float-y, 12px));
}
body[data-rbs-header="float"] .rb-nav.rbs-header-flip .rb-nav__bar {
  clip-path: inset(0 var(--rbs-header-float-x, 32px) 0 var(--rbs-header-float-x, 32px)
                   round var(--rb-ref-radius-xl));
}
body[data-rbs-header="float"] .rb-nav.rbs-header-flip .rb-nav__panel {
  clip-path: inset(0 var(--rbs-header-float-x, 32px) 0 var(--rbs-header-float-x, 32px) round 0);
  background: transparent;
  border-block-start-color: transparent;
}

body[data-rbs-motion-level="authored"][data-rbs-header="float"] :is(.rbs-navplate__face, .rb-nav__bar, .rb-nav__panel) {
  transition:
    clip-path var(--rb-sys-duration-3) var(--rb-sys-ease-morph),
    transform var(--rb-sys-duration-3) var(--rb-sys-ease-morph);
}
body[data-rbs-motion-level="authored"][data-rbs-header="float"] .rbs-navplate {
  transition: filter var(--rb-sys-duration-3) var(--rb-sys-ease-swift);
}
/* Arriving is the editorial move — 400ms expo, the card easing away from
   the edges. Leaving runs on the 320ms morph declared above: exits faster. */
body[data-rbs-motion-level="authored"][data-rbs-header="float"] .rb-nav.rbs-header-flip :is(.rbs-navplate, .rbs-navplate__face, .rb-nav__bar, .rb-nav__panel) {
  transition-duration: calc(var(--rb-sys-duration-4) * 0.8);
  transition-timing-function: var(--rb-sys-ease-expo);
}

/* --- RAIL — the bar holds still and reports where you are -----------------
   A strip of ticks hanging under the bar, one per <section>, built at
   runtime by the area module (which also writes --rbs-navrail-f, 0–1, per
   tick). It hangs rather than stacks: absolutely positioned, so switching
   into this variant moves nothing on the page.

   It duplicates no navigation — it reports position. The bar's own links
   stay the only interactive chrome here, so the rail is inert and hidden
   from assistive tech rather than being a second, worse menu.

   Compact by default (ticks only); labels arrive with the desktop bar at
   1200, where there is room to read them. */
.rbs-navrail {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + var(--rb-ref-border-hairline));
  display: flex;
  align-items: stretch;
  gap: var(--rb-ref-space-4);
  height: calc(var(--rbs-header-rail-h, 28px) * 0.45);
  padding-inline: var(--rb-nav-inset);
  background: var(--rb-sys-bg-canvas);
  border-block-end: var(--rb-ref-border-hairline) solid var(--rb-sys-border-subtle);
  pointer-events: none;
  transition: box-shadow var(--rb-sys-duration-2) ease;
}

.rbs-navrail__tick {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--rb-ref-space-1);
  padding-block-end: var(--rb-ref-space-1);
}

.rbs-navrail__label {
  display: none;
  font-family: var(--rb-sys-font-label);
  font-size: var(--rb-sys-text-l1-size);
  line-height: 1;
  letter-spacing: var(--rb-sys-text-l1-tracking);
  font-weight: var(--rb-sys-text-l1-weight);
  text-transform: uppercase;
  color: var(--rb-sys-fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--rb-sys-duration-2) ease;
}
.rbs-navrail__tick[data-active="true"] .rbs-navrail__label { color: var(--rb-sys-fg-primary); }

.rbs-navrail__track {
  display: block;
  height: var(--rb-ref-border-medium);
  background: var(--rb-sys-border-subtle);
}
/* Constant motion: the fill maps 1:1 to scroll, so no easing and no
   transition — except in step mode, where there is a real state change. */
.rbs-navrail__fill {
  display: block;
  height: 100%;
  background: var(--rb-sys-fg-primary);
  transform: scaleX(var(--rbs-navrail-f, 0));
  transform-origin: 0 50%;
}
body[data-rbs-motion-level="authored"] .rbs-navrail[data-fill="step"] .rbs-navrail__fill {
  transition: transform calc(var(--rb-sys-duration-4) * var(--rbs-motion-scale, 1)) var(--rb-sys-ease-expo);
}

/* The chrome now ends at the rail, so the scrolled shadow moves down to it. */
body[data-rbs-header="rail"] .rb-nav.is-scrolled { box-shadow: none; }
body[data-rbs-header="rail"] .rb-nav.is-scrolled .rbs-navrail { box-shadow: var(--rb-ref-shadow-md); }

@media (min-width: 1200px) {
  .rbs-navrail { height: var(--rbs-header-rail-h, 28px); }
  .rbs-navrail__label { display: block; }
  .rbs-navrail__tick { padding-block-end: var(--rb-ref-space-2); }
}

/* --- SCROLL PROGRESS — knob-gated 2px hairline ---------------------------
   Constant motion maps 1:1 to scroll: no easing, transform only. Invisible
   until the studio writes --rbs-header-progress: 1; with JS absent the
   fallbacks hold it at zero. */
.rb-nav__bar { position: relative; }

.rb-nav__progress {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: var(--rb-ref-border-medium);
  background: var(--rb-sys-bg-accent);
  transform: scaleX(var(--rbs-header-scroll-p, 0));
  transform-origin: 0 50%;
  opacity: var(--rbs-header-progress, 0);
  pointer-events: none;
}

/* --- STATIC — workspace 01, honestly -------------------------------------
   Everything snaps. The rail survives: it reports position rather than
   animating, and a stepped fill is exactly what static should look like. */
body[data-rbs-motion-level="static"] .rb-nav__progress { opacity: 0; }

body[data-rbs-motion-level="static"] .rb-nav,
body[data-rbs-motion-level="static"] .rb-nav::before,
body[data-rbs-motion-level="static"] .rb-nav::after,
body[data-rbs-motion-level="static"] .rb-nav__bar,
body[data-rbs-motion-level="static"] .rb-nav__panel,
body[data-rbs-motion-level="static"] .rb-nav__logotype,
body[data-rbs-motion-level="static"] .rbs-navplate,
body[data-rbs-motion-level="static"] .rbs-navplate__face,
body[data-rbs-motion-level="static"] .rbs-navrail,
body[data-rbs-motion-level="static"] .rbs-navrail__label,
body[data-rbs-motion-level="static"] .rbs-navrail__fill {
  transition-duration: 0s;
}

/* The invert recolour is paced by inherited properties — zero them at both
   ends rather than repeating the element list. */
body[data-rbs-motion-level="static"][data-rbs-header="invert"] .rb-nav,
body[data-rbs-motion-level="static"][data-rbs-header="invert"] .rb-nav.rbs-header-flip {
  --rbs-header-flip-dur: 0s;
  --rbs-header-flip-delay: 0s;
}
