/* ==========================================================================
   Montiliya — the generation state of the preview (js/genstate.js)
   The player is always dark (#0b0b0b) whatever the theme, so its colours are fixed (--gi ink, --gp paper, --gt the line's track, --g2 / --g3 the quiet text); the compact card
   under a playing video sits in the preview pane and takes the theme's tokens instead. Black and white only, like the rest of the app: no accent colour, no gradient.
   The character's actions are small, slow and quiet; each one is a group of the SVG shown by .gen[data-stage] and animated only while it is shown. With reduced motion
   nothing moves: the character keeps its pose, each action is drawn still, and the line jumps instead of gliding. Logical properties: the line fills from the start side.
   ========================================================================== */

.poster { container: poster / size; }
.poster[data-gen] > .mascot, .poster[data-gen] > #poster-note { display: none; }
.gen { --gi: #ededed; --gp: #0b0b0b; --gt: #262626; --g2: #8f8f8f; --g3: #7c7c7c; display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; container-type: inline-size; }
.gen[hidden] { display: none; }
.gen-char { width: 64cqi; max-width: 280px; aspect-ratio: 1174 / 1030; }
.gen-char svg { display: block; width: 100%; height: 100%; overflow: visible; }
.gen-text { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.gen .gen-label { margin: 6cqi 0 0; max-width: 24ch; font-size: clamp(13px, 5.4cqi, 17px); font-weight: 500; line-height: 1.35; color: var(--gi); text-wrap: balance; }
.gen .gen-label.in { animation: gen-in 420ms var(--ease) both; }
.gen .gen-count { margin: 1.5cqi 0 0; max-width: none; font-size: 12px; color: var(--g2); }
.gen .gen-count[hidden] { display: none; }
.gen-bar { position: relative; width: min(70cqi, 260px); height: 4px; margin-top: 5.5cqi; border-radius: 2px; background: var(--gt); overflow: hidden; }
.gen-bar i { position: absolute; inset-block: 0; inset-inline-start: 0; border-radius: inherit; background: var(--gi); transition: width 900ms var(--ease); }
.gen-fill { width: var(--done, 0%); }
.gen-live { width: var(--live, 0%); opacity: 0.24; animation: gen-alive 1.8s var(--ease-in-out) infinite alternate; }
.gen .gen-note { margin: 4.5cqi 0 0; max-width: 30ch; font-size: clamp(11px, 3.7cqi, 12.5px); line-height: 1.45; color: var(--g3); text-wrap: balance; }
@keyframes gen-in { from { opacity: 0; transform: translateY(4px); } }
@keyframes gen-alive { to { opacity: 0.5; } }
/* no step to measure yet (in the queue, starting, stopping): a short piece moves along the line and no value is claimed; it stands still with reduced motion */
.gen-bar[data-mode='busy'] .gen-live { display: none; }
.gen-bar[data-mode='busy'] .gen-fill { width: 34%; transition: none; animation: gen-slide 1.6s var(--ease-in-out) infinite alternate; }
[dir='rtl'] .gen-bar[data-mode='busy'] .gen-fill { animation-name: gen-slide-rtl; }
@keyframes gen-slide { to { transform: translateX(194%); } }
@keyframes gen-slide-rtl { to { transform: translateX(-194%); } }
/* past the end of the estimate the note says so, a little brighter */
.gen.late .gen-note { color: var(--g2); }

/* the card under a playing video (a change request being made): the theme's colours, a small character beside the words, the title and the time on one line */
.gen.compact { --gi: var(--ink); --gp: var(--panel-2); --gt: var(--line-strong); --g2: var(--ink-2); --g3: var(--ink-3); flex-direction: row; align-items: center; gap: var(--s3); container-type: normal; }
.gen.compact .gen-char { width: 60px; max-width: none; flex: none; }
.gen.compact .gen-text { flex: 1; align-items: stretch; min-width: 0; text-align: start; }
.gen.compact .gen-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 var(--s3); margin: 0; }
.gen.compact .gen-title { min-width: 0; font-size: var(--fs-md); font-weight: 650; color: var(--ink); }
.gen.compact .gen-time { flex: none; font-size: var(--fs-xs); color: var(--ink-3); }
.gen.compact .gen-label { margin: 2px 0 0; max-width: none; font-size: var(--fs-sm); color: var(--ink-2); text-wrap: pretty; }
.gen.compact .gen-count { margin: 2px 0 0; }
.gen.compact .gen-bar { width: 100%; max-width: none; margin-top: var(--s2); }
.gen.compact .gen-note { margin: var(--s2) 0 0; max-width: none; font-size: var(--fs-xs); text-align: start; text-wrap: pretty; }

/* landscape frames are short: the character on one side, the words on the other; square ones get a smaller character; a short frame drops the note first */
.frame[data-ratio='16:9'] .gen { flex-direction: row; gap: 5cqi; }
.frame[data-ratio='16:9'] .gen-char { width: 30cqi; flex: none; }
.frame[data-ratio='16:9'] .gen-text { flex: 1; align-items: flex-start; text-align: start; }
.frame[data-ratio='16:9'] .gen .gen-label { margin-top: 0; font-size: clamp(13px, 3.3cqi, 17px); }
.frame[data-ratio='16:9'] .gen-bar { width: 100%; max-width: 260px; margin-top: 3cqi; }
.frame[data-ratio='16:9'] .gen .gen-note { margin-top: 2.6cqi; font-size: clamp(11px, 2.3cqi, 12.5px); }
.frame[data-ratio='1:1'] .gen-char { width: 44cqi; }
@container poster (max-height: 228px) { .frame[data-ratio='1:1'] .gen .gen-note { display: none; } }
@container poster (max-height: 100px) { .gen .gen-note { display: none; } }

/* ---- the character ------------------------------------------------------- */
.gen .gb { fill: var(--gi); }
.gen .eye { fill: var(--gp); }
.gen .gp path, .gen .gp circle { fill: none; stroke: var(--gi); stroke-width: 24; stroke-linecap: round; stroke-linejoin: round; }
.gen .gp-think rect { fill: none; stroke: var(--gi); stroke-width: 16; }
.gen .gp-tune rect, .gen .gp-cut rect, .gen .gp-render rect { fill: var(--gi); }
.gen .gp .spark, .gen .gp-finish .t1, .gen .gp-finish .t2, .gen .gp-finish .t3 { fill: var(--gi); stroke: none; }
.gen .gp-cut .head { stroke-width: 10; }
.gen .scanline { fill: var(--gp); opacity: 0.3; }

/* every action is hidden until its stage; the body breathes, the eyes blink now and then */
.gen .gp { opacity: 0; transition: opacity 360ms var(--ease); }
.gen[data-stage='scan'] .gp-scan, .gen[data-stage='scan'] .gp-scanin, .gen[data-stage='listen'] .gp-listen, .gen[data-stage='think'] .gp-think, .gen[data-stage='tune'] .gp-tune,
.gen[data-stage='cut'] .gp-cut, .gen[data-stage='draw'] .gp-draw, .gen[data-stage='render'] .gp-render, .gen[data-stage='finish'] .gp-finish { opacity: 1; }
.gen .gc { transform-box: fill-box; transform-origin: 50% 100%; animation: gen-breathe 3.2s var(--ease-in-out) infinite alternate; }
.gen .ge { transition: transform 320ms var(--ease); }
.gen .es, .gen .eye { transform-box: fill-box; transform-origin: center; }
.gen .es { transition: transform 320ms var(--ease); }
.gen .eye { animation: gen-blink 5.6s infinite; }
@keyframes gen-breathe { to { transform: scaleY(1.018); } }
@keyframes gen-blink { 0%, 93%, 100% { transform: none; } 95% { transform: scaleY(0.1); } }

/* wait (in the queue, starting, stopping): looks around */
.gen[data-stage='wait'] .ge { animation: gen-look 7s var(--ease-in-out) infinite; }
@keyframes gen-look { 0%, 22%, 86%, 100% { transform: none; } 32%, 46% { transform: translate(-30px, -6px); } 58%, 74% { transform: translate(30px, -6px); } }

/* scan (the clips, the picture, every scene): the eyes go across, a line passes over the body, the viewfinder breathes */
.gen .gp-scan { transform-box: fill-box; transform-origin: center; }
.gen[data-stage='scan'] .ge { animation: gen-dart 2.6s var(--ease-in-out) infinite; }
.gen[data-stage='scan'] .gp-scan { animation: gen-frame 2.6s var(--ease-in-out) infinite alternate; }
.gen[data-stage='scan'] .scanline { animation: gen-sweep 2.6s var(--ease-in-out) infinite alternate; }
@keyframes gen-dart { 0%, 90%, 100% { transform: translateX(-36px); } 40%, 50% { transform: translateX(36px); } }
@keyframes gen-frame { to { transform: scale(0.97); } }
@keyframes gen-sweep { to { transform: translateY(560px); } }

/* listen (the speech): leans in, eyes narrowed towards the sound */
.gen[data-stage='listen'] .gc { animation: gen-lean 2.8s var(--ease-in-out) infinite alternate; }
.gen[data-stage='listen'] .ge { transform: translate(30px, -4px); }
.gen[data-stage='listen'] .es { transform: scaleY(0.84); }
.gen[data-stage='listen'] .gp-listen path { animation: gen-wave 1.8s var(--ease) infinite; }
.gen[data-stage='listen'] .gp-listen .w2 { animation-delay: 0.25s; }
.gen[data-stage='listen'] .gp-listen .w3 { animation-delay: 0.5s; }
@keyframes gen-lean { from { transform: rotate(2deg); } to { transform: rotate(5deg); } }
@keyframes gen-wave { 0% { opacity: 0; transform: translateX(-10px); } 30% { opacity: 1; } 70%, 100% { opacity: 0; transform: translateX(14px); } }

/* think (choosing the best moments): looks from one moment to the next; the one it looks at rises */
.gen .gp-think rect { transform-box: fill-box; transform-origin: center; opacity: 0.32; }
.gen[data-stage='think'] .ge { animation: gen-choose 3s var(--ease-in-out) infinite; }
.gen[data-stage='think'] .gp-think rect { animation: gen-pick 3s var(--ease-in-out) infinite; }
.gen[data-stage='think'] .gp-think .k2 { animation-delay: -2s; }
.gen[data-stage='think'] .gp-think .k3 { animation-delay: -1s; }
@keyframes gen-choose { 0%, 28%, 100% { transform: translate(-40px, -34px); } 34%, 61% { transform: translate(0, -40px); } 67%, 94% { transform: translate(40px, -34px); } }
@keyframes gen-pick { 0%, 28%, 100% { opacity: 1; transform: translateY(-16px); } 34%, 94% { opacity: 0.32; transform: none; } }

/* tune (the audio): eyes almost closed, nodding to a level meter */
.gen .gp-tune rect { transform-box: fill-box; transform-origin: 50% 100%; }
.gen[data-stage='tune'] .gc { animation: gen-nod 0.56s var(--ease-in-out) infinite alternate; }
.gen[data-stage='tune'] .es { transform: scaleY(0.42); }
.gen[data-stage='tune'] .gp-tune rect { animation: gen-level 0.9s var(--ease-in-out) infinite alternate; }
.gen[data-stage='tune'] .gp-tune .b1 { animation-duration: 0.74s; }
.gen[data-stage='tune'] .gp-tune .b2 { animation-duration: 1.02s; animation-delay: -0.3s; }
.gen[data-stage='tune'] .gp-tune .b3 { animation-duration: 0.86s; animation-delay: -0.6s; }
.gen[data-stage='tune'] .gp-tune .b4 { animation-duration: 1.1s; animation-delay: -0.2s; }
.gen[data-stage='tune'] .gp-tune .b5 { animation-duration: 0.8s; animation-delay: -0.45s; }
@keyframes gen-nod { to { transform: translateY(-12px); } }
@keyframes gen-level { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }

/* cut (the cut assembled): looks down at three pieces coming together, then a playhead runs over them */
.gen[data-stage='cut'] .ge { transform: translateY(30px); }
.gen[data-stage='cut'] .s1 { animation: gen-join-start 2.6s var(--ease-in-out) infinite; }
.gen[data-stage='cut'] .s2 { animation: gen-join-middle 2.6s var(--ease-in-out) infinite; }
.gen[data-stage='cut'] .s3 { animation: gen-join-end 2.6s var(--ease-in-out) infinite; }
.gen .gp-cut .head { opacity: 0; }
.gen[data-stage='cut'] .head { animation: gen-play 2.6s linear infinite; }
@keyframes gen-join-start { 0%, 100% { transform: translateX(-44px); opacity: 0.5; } 40%, 82% { transform: none; opacity: 1; } }
@keyframes gen-join-middle { 0%, 100% { opacity: 0.5; } 40%, 82% { opacity: 1; } }
@keyframes gen-join-end { 0%, 100% { transform: translateX(44px); opacity: 0.5; } 40%, 82% { transform: none; opacity: 1; } }
@keyframes gen-play { 0%, 42% { transform: none; opacity: 0; } 46% { opacity: 1; } 80% { transform: translateX(624px); opacity: 1; } 84%, 100% { transform: translateX(624px); opacity: 0; } }

/* draw (the motion graphics): its eyes follow a stroke drawing itself; a spark where it ends */
.gen .gp-draw .stroke { stroke-dasharray: 100; stroke-dashoffset: 0; }
.gen .gp-draw .spark { transform-box: fill-box; transform-origin: center; }
.gen[data-stage='draw'] .ge { animation: gen-follow 3s var(--ease-in-out) infinite; }
.gen[data-stage='draw'] .stroke { animation: gen-draw 3s var(--ease-in-out) infinite; }
.gen[data-stage='draw'] .spark { animation: gen-spark 3s var(--ease) infinite; }
@keyframes gen-follow { 0%, 100% { transform: translate(28px, 36px); } 55%, 82% { transform: translate(40px, -24px); } }
@keyframes gen-draw { 0% { stroke-dashoffset: 100; opacity: 1; } 55%, 82% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes gen-spark { 0%, 50% { transform: scale(0); opacity: 0; } 62% { transform: scale(1.15) rotate(20deg); opacity: 1; } 70%, 82% { transform: none; opacity: 1; } 100% { transform: scale(0.6); opacity: 0; } }

/* render (the final video): busy, eyes on the frames going out */
.gen[data-stage='render'] .gc { animation: gen-busy 0.34s var(--ease-in-out) infinite alternate; }
.gen[data-stage='render'] .ge { transform: translateY(30px); }
.gen[data-stage='render'] .es { transform: scaleY(0.8); }
.gen[data-stage='render'] .belt { animation: gen-belt 0.9s linear infinite; }
@keyframes gen-busy { to { transform: translateY(-7px); } }
@keyframes gen-belt { to { transform: translateX(-150px); } }

/* finish (the last checks): pleased, a small hop, a tick drawn, a sparkle */
.gen .gp-finish .tick { stroke-dasharray: 100; stroke-dashoffset: 0; }
.gen .gp-finish .t1, .gen .gp-finish .t2, .gen .gp-finish .t3 { transform-box: fill-box; transform-origin: center; }
.gen[data-stage='finish'] .gc { animation: gen-hop 2.4s var(--ease) infinite; }
.gen[data-stage='finish'] .ge { transform: translateY(-6px); }
.gen[data-stage='finish'] .es { transform: scaleY(0.3); }
.gen[data-stage='finish'] .tick { animation: gen-tick 2.4s var(--ease-in-out) infinite; }
.gen[data-stage='finish'] .gp-finish .t1, .gen[data-stage='finish'] .gp-finish .t2, .gen[data-stage='finish'] .gp-finish .t3 { animation: gen-twinkle 2.4s var(--ease-in-out) infinite; }
.gen[data-stage='finish'] .gp-finish .t2 { animation-delay: -0.8s; }
.gen[data-stage='finish'] .gp-finish .t3 { animation-delay: -1.6s; }
@keyframes gen-hop { 0%, 55%, 76%, 88%, 100% { transform: none; } 66% { transform: translateY(-28px); } 82% { transform: translateY(-8px); } }
@keyframes gen-tick { 0% { stroke-dashoffset: 100; } 30%, 100% { stroke-dashoffset: 0; } }
@keyframes gen-twinkle { 0%, 100% { transform: scale(0.2); opacity: 0; } 40% { transform: scale(1) rotate(45deg); opacity: 1; } 70% { transform: scale(0.85) rotate(90deg); opacity: 0.7; } }

@media (prefers-reduced-motion: reduce) {
  .gen *, .gen *::before, .gen *::after { animation: none !important; }
}
