/* =========================================================================
   Traxy — refined motion & polish layer  (accessible, robust)
   - All motion gated behind prefers-reduced-motion: no-preference. The inline
     head script only adds `tx-motion` when motion is allowed, so under "reduce"
     nothing is ever hidden.
   - Static reveal targets ([data-tx-reveal], children of
     [data-tx-reveal-children]) are pre-hidden via `html.tx-motion` BEFORE paint,
     so reveal-on-scroll is layout-timing independent (no early reveal, no flash).
   - Dynamic tracker cards are NOT pre-hidden by selector (trackers.js re-renders
     them); motion.js marks them with `.tx-reveal-el` and reveals in-view ones
     immediately to avoid flicker on re-render.
   - `html.tx-revealed` (failsafe, set after a timeout) forces everything visible.
   ========================================================================= */

/* Elegant keyboard focus (mouse users unaffected) */
:where(a, button, [role="button"], input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--tx-focus, #38bdf8);
  outline-offset: 2px;
}

/* Refined text selection */
::selection { background: rgba(56, 189, 248, 0.28); }

/* Refined, unobtrusive scrollbars (works on light + dark atmospheres) */
* { scrollbar-width: thin; scrollbar-color: rgba(148, 163, 184, 0.5) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: rgba(148, 163, 184, 0.45);
  border: 2px solid transparent;
  border-radius: 8px;
  background-clip: padding-box;
  transition: background 0.2s ease;
}
*::-webkit-scrollbar-thumb:hover { background: rgba(148, 163, 184, 0.7); background-clip: padding-box; }

/* Smooth, premium-feeling form fields */
@media (prefers-reduced-motion: no-preference) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  textarea, select {
    transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  }
}

/* Shared revealed state — wins over every hidden rule below.
   Subtle + snappy (restraint reads as taste); no persistent will-change.
   transform is deliberately NOT !important: the pre-hide rules are all gated
   by :not(.tx-in) so no override is needed, and an !important here would
   permanently kill [data-tx-lift]/[data-tx-tilt] hover transforms on
   revealed cards (e.g. the finance dashboard stat articles). */
.tx-in {
  opacity: 1 !important;
  transform: none;
  transition:
    opacity var(--tx-reveal-dur, 0.45s) cubic-bezier(0.22, 0.61, 0.36, 1),
    transform var(--tx-reveal-dur, 0.45s) cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--tx-delay, 0ms);
}

/* Motion-intensity tuning (A4). The effective level lives on html[data-motion-level]
   (0 Minimal .. 4 Maximum); level 0 never reaches here (html.tx-motion is off, so
   nothing is pre-hidden). Level 2 is the baseline (unchanged from before). */
html[data-motion-level="1"] { --tx-reveal-dur: 0.28s; --tx-reveal-shift: 6px; }
html[data-motion-level="3"] { --tx-reveal-dur: 0.5s;  --tx-reveal-shift: 14px; }
html[data-motion-level="4"] { --tx-reveal-dur: 0.6s;  --tx-reveal-shift: 18px; }

/* Static reveal targets — hidden pre-paint, layout-independent.
   Small offset only; no will-change (persisting it on every off-screen element
   wastes GPU memory and itself causes scroll jank). */
html.tx-motion :is([data-tx-reveal], [data-tx-reveal-children] > *):not(.tx-in) {
  opacity: 0;
  transform: translateY(var(--tx-reveal-shift, 10px));
}

/* Fade-only variant — pre-hides with opacity alone (no translateY). Use on
   containers with position:fixed descendants: a transform would become their
   containing block and break the popovers. The failsafe + print rules below
   already cover it via the bare [data-tx-reveal] attribute selector. */
html.tx-motion [data-tx-reveal="fade"]:not(.tx-in) {
  transform: none;
}

/* Dynamic cards — hidden only after JS marks them */
.tx-reveal-el:not(.tx-in) {
  opacity: 0;
  transform: translateY(var(--tx-reveal-shift, 10px));
}

/* Failsafe — reveal everything if something went wrong */
html.tx-revealed :is([data-tx-reveal], [data-tx-reveal-children] > *, .tx-reveal-el) {
  opacity: 1 !important;
  transform: none !important;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }

  /* Tracker cards contain position:fixed popovers → lift with SHADOW ONLY
     (a transform here would become their containing block and break them). */
  .tracker-card { transition: box-shadow 0.3s ease, border-color 0.3s ease; }
  .tracker-card:hover { box-shadow: 0 22px 48px -20px rgba(2, 8, 23, 0.55); }

  /* Opt-in transform lift for simple cards (no fixed-position descendants). */
  [data-tx-lift] {
    transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.28s ease;
  }
  [data-tx-lift]:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 40px -14px rgba(2, 8, 23, 0.5);
  }

  /* Lift + tilt combo (high tier, e.g. homepage theme cards): compose both —
     the lift's hover transform alone would flatten depth.js's rotateX/rotateY
     (depth.css keeps the tilt rule at :where (0,1,1) by design). */
  html[data-tier="high"] [data-tx-tilt][data-tx-lift]:hover {
    transform: rotateX(var(--tx-rx, 0deg)) rotateY(var(--tx-ry, 0deg)) translateY(-4px);
  }

  button:active, [role="button"]:active { transform: translateY(0.5px); }
}

/* Reduced motion: freeze Tailwind's infinite decorative loops (hero ping dots,
   pulse placeholders, bounce). .animate-spin is deliberately excluded — it
   conveys loading state. motion.css owns motion policy; never patch the
   generated tailwind.css for this. */
@media (prefers-reduced-motion: reduce) {
  .animate-ping,
  .animate-pulse,
  .animate-bounce {
    animation: none !important;
  }
}

/* Print: reveal-on-scroll targets must never print as blank gaps. Additive
   fallback only — live [data-tx-reveal] opacity semantics stay untouched
   (e2e/audit.js observes them). */
@media print {
  html.tx-motion :is([data-tx-reveal], [data-tx-reveal-children] > *, .tx-reveal-el) {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* =========================================================================
   Page-to-page navigation layer (page-nav.js)
   - Enter pose is applied pre-paint via html[data-txnav-enter] (head script),
     so an in-site arrival never flashes at identity before sliding in. The
     attribute is only ever set when html.tx-motion is on; a head failsafe
     removes it even if page-nav.js dies.
   - Exit/drag states are inline-style driven by page-nav.js; only the shared
     transitions and the progress bar live here.
   ========================================================================= */

/* Enter pose — held without transition until page-nav.js releases it. */
html.tx-motion[data-txnav-enter] #page-shell {
  opacity: 0;
  transition: none;
}

html.tx-motion[data-txnav-enter='right'] #page-shell {
  transform: translateX(30px);
}

html.tx-motion[data-txnav-enter='left'] #page-shell {
  transform: translateX(-30px);
}

/* Release transition — id+class outranks the attribute rules above once the
   attribute is gone, and Tailwind's transition-transform utility always. */
#page-shell.txnav-enter-play {
  transition:
    opacity 0.38s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.38s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Outgoing fade for plain link navigations (the request races the fade, so
   fast responses simply cut it short). */
html.tx-motion #page-shell.txnav-exit {
  opacity: 0.3;
  transition: opacity 0.4s ease;
}

/* Swipe surface: keep vertical scroll + pinch zoom native, claim horizontal
   drags for page paging. Applied by page-nav.js only on ring pages that do
   not embed the dashboard track (which owns its own gestures). */
#page-shell.txnav-swipe-surface {
  touch-action: pan-y pinch-zoom;
}

/* Navigation progress bar — fixed above everything (boot overlay is 4000).
   Width animates via scaleX so the trickle never causes layout. Kept under
   reduced motion: like .animate-spin, it conveys loading state. */
.txnav-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  z-index: 4100;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.txnav-bar.is-active {
  opacity: 1;
}

.txnav-bar .txnav-bar-fill {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  background: linear-gradient(90deg, #38bdf8, #22d3ee 55%, #fbbf24);
  box-shadow: 0 0 10px rgba(56, 189, 248, 0.65);
  transition: transform 0.18s linear;
}
