/* ===========================================================================
   Service films: eight 9-second clips, one per folder, played in a loop. Pure
   CSS keyframes, one iteration each; ensamble-folders.js adds .is-playing,
   measures anchors, drives play/pause through getAnimations() and bridges the
   loops: the caption fades out on the held result, a still copy of the stage
   (.film-still, never animated) covers it while the clips restart, and the
   still dissolves into the first frame. This is deliberately separate from ensamble-motion.js,
   whose scene is scrubbed by scroll. Do not merge the two mechanisms.

   The BASE style of every element is the RESULT frame, and the 100 % keyframe
   must match it: that is what shows without JS, with reduced motion, at the
   end of every loop, in the still that bridges the loops AND as the poster on
   each folder card (a clone of the stage that never plays). A final state written
   only inside a keyframe looks right in the open case and wrong on the card:
   check the posters in the grid whenever a film changes. Keyframes exist only
   under .case-panel.is-playing, so 0 % is the first frame of the story.

   Shared timing grid (9 s, 1 % = 90 ms). No keyframe uses a time that is not
   listed in its film's table below.
     0–22 %   situation       (2 s)   caption 1
     22–67 %  transformation  (4 s)   caption 2
     67–100 % result, held    (3 s)   caption 3
   Flying pieces read their start and end points from --<anchor>-x/y, which
   the script measures in cqw from [data-a] elements before playback.
   =========================================================================== */

.case-film{position:relative;display:flex;flex-direction:column;gap:14px;padding:28px 22px 30px 28px;min-width:0}
.film-head{display:flex;justify-content:space-between;gap:16px;margin:0;font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:#687687}
.film-stage{position:relative;aspect-ratio:4/3;container-type:inline-size;border-radius:10px;overflow:hidden;background:var(--film-bg);isolation:isolate;font-size:2.4cqw;line-height:1.25;color:#27364a;box-shadow:inset 0 0 0 1px #17202b0d}
.film-stage::before{content:"";position:absolute;inset:0;background-image:radial-gradient(var(--film-dot) .7px,transparent .9px);background-size:3.4cqw 3.4cqw;background-position:1.7cqw 1.7cqw}
.film-stage *,.film-stage *::before,.film-stage *::after{box-sizing:border-box}
.film-stage .fc{position:absolute;background:#fff;border-radius:1.6cqw;box-shadow:0 .2cqw .5cqw #17202b12,0 2.6cqw 5cqw -2.4cqw #243f7352}
.film-stage .fl{position:absolute;font-size:1.9cqw;font-weight:650;letter-spacing:.12em;text-transform:uppercase;color:#5d6b82;white-space:nowrap}
.film-cursor{position:absolute;z-index:8;left:0;top:0;width:4.8cqw;height:4.8cqw;opacity:0}
.film-cursor svg{display:block;width:100%;height:100%;fill:#0f1a33;stroke:#fff;stroke-width:1.5;stroke-linejoin:round;transform-origin:22% 14%;filter:drop-shadow(0 .4cqw .5cqw #0f1a3340)}

.film-foot{display:flex;align-items:center;gap:14px}
.film-toggle{flex:none;width:38px;height:38px;border:1px solid #1a2740;border-radius:50%;background:#1a2740;color:#fff;display:grid;place-items:center;padding:0;cursor:pointer;transition:background .16s,transform .16s}
.film-toggle[hidden]{display:none}
.film-toggle:hover{background:#324563}
.film-toggle:active{transform:scale(.96)}
.film-toggle:focus-visible{outline:3px solid #2453ec;outline-offset:3px}
.film-toggle svg{width:15px;height:15px;fill:currentColor}
.film-toggle path{display:none}
.film-toggle[data-state="playing"] .i-pause,.film-toggle[data-state="paused"] .i-play{display:block}
.film-toggle-label{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.film-caption{display:grid;margin:0;font-size:14px;font-weight:550;line-height:1.35;letter-spacing:-.015em;color:#27364a}
.film-caption span{grid-area:1/1;opacity:0}
.film-caption span:last-child{opacity:1}
.film-caption{flex:1;min-width:0}
/* The still that bridges two loops: a copy of the stage in its result frame. */
.film-still{position:absolute;z-index:1;margin:0;pointer-events:none}
.film-still[hidden]{display:none}
.film-still,.film-still *,.film-still *::before,.film-still *::after{animation:none!important}

/* Playback defaults. Timing functions are set per keyframe where they differ. */
.case-panel.is-playing .case-film *,.case-panel.is-playing .case-film *::before,.case-panel.is-playing .case-film *::after{animation-duration:9s;animation-fill-mode:both;animation-iteration-count:1;animation-timing-function:cubic-bezier(.2,0,0,1)}
.is-playing .film-caption span:nth-child(1){animation-name:cap-a}
.is-playing .film-caption span:nth-child(2){animation-name:cap-b}
.is-playing .film-caption span:nth-child(3){animation-name:cap-c}
@keyframes cap-a{0%,21%{opacity:1;transform:none}23%,100%{opacity:0;transform:translateY(-4px)}}
@keyframes cap-b{0%,22%{opacity:0;transform:translateY(4px)}24.5%,65.5%{opacity:1;transform:none}67.5%,100%{opacity:0;transform:translateY(-4px)}}
@keyframes cap-c{0%,67%{opacity:0;transform:translateY(4px)}69.5%,100%{opacity:1;transform:none}}
@keyframes caret{0%,2.5%{opacity:1}2.6%,5%{opacity:0}5.1%,7.5%{opacity:1}7.6%,10%{opacity:0}10.1%,12.5%{opacity:1}12.6%,15%{opacity:0}15.1%,17.5%{opacity:1}17.6%,20%{opacity:0}20.1%,21.5%{opacity:1}22%,100%{opacity:0}}

/* The four first-generation films (.f1-…f4-, SVG) lived here until 27-sep-2026;
   the folders now play C1–C8 (ensamble-films-casos.css). Removed as dead code
   (32 KB, −160 ms FCP on Fast 3G, measured); a copy is in
   estudio/respaldos/2026-09-27-equipo-v1/ensamble-films.antes-poda-f1-f4.css. */

/* Layout of the film column on narrow screens. */
@media(max-width:760px){
  .case-film{padding:22px 16px 4px;gap:12px}
  .film-head{padding-right:48px}
  .film-caption{font-size:13px}
}
/* Reduced motion: the result frame, still, and no player controls. */
@media(prefers-reduced-motion:reduce){.film-toggle{display:none!important}}
