/* transitions.css · Sky Map · the ONE definition of page + section transitions.
   Linked on EVERY page so cross-document View Transitions fire for any same-origin
   navigation (both the outgoing AND incoming page must opt in via @view-transition),
   and so the in-page section switchers (planisphere / astrolabe / sextant) share the
   same drawer motion via document.startViewTransition(). Chromium-only; other browsers
   just navigate/​swap instantly. Moved here from style.css so pages that don't load the
   full stylesheet still get transitions. */

/* Cross-document page transitions — clicking the instrument switch (or any same-origin
   nav) slides calmly to the next page, mirroring the in-page section drawer. */
@view-transition { navigation: auto; }

/* DRAWER cover: the outgoing view holds still underneath while the incoming view slides
   fully in, covering it — the same motion for page-to-page and the in-page section switch. */
::view-transition-group(root) { animation-duration: 1.1s; animation-timing-function: cubic-bezier(.33,.66,.28,1); }
::view-transition-old(root) { animation-name: vtHold; z-index: 1; }         /* holds still underneath */
::view-transition-new(root) { animation-name: vtInLeft; z-index: 2; }       /* slides fully in, covering */
@keyframes vtHold   { from { transform: none; }                to { transform: none; } }
@keyframes vtInLeft  { from { transform: translateX(-100%); }  to { transform: none; } }
@keyframes vtInRight { from { transform: translateX(100%); }   to { transform: none; } }
@keyframes vtInTop   { from { transform: translateY(-100%); }  to { transform: none; } }
@keyframes vtInBottom{ from { transform: translateY(100%); }   to { transform: none; } }

/* Random swipe direction — set on <html data-vt-dir> (config.js for page-to-page, the
   section switcher for in-page). Falls back to the left→right default above if unset. */
:root[data-vt-dir="right"]::view-transition-new(root)  { animation-name: vtInRight; }
:root[data-vt-dir="top"]::view-transition-new(root)    { animation-name: vtInTop; }
:root[data-vt-dir="bottom"]::view-transition-new(root) { animation-name: vtInBottom; }
:root[data-vt-dir="left"]::view-transition-new(root)   { animation-name: vtInLeft; }

/* =========================================================================
   TRANSITION TYPES — a rotating palette. js/transitions.js sets data-vt-type on
   <html> at load (before first paint), so each navigation ARRIVES with a type.
   These rules come AFTER the data-vt-dir slide above, so when a type is set it
   wins the cascade. Absent data-vt-type (no transitions.js), the classic slide
   still plays. All effects use transform / opacity / clip-path — reliable on the
   view-transition pseudo-elements. Chromium-only; elsewhere it swaps instantly.
   ========================================================================= */
:root[data-vt-type]::view-transition-group(root) { animation-duration: .8s; animation-timing-function: cubic-bezier(.4,0,.2,1); }
:root[data-vt-type]::view-transition-old(root),
:root[data-vt-type]::view-transition-new(root) { animation-duration: .8s; animation-timing-function: cubic-bezier(.4,0,.2,1); }

/* ---- SLIDE (drawer cover): new slides fully in over a held old ---- */
:root[data-vt-type^="slide"]::view-transition-old(root) { animation-name: vtHold;  z-index: 1; }
:root[data-vt-type^="slide"]::view-transition-new(root) { z-index: 2; }
:root[data-vt-type="slide-left"]::view-transition-new(root)  { animation-name: vtInLeft; }
:root[data-vt-type="slide-right"]::view-transition-new(root) { animation-name: vtInRight; }
:root[data-vt-type="slide-up"]::view-transition-new(root)    { animation-name: vtInBottom; }  /* new rises up from the bottom */
:root[data-vt-type="slide-down"]::view-transition-new(root)  { animation-name: vtInTop; }      /* new drops down from the top */

/* ---- FADE — a plain cross-fade ---- */
:root[data-vt-type="fade"]::view-transition-old(root) { animation-name: vtFadeOut; z-index: 1; }
:root[data-vt-type="fade"]::view-transition-new(root) { animation-name: vtFadeIn;  z-index: 2; }

/* ---- DISSOLVE — cross-fade softened with a little blur + scale, filmic ---- */
:root[data-vt-type="dissolve"]::view-transition-old(root) { animation-name: vtDissolveOut; z-index: 1; }
:root[data-vt-type="dissolve"]::view-transition-new(root) { animation-name: vtDissolveIn;  z-index: 2; }

/* ---- ZOOM IN — new grows from the centre over a held old ---- */
:root[data-vt-type="zoom-in"]::view-transition-old(root) { animation-name: vtHold;   z-index: 1; }
:root[data-vt-type="zoom-in"]::view-transition-new(root) { animation-name: vtZoomIn; z-index: 2; transform-origin: center; }

/* ---- ZOOM OUT — old pulls back and fades, revealing new underneath ---- */
:root[data-vt-type="zoom-out"]::view-transition-old(root) { animation-name: vtZoomOutOld; z-index: 2; transform-origin: center; }
:root[data-vt-type="zoom-out"]::view-transition-new(root) { animation-name: vtFadeIn;     z-index: 1; }

/* ---- IRIS — new revealed through an expanding circle (from centre / from a corner) ---- */
:root[data-vt-type="iris"]::view-transition-old(root)        { animation-name: vtHold; z-index: 1; }
:root[data-vt-type="iris"]::view-transition-new(root)        { animation-name: vtIris; z-index: 2; }
:root[data-vt-type="iris-corner"]::view-transition-old(root) { animation-name: vtHold;       z-index: 1; }
:root[data-vt-type="iris-corner"]::view-transition-new(root) { animation-name: vtIrisCorner; z-index: 2; }

/* ---- DIAMOND — new revealed through an expanding rhombus from centre ---- */
:root[data-vt-type="diamond"]::view-transition-old(root) { animation-name: vtHold;    z-index: 1; }
:root[data-vt-type="diamond"]::view-transition-new(root) { animation-name: vtDiamond; z-index: 2; }

/* ---- WIPE — a hard linear edge sweeps the new page across ---- */
:root[data-vt-type^="wipe"]::view-transition-old(root) { animation-name: vtHold; z-index: 1; }
:root[data-vt-type^="wipe"]::view-transition-new(root) { z-index: 2; }
:root[data-vt-type="wipe-left"]::view-transition-new(root)  { animation-name: vtWipeLeft; }
:root[data-vt-type="wipe-right"]::view-transition-new(root) { animation-name: vtWipeRight; }
:root[data-vt-type="wipe-up"]::view-transition-new(root)    { animation-name: vtWipeUp; }
:root[data-vt-type="wipe-down"]::view-transition-new(root)  { animation-name: vtWipeDown; }

/* ---- FLIP — a 3D page flip ---- */
:root[data-vt-type="flip"]::view-transition-old(root) { animation-name: vtFlipOut; z-index: 1; backface-visibility: hidden; }
:root[data-vt-type="flip"]::view-transition-new(root) { animation-name: vtFlipIn;  z-index: 2; backface-visibility: hidden; }

@keyframes vtFadeOut     { to   { opacity: 0; } }
@keyframes vtFadeIn      { from { opacity: 0; } }
@keyframes vtDissolveOut { to   { opacity: 0; filter: blur(7px);  transform: scale(1.03); } }
@keyframes vtDissolveIn  { from { opacity: 0; filter: blur(7px);  transform: scale(1.03); } }
@keyframes vtZoomIn      { from { opacity: 0; transform: scale(.72); } to { opacity: 1; transform: none; } }
@keyframes vtZoomOutOld  { to   { opacity: 0; transform: scale(1.28); } }
@keyframes vtIris        { from { clip-path: circle(0% at 50% 50%); }  to { clip-path: circle(140% at 50% 50%); } }
@keyframes vtIrisCorner  { from { clip-path: circle(0% at 0% 0%); }    to { clip-path: circle(160% at 0% 0%); } }
@keyframes vtDiamond     { from { clip-path: polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%); } to { clip-path: polygon(50% -60%, 160% 50%, 50% 160%, -60% 50%); } }
@keyframes vtWipeLeft    { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0); } }  /* edge sweeps right→left */
@keyframes vtWipeRight   { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
@keyframes vtWipeUp      { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0); } }
@keyframes vtWipeDown    { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0); } }
@keyframes vtFlipOut     { from { transform: perspective(1400px) rotateY(0);    opacity: 1; } to { transform: perspective(1400px) rotateY(90deg);  opacity: 0; } }
@keyframes vtFlipIn      { from { transform: perspective(1400px) rotateY(-90deg); opacity: 0; } to { transform: perspective(1400px) rotateY(0);      opacity: 1; } }

/* Universal enter-fade — for browsers WITHOUT cross-document View Transitions
   (Firefox / Safari), which swap pages instantly. js/transitions.js sets
   data-vt-enter there, and each page then fades in on load. Opacity only: a
   transform/filter on <body> would break the app's position:fixed panels. The
   dark <html> background shows through the fade, so there's no white flash; and
   if the script never runs, <body> just stays at its normal opacity (no blank). */
:root[data-vt-enter] body { animation: vtPageEnter .5s ease; }
@keyframes vtPageEnter { from { opacity: 0; } }

/* Reduced motion: skip every transition type, the base slide, and the enter-fade. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  :root[data-vt-enter] body { animation: none !important; }
}
