/* Motion: keyframes, page transitions (View Transitions API) and the motion levels.
   html[data-motion=off] (or prefers-reduced-motion) stops everything; "show" keeps only feedback
   (nudges, digits, state edges, tally) and is set in the user menu. See docs/design.md §2, §5. */

/* ---------- keyframes ---------- */
@keyframes wipe { from { transform: skewX(-14deg) scaleX(0); } to { transform: skewX(-14deg) scaleX(1); } }
@keyframes wipeOut { to { transform: skewX(-14deg) scaleX(0); transform-origin: right; } }
@keyframes edgeDraw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes ruleDraw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes titleIn { from { clip-path: inset(0 100% 0 0); transform: translateX(-1rem); } to { clip-path: inset(0 0 0 0); transform: none; } }
@keyframes riseIn { from { opacity: 0; transform: translateY(var(--rise)); } to { opacity: 1; transform: none; } }
@keyframes tileIn { from { opacity: 0; transform: translateY(var(--rise)); } to { opacity: 1; transform: none; } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes dropIn { from { opacity: 0; transform: translateY(-.375rem); } to { opacity: 1; transform: none; } }
@keyframes toastIn { from { opacity: 0; transform: translateX(-1.5rem) skewX(-6deg); } to { opacity: 1; transform: none; } }
@keyframes toastOut { to { opacity: 0; transform: translateX(-1.5rem); } }
@keyframes popIn { from { opacity: 0; transform: translateY(-.25rem) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes popOut { to { opacity: 0; transform: translateY(-.25rem); } }
@keyframes menuIn { from { opacity: 0; transform: scaleY(.96); } to { opacity: 1; transform: none; } }
@keyframes dialogIn { from { opacity: 0; transform: translateY(.75rem) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes bannerIn { from { transform: translateY(-100%); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes hit { 50% { transform: scaleX(1); opacity: 1; } to { transform: scaleX(1); opacity: 0; } }
@keyframes dgUp { to { transform: translateY(-50%); } }
@keyframes dgDn { from { transform: translateY(-50%); } to { transform: none; } }
@keyframes rollIn { from { opacity: 0; transform: translateY(60%); } to { opacity: 1; transform: none; } }
@keyframes rollOut { to { opacity: 0; transform: translateY(-60%); } }
@keyframes railTick { from { transform: translateX(0); } to { transform: translateX(-14px); } }
@keyframes blink2 { 0% { opacity: 1; } 50% { opacity: .35; } }
@keyframes blink { 0%, 60% { opacity: 1; } 61%, 100% { opacity: .4; } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes skSweep { from { transform: translateX(-100%); } to { transform: translateX(400%); } }
@keyframes glint { from { transform: translateX(-100%) skewX(-14deg); } to { transform: translateX(600%) skewX(-14deg); } }
@keyframes shake { 20%, 60% { transform: translateX(-.25rem); } 40%, 80% { transform: translateX(.25rem); } }
@keyframes flashEdge { 0%, 100% { box-shadow: inset 0 0 0 0 transparent; } 30% { box-shadow: inset 0 0 0 2px var(--accent); } }
@keyframes sweepLine { from { transform: scaleX(0); opacity: 1; } 70% { transform: scaleX(1); opacity: 1; } to { transform: scaleX(1); opacity: 0; } }
@keyframes bump { 0% { color: var(--accent); transform: translateY(-2px); } 100% { color: inherit; transform: none; } }

/* ---------- page transitions ---------- */
/* The top bar is fixed chrome: it shows live through the transition. Pages slide in the tab
   order's direction; the band (eyebrow, word, //, count, rule) morphs between pages. */
.topbar { view-transition-name: chrome; }
::view-transition { pointer-events: none; }
::view-transition-group(chrome), ::view-transition-new(chrome) { animation: none; }
::view-transition-old(chrome) { display: none; }
::view-transition-old(root) { animation: vtOut var(--t-exit) var(--e-in) both; }
::view-transition-new(root) { animation: vtIn var(--t-in) var(--e-out) 60ms both; }
html[data-dir="back"]::view-transition-old(root) { animation-name: vtOutBack; }
html[data-dir="back"]::view-transition-new(root) { animation-name: vtInBack; }
::view-transition-group(*.shared) { animation-duration: var(--t-move); animation-timing-function: var(--e-out); }
::view-transition-group(ph-eyebrow), ::view-transition-group(ph-slash), ::view-transition-group(ph-rule), ::view-transition-group(ph-word), ::view-transition-group(ph-count), ::view-transition-group(strip) { animation-duration: var(--t-move); animation-timing-function: var(--e-out); }
::view-transition-old(ph-word), ::view-transition-new(ph-word), ::view-transition-old(ph-count), ::view-transition-new(ph-count), ::view-transition-old(ph-eyebrow), ::view-transition-new(ph-eyebrow) { height: 100%; width: auto; object-fit: none; object-position: left center; }
::view-transition-old(ph-word) { animation: fadeOutFast var(--t-exit) var(--e-in) both; }
::view-transition-new(ph-word) { animation: vtWipe var(--t-in) var(--e-whip) 40ms both; }
::view-transition-image-pair(ph-count) { overflow: clip; }
::view-transition-old(ph-count) { animation: rollOut var(--t-exit) var(--e-in) both; }
::view-transition-new(ph-count) { animation: rollIn var(--t-in) var(--e-roll) 60ms both; }
::view-transition-old(ph-eyebrow) { animation: fadeOutFast var(--t-exit) var(--e-in) both; }
::view-transition-new(ph-eyebrow) { animation: fadeIn var(--t-in) linear 80ms both; }
@keyframes vtOut { to { opacity: 0; transform: translateX(calc(-1 * var(--slide))); } }
@keyframes vtIn { from { opacity: 0; transform: translateX(var(--slide)); } }
@keyframes vtOutBack { to { opacity: 0; transform: translateX(var(--slide)); } }
@keyframes vtInBack { from { opacity: 0; transform: translateX(calc(-1 * var(--slide))); } }
@keyframes vtWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes fadeOutFast { to { opacity: 0; } }

/* ---------- motion levels ---------- */
html[data-motion="show"] .band-title, html[data-motion="show"] .ph-rule { animation: none !important; }
html[data-motion="show"] .stagger > * { animation-delay: 0ms !important; }
html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="off"] *::after { animation: none !important; transition: none !important; }
html[data-motion="off"]::view-transition-group(*), html[data-motion="off"]::view-transition-old(*), html[data-motion="off"]::view-transition-new(*) { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* Band parts of the visible page carry fixed names so they morph between pages. */
.tabpane:not(.hidden) .ph-eyebrow { view-transition-name: ph-eyebrow; }
.tabpane:not(.hidden) .ph-word { view-transition-name: ph-word; }
.tabpane:not(.hidden) .ph-slash { view-transition-name: ph-slash; }
.tabpane:not(.hidden) .ph-count { view-transition-name: ph-count; }
.tabpane:not(.hidden) .ph-unit { view-transition-name: ph-unit; }
.tabpane:not(.hidden) .ph-rule { view-transition-name: ph-rule; }
::view-transition-old(ph-unit), ::view-transition-new(ph-unit) { height: 100%; width: auto; object-fit: none; object-position: left center; }
::view-transition-old(ph-unit) { animation: fadeOutFast var(--t-exit) var(--e-in) both; }
::view-transition-new(ph-unit) { animation: vtWipe var(--t-in) var(--e-whip) 80ms both; }
