/* Scene styling and keyframes for the hero animation of /features/,
   "A week with allme". Every animated element's resting style IS its final pose; the
   keyframes only animate towards it (fill-mode both), so a scene shown without animation
   (reduced motion) is complete. Keyframes run only while their scene carries .is-active.
   Timing: an element's timing class sets --ov-at (its start) and, for a flight, the
   --ov-dx / --ov-dy offset it flies in from. */

.ov-ink { color: var(--anim-ink); }
.ov-friend { color: var(--brand-2); }
.ov-brand { color: var(--brand-1); }
.ov-warm { color: var(--anim-warm); }
.ov-love { color: var(--anim-love); }
.ov-alert { color: var(--anim-alert); }
.ov-muted { color: var(--anim-muted); }
.ov-line { fill: var(--anim-muted); opacity: 0.7; }
.ov-line-ink { fill: var(--anim-ink); }
.ov-glow-soft { fill: var(--anim-warm-soft); }
.ov-floor { fill: var(--anim-muted); opacity: 0.35; }
.ov-beam, .ov-halo { fill: none; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 0; }
.ov-halo { stroke: var(--anim-warm-soft); stroke-width: 12; }
.ov-beam { stroke: var(--anim-warm); stroke-width: 3; }
.ov-beam-alert { stroke: var(--anim-alert); }
.ov-face-out, .ov-face-mid, .ov-gone, .ov-ringing, .ov-into, .ov-mid { opacity: 0; }
.ov-pop, .ov-fly, .ov-gone, .ov-drop, .ov-into, .ov-grow { transform-box: fill-box; transform-origin: center; }
.ov-grow { transform-origin: 0 50%; }
.ov-body { transform-box: fill-box; transform-origin: 50% 100%; }
.ov-buzz { transform-box: fill-box; transform-origin: 50% 50%; }

@keyframes ov-fade-in { from { opacity: 0; } }
@keyframes ov-fade-out { from { opacity: 1; } }
/* Shown only between two moments: in at the start, out at the end. */
@keyframes ov-mid { 0% { opacity: 0; } 14%, 86% { opacity: 1; } 100% { opacity: 0; } }
/* Gone for a while, then back: out at the start, in again at the end. */
@keyframes ov-away { 0% { opacity: 1; } 14%, 86% { opacity: 0; } 100% { opacity: 1; } }
@keyframes ov-pop { from { transform: scale(0); opacity: 0; } 50% { opacity: 1; } }
/* A thing flying to where it lands; each element names its own start offset. */
@keyframes ov-fly { from { transform: translate(var(--ov-dx, 0), var(--ov-dy, 0)) scale(0.4); opacity: 0; } 20% { opacity: 1; } }
/* A thing flying into a container and disappearing inside it. */
@keyframes ov-into { 0% { transform: translate(var(--ov-dx, 0), var(--ov-dy, 0)); opacity: 0; } 15% { opacity: 1; } 80% { transform: none; opacity: 1; } 100% { transform: translateY(14px) scale(0.6); opacity: 0; } }
/* Leaving: shrinks and fades to nothing. */
@keyframes ov-gone { from { transform: none; opacity: 1; } to { transform: scale(0.3); opacity: 0; } }
@keyframes ov-drop { from { transform: translateY(-70px); opacity: 0; } 30% { opacity: 1; } }
@keyframes ov-grow { from { transform: scaleX(0); } }
@keyframes ov-draw { from { stroke-dashoffset: 100; } }
@keyframes ov-hop { 0%, 100% { transform: none; } 40% { transform: translateY(-9px); } 70% { transform: translateY(2px); } }
@keyframes ov-giggle { 0%, 40%, 80%, 100% { transform: none; } 20% { transform: translateY(-6px) rotate(-2deg); } 60% { transform: translateY(-5px) rotate(2deg); } }
@keyframes ov-shake { 0%, 100% { transform: none; } 20% { transform: rotate(-4deg); } 40% { transform: rotate(4deg); } 60% { transform: rotate(-3deg); } 80% { transform: rotate(2deg); } }
@keyframes ov-buzz { 0%, 100% { transform: none; } 10%, 30%, 50%, 70%, 90% { transform: rotate(-6deg); } 20%, 40%, 60%, 80% { transform: rotate(6deg); } }
@keyframes ov-ring { 0% { opacity: 0; } 20%, 80% { opacity: 1; } 100% { opacity: 0; } }

/* Springy entrances overshoot through the easing, not through extra keyframes. */
.is-active .ov-pop { animation: ov-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) var(--ov-at, 0s) both; }
.is-active .ov-fly { animation: ov-fly 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) var(--ov-at, 0s) both; }
.is-active .ov-drop { animation: ov-drop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) var(--ov-at, 0s) both; }
.is-active .ov-grow { animation: ov-grow 0.4s ease var(--ov-at, 0s) both; }
.is-active .ov-into { animation: ov-into 1.1s ease-in-out var(--ov-at, 0s) both; }
.is-active .ov-gone { animation: ov-gone 0.5s ease-in var(--ov-at, 1s) both; }
.is-active .ov-ringing { animation: ov-ring 1s ease var(--ov-at, 0.3s) both; }
.is-active .ov-buzzing { animation: ov-buzz 0.9s ease var(--ov-at, 0.3s) both; }
/* A face swap: the earlier face fades out as the later one fades in, at the pair's --ov-at. */
.is-active .ov-face-out { animation: ov-fade-out 0.2s ease var(--ov-at, 1s) both; }
.is-active .ov-face-in { animation: ov-fade-in 0.2s ease var(--ov-at, 1s) both; }
.is-active .ov-face-mid, .is-active .ov-mid { animation: ov-mid var(--ov-dur, 1.4s) linear var(--ov-at, 1s) both; }
.is-active .ov-away { animation: ov-away var(--ov-dur, 1.4s) linear var(--ov-at, 1s) both; }
.is-active .ov-hop { animation: ov-hop 0.5s ease-out var(--ov-at, 1s) both; }
.is-active .ov-giggle { animation: ov-giggle 0.6s ease var(--ov-at, 1s) both; }
.is-active .ov-shake { animation: ov-shake 0.4s ease var(--ov-at, 1s) both; }
.is-active .ov-beam, .is-active .ov-halo { animation: ov-draw 0.5s ease-in-out var(--ov-at, 1s) both; }

/* A phone screen that lights up and stays lit. */
.ov-lit { fill: var(--anim-warm-soft); }
@keyframes ov-show { from { opacity: 0; } }
.is-active .ov-show { animation: ov-show 0.35s ease var(--ov-at, 1s) both; }
/* A thing that is thrown back where it came from: it flies in, stops, and falls away. */
.ov-bounce { opacity: 0; transform-box: fill-box; transform-origin: center; }
@keyframes ov-bounce { 0% { transform: translate(var(--ov-dx, 0), var(--ov-dy, 0)); opacity: 0; } 15% { opacity: 1; } 55% { transform: none; opacity: 1; } 70% { transform: translateX(10px) rotate(8deg); opacity: 1; } 100% { transform: translate(40px, 50px) rotate(30deg); opacity: 0; } }
.is-active .ov-bounce { animation: ov-bounce 1.6s ease-in-out var(--ov-at, 1s) both; }
/* A lid tossed off a box. */
.ov-toss { opacity: 0; transform-box: fill-box; transform-origin: center; }
@keyframes ov-toss { 0% { transform: none; opacity: 1; } 100% { transform: translate(70px, -120px) rotate(40deg); opacity: 0; } }
.is-active .ov-toss { animation: ov-toss 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) var(--ov-at, 1s) both; }

.ov-btn { fill: var(--brand-1); }

/* Scene 1, Monday: Sofia meets Marcus; one code connects them. */
.ov-s1-code { --ov-at: 0.4s; }
.ov-s1-beam { --ov-at: 1.2s; }
.ov-s1-ok { --ov-at: 1.8s; }
.ov-s1-sofia, .ov-s1-sofiaf, .ov-s1-marcus, .ov-s1-marcusf { --ov-at: 2s; }
.ov-s1-k1 { --ov-at: 2.2s; }
.ov-s1-k2 { --ov-at: 2.4s; }

/* Scene 2, Wednesday: her number changes once and Yuki's, Amara's and Mateo's phones light up with it. */
.ov-s2-sim { --ov-at: 0.3s; }
.ov-s2-b1 { --ov-at: 0.8s; }
.ov-s2-b2 { --ov-at: 1s; }
.ov-s2-b3 { --ov-at: 1.2s; }
.ov-s2-l1, .ov-s2-c1 { --ov-at: 1.4s; }
.ov-s2-l2, .ov-s2-c2 { --ov-at: 1.6s; }
.ov-s2-l3, .ov-s2-c3 { --ov-at: 1.8s; }
.ov-s2-sofia, .ov-s2-sofiaf, .ov-s2-yuki, .ov-s2-yukif, .ov-s2-amara, .ov-s2-amaraf, .ov-s2-mateo, .ov-s2-mateof { --ov-at: 2.2s; }

/* Scene 3, Thursday: she signs her rental contract in the app, and the new home is hers. */
.ov-s3-lit { --ov-at: 0.3s; }
.ov-s3-doc { --ov-at: 0.5s; }
.ov-s3-pen { --ov-at: 1.2s; }
.ov-s3-ok { --ov-at: 1.8s; }
.ov-s3-house { --ov-at: 2.2s; }
.ov-s3-sofia, .ov-s3-sofiaf { --ov-at: 2.4s; }
.ov-s3-key { --ov-at: 2.6s; }
.ov-s3-k1 { --ov-at: 2.8s; }

/* Scene 4, Friday: she signs in to a website with allme; only her email goes, the rest stays locked. */
.ov-s4-lit { --ov-at: 0.4s; }
.ov-s4-mail { --ov-at: 1s; --ov-dx: -290px; --ov-dy: 10px; }
.ov-s4-lock { --ov-at: 1.4s; }
.ov-s4-ok { --ov-at: 1.9s; }
.ov-s4-sofia, .ov-s4-sofiaf { --ov-at: 2.2s; }
.ov-s4-k1 { --ov-at: 2.4s; }

/* Scene 5, the weekend: Liam is safely set up, a stranger is turned away, and Sofia relaxes. */
.ov-s5-lit { --ov-at: 0.4s; }
.ov-s5-ok { --ov-at: 0.8s; }
.ov-s5-no { --ov-at: 1.4s; }
.ov-s5-sofia, .ov-s5-liam, .ov-s5-liamf, .ov-s5-sofiaf { --ov-at: 2s; }
.ov-s5-heart { --ov-at: 2.4s; }

/* Scene 6, the closing: everyone's phone, in a circle, lights up. */
.ov-s6-p1 { --ov-at: 0.2s; }
.ov-s6-p2 { --ov-at: 0.4s; }
.ov-s6-p3 { --ov-at: 0.6s; }
.ov-s6-p4 { --ov-at: 0.8s; }
.ov-s6-p5 { --ov-at: 1s; }
.ov-s6-p6 { --ov-at: 1.2s; }
.ov-s6-p7 { --ov-at: 1.4s; }
.ov-s6-p8 { --ov-at: 1.6s; }
.ov-s6-l1 { --ov-at: 2s; }
.ov-s6-l2 { --ov-at: 2.1s; }
.ov-s6-l3 { --ov-at: 2.2s; }
.ov-s6-l4 { --ov-at: 2.3s; }
.ov-s6-l5 { --ov-at: 2.4s; }
.ov-s6-l6 { --ov-at: 2.5s; }
.ov-s6-l7 { --ov-at: 2.6s; }
.ov-s6-l8 { --ov-at: 2.7s; }
.ov-s6-heart { --ov-at: 3s; }
.ov-s6-k1 { --ov-at: 3.2s; }
.ov-s6-k2 { --ov-at: 3.3s; }
