/* Revised 2026-09-20: independent scenes replace the shared presentation timeline.
   Layout and artwork remain the approved Figma design. */

/* Readable no-JS / paused / reduced-motion results. */
.space-collection-count:not(.space-count-after),.space-job-status:not(.done){opacity:0}
.space-count-after,.space-search-result,.space-job-status.done,.rank-badge{opacity:1}
.phone-ja,.phone-sweep,.lettering-ja,.lettering-scan i,.editor-original,.field-original{opacity:0}
.phone-en.top{height:62em}.phone-en.bottom{height:65em}
.phone-en,.lettering-en,.context-next,.context-name,.editor-refined,.field-refined{opacity:1}
.phone-sweep{width:16em;height:56em}
.phone-sweep.top{top:58em}.phone-sweep.top.sweep-right{left:64em}
.phone-sweep.bottom{top:368em;height:59em}.phone-sweep.bottom.sweep-right{left:326em}
.lettering-scan{height:92em;background:none;opacity:1;display:flex;justify-content:center;gap:10em}
.lettering-scan i{display:block;width:24em;height:100%;background:var(--blue)}

/* The phone stays still. Only its lettering changes. The cursor follows the
   continuously animated word window in typewriter.js, without blinking. */

/* Clear the entire source before revealing any English: mixed-language
   fragments never share the bubble, including during the loop reset. */
.motion-ready .phone-ja,.motion-ready .lettering-ja{animation:source-wipe 6s ease-in-out infinite both}
.motion-ready .phone-en,.motion-ready .lettering-en{animation:translation-wipe 6s ease-in-out infinite both}
.motion-ready .phone-sweep,.motion-ready .lettering-scan i{animation:translation-bars 6s ease-in-out infinite both}
.motion-ready .phone-sweep.sweep-left,.motion-ready .lettering-scan i:nth-child(2){animation-delay:160ms}
.motion-ready .lettering-scan i:first-child{animation-delay:320ms}
.motion-ready .phone-ja.bottom,.motion-ready .phone-en.bottom,.motion-ready .phone-sweep.bottom{animation-delay:700ms}
.motion-ready .phone-sweep.bottom.sweep-left{animation-delay:860ms}
@keyframes source-wipe{
  0%,18%{opacity:1;clip-path:inset(0 0 0 0)}
  26%,90%{opacity:0;clip-path:inset(100% 0 0 0)}
  96%,100%{opacity:1;clip-path:inset(0 0 0 0)}
}
@keyframes translation-wipe{
  0%,34%{opacity:0;clip-path:inset(0 0 100% 0)}
  46%,80%{opacity:1;clip-path:inset(0 0 0 0)}
  86%,100%{opacity:0;clip-path:inset(100% 0 0 0)}
}
@keyframes translation-bars{
  0%,17%{opacity:0;clip-path:inset(0 0 100% 0)}
  18%{opacity:1;clip-path:inset(0 0 100% 0)}
  29%,31%{opacity:1;clip-path:inset(0 0 0 0)}
  43%{opacity:1;clip-path:inset(100% 0 0 0)}
  44%,100%{opacity:0;clip-path:inset(100% 0 0 0)}
}

/* Each spread enters once, in the requested L / R / R / L order. */
.feature-spread[data-reveal="left"]{--entry-x:-72px}
.feature-spread[data-reveal="right"]{--entry-x:72px}
.motion-ready .feature-spread.reveal-ready:not(.scene-entered){opacity:0;transform:translateX(var(--entry-x)) translateY(16px)}
.motion-ready .feature-spread.scene-entered{animation:spread-enter 800ms cubic-bezier(.16,1,.3,1) both}
@keyframes spread-enter{from{opacity:0;transform:translateX(var(--entry-x)) translateY(16px)}to{opacity:1;transform:translateX(0) translateY(0)}}

/* 02: carry a name into the following panel, then reveal its dialogue. */
.motion-ready .context-name{animation:context-name 5.6s ease-in-out infinite both}
.motion-ready .context-next{animation:context-dialogue 5.6s ease-in-out infinite both}
@keyframes context-name{0%,5%{opacity:0;transform:translateY(8em) scale(.96)}14%,79%{opacity:1;transform:translateY(0) scale(1)}91%,100%{opacity:0;transform:translateY(8em) scale(.96)}}
@keyframes context-dialogue{0%,15%{opacity:0;transform:translateY(8em)}26%,79%{opacity:1;transform:translateY(0)}91%,100%{opacity:0;transform:translateY(8em)}}

/* 03: separate cleanup and lettering without changing the original art. */
.cleanup-sheet{--layer-x:-60em;--layer-y:25em}
.lettering-sheet{--layer-x:-112em;--layer-y:67em}
.motion-ready .cleanup-sheet,.motion-ready .lettering-sheet{animation:layers-separate 6.4s ease-in-out infinite both}
@keyframes layers-separate{0%,8%,100%{transform:translate(var(--layer-x),var(--layer-y))}31%,72%{transform:translate(0,0)}}

/* 04: the editing field and its speech bubble always change together. */
.motion-ready .editor-original,.motion-ready .field-original{animation:editor-before 5.8s ease-in-out infinite both}
.motion-ready .editor-refined,.motion-ready .field-refined{animation:editor-after 5.8s ease-in-out infinite both}
.motion-ready .fit-tool{animation:autofit-feedback 5.8s ease-in-out infinite}
@keyframes editor-before{0%,16%,94%,100%{opacity:1;transform:translateY(0)}20%,90%{opacity:0;transform:translateY(-3em)}}
@keyframes editor-after{0%,23%,86%,100%{opacity:0;transform:translateY(4em) scale(.97)}29%,80%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes autofit-feedback{0%,24%,42%,100%{transform:scale(1);box-shadow:0 0 0 0 #005bff00}32%{transform:scale(1.035);box-shadow:0 0 0 4px #005bff20}}

/* Pause offscreen work. The scroll entrance itself is deliberately one-shot. */
.motion-ready [data-motion-scene]:not(.scene-visible) *{animation-play-state:paused!important}
.motion-ready .scene-visible *{animation-play-state:running}
.document-hidden [data-motion-scene],.document-hidden [data-motion-scene] *{animation-play-state:paused!important}
.motion-paused [data-motion-scene],.motion-paused [data-motion-scene] *{animation:none!important}
.motion-paused .feature-spread.reveal-ready{opacity:1!important;transform:none!important}
.motion-paused .typing-cursor{visibility:hidden}
@media(max-width:767px){
  .feature-spread[data-reveal="left"]{--entry-x:-28px}
  .feature-spread[data-reveal="right"]{--entry-x:28px}
  .cleanup-sheet{--layer-x:-34em;--layer-y:15em}
  .lettering-sheet{--layer-x:-63em;--layer-y:38em}
  .lettering-scan{height:80em;gap:8em}.lettering-scan i{width:18em}
}
@media(prefers-reduced-motion:reduce){
  [data-motion-scene],[data-motion-scene] *{animation:none!important;transition:none!important}
  .motion-ready .feature-spread.reveal-ready{opacity:1!important;transform:none!important}
  .typing-cursor{visibility:hidden}
}
