/* Cinematic grammar for the 01 → 04 prototype chain.
   Depth of field: scenes off screen sit out of focus and slightly forward; the active scene is sharp.
   While the RFQ dossier flies, the incoming scene is held soft (.cn-dof) and focus racks to it on landing.
   Leaving a chain scene pushes it back in depth (.cn-out). Film texture: grain + vignette, chain scenes only. */
:is(#s-problem,#s-evidence,#s-cause,#s-flow){filter:blur(8px) brightness(.55);transform:scale(1.028);transition:opacity .6s var(--io),transform 1s var(--out),filter .7s var(--io),visibility 0s 1s}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).active{filter:none;transform:none;transition:opacity .8s var(--io) .1s,transform 1.3s cubic-bezier(.16,1,.3,1) .04s,filter 1s cubic-bezier(.35,0,.15,1) .04s,visibility 0s}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).active.cn-dof{filter:blur(8px) brightness(.58)}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).leaving{filter:none}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).cn-out{opacity:0;transform:scale(.962);filter:none;transition:opacity .7s var(--io),transform 1.1s cubic-bezier(.5,0,.2,1),visibility 0s 1.1s}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).cn-out .head{opacity:0!important;transition:opacity .25s var(--io)!important}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).cn-in .head .mk>span{transition-delay:.3s}
:is(#s-problem,#s-evidence,#s-cause,#s-flow).cut{transition:none!important}
body.safe :is(#s-problem,#s-evidence,#s-cause,#s-flow){filter:none!important}
/* 21/10: a full-stage 8 px blur on 03/04 cost 40–200 ms GPU frames on every entry (traced); like 02, depth there comes from scale and opacity only */
:is(#s-cause,#s-flow),:is(#s-cause,#s-flow).active,:is(#s-cause,#s-flow).active.cn-dof{filter:none!important}

#cine-fx{position:absolute;inset:0;z-index:45;pointer-events:none;opacity:0;overflow:hidden;transition:opacity 1.2s var(--io)}
#stage:is([data-scene="problem"],[data-scene="evidence"],[data-scene="cause"],[data-scene="flow"]) #cine-fx{opacity:1}
#cine-fx .cn-vig{position:absolute;inset:0;background:radial-gradient(ellipse 78% 74% at 50% 47%,transparent 60%,rgba(1,4,12,.42) 100%)}
#cine-fx .cn-grain{position:absolute;inset:-80px;opacity:.045;will-change:transform;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");animation:cnGrain .7s steps(5) infinite}
@keyframes cnGrain{0%{transform:translate(0,0)}20%{transform:translate(-31px,17px)}40%{transform:translate(23px,-29px)}60%{transform:translate(-13px,-41px)}80%{transform:translate(37px,11px)}100%{transform:translate(0,0)}}
body.safe #cine-fx .cn-grain{animation:none}

.cn-trail{position:absolute;left:0;top:0;z-index:39;pointer-events:none;will-change:transform,opacity}
#rfq-ghost{will-change:transform,opacity}
#rfq-ghost .cn-shadow{position:absolute;left:4%;right:4%;top:10%;bottom:-10%;z-index:-1;border-radius:40%;background:radial-gradient(ellipse at 50% 50%,rgba(0,0,0,.6),rgba(0,0,0,.25) 45%,transparent 70%);opacity:.35;pointer-events:none;will-change:transform,opacity}
.cn-ring{position:absolute;z-index:41;pointer-events:none;box-sizing:border-box;border:2px solid rgba(186,212,255,.95);box-shadow:0 0 26px rgba(127,176,255,.75),inset 0 0 20px rgba(127,176,255,.35);opacity:0}
.cn-ring.amber{border-color:rgba(255,206,130,.95);box-shadow:0 0 26px rgba(240,166,58,.75),inset 0 0 20px rgba(240,166,58,.35)}
.cn-flare{position:absolute;z-index:41;pointer-events:none;opacity:0;border-radius:2px;background:linear-gradient(90deg,transparent,rgba(150,190,255,.25) 22%,rgba(225,236,255,.95) 50%,rgba(150,190,255,.25) 78%,transparent);box-shadow:0 0 18px 2px rgba(127,176,255,.6)}
.cn-flare.amber{background:linear-gradient(90deg,transparent,rgba(240,166,58,.25) 22%,rgba(255,232,190,.95) 50%,rgba(240,166,58,.25) 78%,transparent);box-shadow:0 0 18px 2px rgba(240,166,58,.6)}
.cn-sweep{position:absolute;z-index:42;pointer-events:none;overflow:hidden}
.cn-sweep b{position:absolute;top:-30%;bottom:-30%;left:0;width:34%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);transform:translateX(-120%) skewX(-18deg)}

/* scene 04: each role node ignites as the dossier reaches it */
#s-flow .fl-node i{position:relative}
#s-flow .fl-node i::after{content:"";position:absolute;inset:-2px;border-radius:50%;border:2px solid #AFCBFF;box-shadow:0 0 18px rgba(127,176,255,.7);opacity:0;pointer-events:none}
#s-flow:not(.cut)[data-k="1"] .fl-node.n1 i::after{animation:cnIgnite 1.2s cubic-bezier(.2,.7,.2,1) 1.25s both}
#s-flow:not(.cut):not(.fs-hold)[data-k="2"] .fl-node.n2 i::after{border-color:var(--amber);box-shadow:0 0 18px rgba(240,166,58,.7);animation:cnIgnite 1.2s cubic-bezier(.2,.7,.2,1) .95s both}
#s-flow:not(.cut)[data-k="3"] .fl-node.n3 i::after{animation:cnIgnite 1.2s cubic-bezier(.2,.7,.2,1) .85s both}
@keyframes cnIgnite{0%{opacity:.95;transform:scale(1)}100%{opacity:0;transform:scale(2.2)}}
/* first use of a blur filter costs a shader compile and a raster pass: prime them once at load, invisibly, so the first flight is smooth */
#cine-fx .cn-prime{position:absolute;left:0;top:0;width:1920px;height:1080px;opacity:.004;filter:blur(8px) brightness(.58);animation:cnPrime .9s linear 2;background:linear-gradient(120deg,#0b1736,#2a63e6)}
#cine-fx .cn-prime b{position:absolute;left:300px;top:200px;width:780px;height:440px;border-radius:28px;background:#F3F6FA;filter:blur(9px);animation:cnPrimeB .9s linear 2}
#stage:not([data-scene="open"]) #cine-fx .cn-prime{display:none}
@keyframes cnPrime{from{filter:blur(0) brightness(1)}to{filter:blur(8px) brightness(.58)}}
@keyframes cnPrimeB{from{transform:perspective(1800px) translate(0,0) rotateX(0)}to{transform:perspective(1800px) translate(400px,-100px) rotateX(13deg) rotateY(-10deg)}}
.scene.cn-warm{visibility:visible!important;opacity:.004!important;transition:none!important}
.scene.cn-warm *{transition:none!important;animation-play-state:paused!important}
/* during a chain cut both scenes keep one raster each (no per-frame re-raster while they scale) */
:is(#s-problem,#s-evidence,#s-cause,#s-flow):is(.cn-out,.cn-in,.cn-dof){will-change:transform,opacity,filter}
