/* ──────────────────────────────────────────────────────────────────────────
   RASA — Page transition motion

   Loaded on every page, BEFORE the page's own stylesheet, so a page can
   always override. Three responsibilities:

     1. The root paint colour, so no navigation can ever flash white.
     2. The readiness gate's hidden state.
     3. The cross-document View Transition keyframes.

   Design intent (dark luxury): the transition should read as one surface
   being replaced by another under the SAME fixed chrome — not as two
   documents being swapped. The nav and footer therefore hold still while
   only the content moves. That single choice is most of what separates a
   premium app transition from a web page fade.
   ────────────────────────────────────────────────────────────────────────── */

/* ── 1. Never flash white ─────────────────────────────────────────────────
   MEASURED BUG (2026-08-21): <html> computed background-color was
   rgba(0,0,0,0) — fully transparent — with only <body> painted #080C14.
   Between documents the browser paints the ROOT colour, so on any load
   slower than the local dev server the user gets a white/system-coloured
   frame. This one line is the fix, and it matters most on the slow mobile
   connections the store reviewers will use.

   The colour is the brand background token, hardcoded here because this
   file must be able to paint before styles.css has parsed its variables. */
html {
  background-color: #080c14;
}

/* Overscroll (rubber-band past the top/bottom on trackpads and touch) also
   reveals the root colour. Same fix, stated explicitly. */
html,
body {
  background-color: #080c14;
}

/* ── 2. The readiness gate ────────────────────────────────────────────────
   visibility:hidden — NOT display:none. The page still lays out at its real
   dimensions, so when it appears there is zero layout shift; display:none
   would collapse the layout and cause exactly the footer-jump we are fixing.

   Scoped to <body> so the nav's fixed chrome and the page background are
   still painted — the user sees the brand surface, never a blank void. */
html[data-rasa-gate] body > *:not(nav):not(.nav):not(.cursor-glow):not(#topoCanvas) {
  visibility: hidden;
}

/* When the gate lifts, content appears with a short settle. Opacity+transform
   only — both composited, so this cannot cause layout work on reveal.

   SCOPED TO `:not(.rasa-vt)` ON PURPOSE. When cross-document View Transitions
   are running, js/page-transition.js already waits for readiness BEFORE it
   lets the cross-fade play, so the content is revealed by the transition
   itself. Running this settle as well would fade the same content in twice —
   a visible double-animation. This rule is therefore the fallback path:
   Safari/Firefox today, a direct page load, or a reload — anywhere no
   transition is playing. */
html:not(.rasa-vt)[data-rasa-ready] body > main,
html:not(.rasa-vt)[data-rasa-ready] body > footer,
html:not(.rasa-vt)[data-rasa-ready] body > .planner {
  animation: rasa-gate-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes rasa-gate-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── 3. Cross-document View Transitions ───────────────────────────────────
   Opt this document in. Both pages in a navigation must carry this rule for
   the browser to run a transition — which is why this file ships site-wide. */
@view-transition {
  navigation: auto;
}

/* The default UA transition cross-fades the ENTIRE page including the nav,
   which makes fixed chrome appear to blink. We stop that by giving the nav
   and footer their own transition names: an element with a stable name is
   matched across documents and animated independently — so identical chrome
   simply HOLDS STILL instead of fading out and back in.

   This is the single highest-impact rule in the file. */
.nav,
nav.nav {
  view-transition-name: rasa-nav;
}

.footer {
  view-transition-name: rasa-footer;
}

/* Chrome that is identical on both pages: no animation at all. Holding a
   perfectly still nav is what sells the illusion of one continuous app. */
::view-transition-old(rasa-nav),
::view-transition-new(rasa-nav),
::view-transition-old(rasa-footer),
::view-transition-new(rasa-footer) {
  animation: none;
  mix-blend-mode: normal;
}

/* The content area — everything that is NOT named above — is the `root`
   snapshot. This is what actually moves. */
::view-transition-group(root) {
  animation-duration: 0.44s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}

/* `normal` instead of the default `plus-lighter`: plus-lighter ADDS the two
   snapshots together mid-transition, which on a dark surface momentarily
   brightens the page — reading as a flash. Normal blending keeps the
   background constant throughout. */
::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
  /* The old page must not paint over the new one as it leaves. */
  backface-visibility: hidden;
}

/* ── Directional motion ───────────────────────────────────────────────────
   data-vt-dir is stamped by js/page-transition.js from the nav order.
   Forward = the new page comes from the right (you moved deeper).
   Back     = the new page comes from the left (you returned).

   The distances are deliberately SMALL (18px). A big slide is a website
   effect; a small, fast, well-eased displacement is what native apps do and
   is what reads as expensive. */

html[data-vt-dir="forward"]::view-transition-old(root) {
  animation: rasa-out-left 0.44s cubic-bezier(0.16, 1, 0.3, 1) both;
}
html[data-vt-dir="forward"]::view-transition-new(root) {
  animation: rasa-in-right 0.44s cubic-bezier(0.16, 1, 0.3, 1) both;
}

html[data-vt-dir="back"]::view-transition-old(root) {
  animation: rasa-out-right 0.44s cubic-bezier(0.16, 1, 0.3, 1) both;
}
html[data-vt-dir="back"]::view-transition-new(root) {
  animation: rasa-in-left 0.44s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* The outgoing page fades faster than the incoming one arrives, so the two
   never sit at full opacity on top of each other (which is what produces the
   "seeing through to what's behind" ghosting Rakesh reported). */
@keyframes rasa-out-left {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(-18px);
  }
}

@keyframes rasa-in-right {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes rasa-out-right {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(18px);
  }
}

@keyframes rasa-in-left {
  from {
    opacity: 0;
    transform: translateX(-18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── Accessibility ────────────────────────────────────────────────────────
   A user who has asked their operating system for less motion gets a clean
   instant swap. We never keep "just a little" movement — the setting is a
   request, not a suggestion. The readiness gate still applies, so they still
   get the correct-first-time page, just without the slide. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }

  html[data-rasa-ready] body > main,
  html[data-rasa-ready] body > footer,
  html[data-rasa-ready] body > .planner {
    animation: none !important;
  }
}
